ScreenShootMe на 1 година

2 коментара

Публикувана на 01.08.2010 от Lucho в Dev |HTML5 |Web |Нонсенс

, , , ,

Преди около година сътворих едно малко уеб-туулче, което да позволява бързо качване на скрийншот в мрежата – ScreenShootMe. Очакванията ми да стана свръх богат и да задмина Facebook по потребители не се сбъднаха, но и първоначалната ми идея никога не е била тази, де. Подбудите да го създам тогава бяха, че такъв инструмент ми е нужен и има смисъл от него. Виждам смисъл в него и сега – 1 година по-късно. Първата му версия беше функционална – имаше това което исках, но нямаше това, което искаха останалите хора – хубав вид. За това докато пътувах в автобуса от Созопол към София с изтощена батерия на телефона и празен поглед забит в хоризонта, реших да подобря творението си – да го направя „красиво“. И не просто реших, ами помислих сериозно какво искам, помислих за всеки детайл, за цветове, разположение – за всичко. Когато се прибрах веднага започнах работа по него и след 4-5 дни бях завършил всичко, което ми се въртеше в главата докато пътувах в автобуса. Всички промени касаят клиентската част – нищо по сървърната част или в Applet-а не е пипано, което беше и първоначалната идея – все пак е само фейслифтинг.

Ето и списък с промените:

  • Разположението – меню с всички бутони и контроли в ляво, до менюто е платното, а под тях е информативен текст.
  • Менюто се дели на 4 части – бутони с основни функции, бутон и контроли за crop, бутон и контроли за рисуване върху платното (избор на дебелина и цвят на четката), поле за въвеждане на специфичен ключ (ключа се ползва в URL-a с изображението).
  • Информативния текст се дели да две паралелни колони, като в лявата има информация за функциите на уеб-туулчето, а в дясната има текст с общо предназначение.
  • Състоянието на кенвъса по подразбиране трябва да има рекламен вид – да казва колко е лесно и полезно туулчето.
  • Цветовете: Тъмно синьо, жълто, оранжево и бяло (за текста). Топлите и студени цветове, някак си противно на логиката, си паснаха. Тъмно синьото и бялото бяха първите два избрани цвят, които да си призная, разбрах че си пасват благодарение на това лого – http://screenshoot.me/7r04fQ . За оранжавото знаех, че е енергичен цвят, а за жълтото че прави много добър контраст с черно и тъмни цветове (освен това ми е любим). И така от цялата каша се роди една палитра, която е ЕДИНСТВЕНАТА свястна палитра, която някога съм подбирал.
  • Бутоните и контролите представляват Canvas елементи и са изцяло генерирани от Javascript. Един ден ще бъдат заменени от HTML5 Web Forms.
  • Наех домейн за уеб-туулчето – screenshoot.me
  • Donation бутонче – домейнът струва пари :-P
  • Футър
  • Undo – в случай, че нещо се обърка тотално.

Това „разкрасяване“ за пореден път подтвърди мнението ми, че хубавията дизайн се постига много по-трудно отколкото самата функционалност. Дано поне да си е заслужавало труда  и парите за домейн и да привлече повече потребители ;-)

  • Twitter
  • Facebook
  • HackerNews
  • Google Bookmarks
  • Suggest to Techmeme via Twitter
  • RSS
  • PDF
  • email

Бъдещето на телекомуникациите – Web Sockets

1 коментар

Публикувана на 22.03.2010 от Lucho в Dev |HTML5 |Web

, ,

Най-голямата спънка при разработката на богати уеб приложения до сега е липсата на двупосочна връзка – от клиента към сървъра и от сървъра към клиента. Решението на този проблем винаги е било голяма болка и страдания, като най-общо се ползват чести запитвания към сървъра, на които той в 90% от времето  връща празен response или Comet (познато още като long polling най-общо). И двата начина са тромави и ресурсоемки… даже бих ги определил като законни DoS атаки. И всичко това за да се симулира нещо подобно на двупосочна връзка.
Е, дните на безсмислени request-и и празни response-и отминаха, защото HTML5 предлага няколко варианта за решение на този казус. Ще се спра само на един от тях, на тъй наречените Web Socket-и. Както сигурно се досещате става въпрос за сокет съединения, макар и леко модифицирани и орязани, които могат да се създават и управляват чрез Javascirpt. Освен че тези web socket-и могат само да започват връзка, но не и да стоят и да слушат за постъпване на такава, те имат и собствен допълнителен протокол, с който си комуникират със сървърното приложение. Важното в случая е че дуплексна връзка има и то на много ниска цена (от към писане на код). При създаване на сокет се оказват callback функции за четене, възникване на грешка и отваряне/затваряне на връзката, така че когато някое от изборените събития се случи, тези callback функции се извикват и обработката на данни пада във вашите ръце. Това намалява драстично главоболията породени от блокиращи/неблокиращи сокети, безкрайни цикли, exception-и и какво ли още не.
От сървърна гледна точка нещата също са прости, кодът който е нужен за успешна комуникация с клиента е съвсем стандартен за сървърно сокет приложение, с изключение на едни служебни съобщения, които Web Socket-ите очакват и от които не може да се бяга.

Понеже всичко до сега звучи прекалено хубаво, ще се наложи да ви приземя малко, защото Web Socket-и за сега се поддържат само от Google Chrome, но рано или късно и другите browser vendor-и ще се усетят откъде духа вятъра. И понеже вече се приземихте ето и едно примерно приложение, което сглобих – MultiDraw. Идеята е чрез HTML5 Canvas елемента и Web Socket-и да се постигне паралелно рисуване от множество клиенти върху платно. Сървърната част е на Python 2.6 и ползва модула asyncore от стандартната библиотека, който симулира асинхронно четене и писане от сокети.

Ето кодът, който се отнася до web socket-ите при клиента:

var s = new WebSocket("ws://" + document.location.host + ":6789/");
// създаване на сокет съединение на порт 6789
s.onopen = function(e) { document.title = 'MultiDraw - Online'; }
// функция, която да се изпълни при установена връзка
s.onclose = function(e) { document.title = 'MultiDraw - Offline'; }
// функция, която да се изпълни при прекратяване на връзка
s.onmessage = function(e) {
// функция, която да се изпълни при пристигане на съобщение (съобщението е в e.data)
    var data = e.data.split(" "); // обработваме съобщението...
    draw(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); // ... и чертаем върху Canvas-а
}
...
s.send([x, y, e.pageX, e.pageY, color, brushSize, lineCap, lineJoin].join(' ')); // изпращане на съобщение

При сървъра, единственото по-екзотично е хендшейк съобщението и това, че всяко съобщение започва с нулев байт и завършва с 0xFF (може да го видите в кода на сървъра).

Кодът на клиента и сървъра е тук – http://gist.github.com/339983 .

Happy Web Socketing ;-)

P.S. Незнам дали забелязахте, ама редакторът на спецификацията за Web Socket-ите е „Ian Hickson, Google, Inc.“, така че няма нищо странно, че  тези чудесии се появяват именно в Chrome за първи път :-P

  • Twitter
  • Facebook
  • HackerNews
  • Google Bookmarks
  • Suggest to Techmeme via Twitter
  • RSS
  • PDF
  • email

FarmBot… или какво да правим докато нямаме личен живот

7 коментара

Публикувана на 10.03.2010 от Lucho в Dev |Web |Нонсенс

В последно време не съм писал нищо (става въпрос за писане на код) и взе да ми липсва… което май е нормално имайки предвид, че съм Софтуерен Инженер :-) . Та, много умувах какво да направя, първо бях решил да разширя ScreenShootMe с четка и възможност за писане, обаче това в някаква степен измества фокуса от основната идея на приложението и е трудоемко, а и искам FF да почне да поддържа colorpicker и slider функционалностите от HTML5, за да си спестя ненужни мъки. Впоследствие разбрах, че една колежка е 40 левъл в FarmVille… не че тя е единствената колежка, която играе FarmVille, но определено е висок левъл :-D . Понеже и аз имам фермичка се сетих, че всъщност в timeline-a на ФБ постоянно излизат съобщения за бонуси в FarmVille и част от тях си заслужават, но е досадно да си проверяваш нон-стоп ФБ за FV бонуси и да цъкаш по тях като ненормален. За това естествено тръгнах да мисля начин за автоматизация на процеса… за БОТ.

След нетолкова кратък рисърч, стигнах до извода че ФБ API-то може и да е удобно и лесно за ползване, но определено би отнело известно време, за да се свикне с него и за да се напише нещо такова, а и писането на PHP или друг скриптов език означава допълнителни constraints за обикновения юзър, който не е виждал програмен език в живота си или пък няма инсталиран нужния софтуер, за да подкара бота. От тук вече избора съвсем се стесни до… хм… Javascript и браузър.

v.0.1: Тръгнах да пиша един html файл, който да отваря ФБ в един фрейм и да парсва линковете за FarmVille… е не стана, незнам дали заради фроуд детекшън или заради нещо друго, но браузърите вече не дават да се бърника/чете html кода на страници в различни от настоящия домейн.

v.0.2: Същото важи и за отваряне на child прозорци и бърникане по техния код… god damn it… X_X

v.0.3: Докато търсех инфо за ФБ API-то попаднах на sandbox, в който може да се тестват разни функционалности – http://developers.facebook.com/tools.php и едно от нещата, които ми направиха впечатление, е че за изпълнение на request се ползва AJAX, a не просто постбек. Това естествено значи, че мога да напиша js код, който да се слага в addressbar-а или като bookmarklet и да обновява информацията през определено време, да я парсва и да отваря част от линковете в нови iframe-ове, което изпълнява целта напълно!

Моля, запишете си нужните продукти за да сготвиме бота :-)

1.  Логвате се в ФБ по стандартния начин

2. Отивате тук – http://developers.facebook.com/tools.php и избирате от падащото меню на Method > stream.get (това извежда timeline-a ви)

3. Copy/Paste кода по-долу в addressbar-a (за всички, които виждат браузър за първи път – после натиснете Enter)

javascript:
visited = {};

function process() {
    var code = document.getElementById('trace').innerHTML;
    var m = null;
    while (m = /\<href\>(http:\/\/apps\.facebook\.com\/onthefarm\/.+?)\<\/href\>/gi.exec(code)) {
        if (!visited[m[1]]) {
            var ifr = document.createElement('iframe');
            ifr.src = (m[1].replace(/&/g, '&')).replace(/&/g, '&');
            container.appendChild(ifr);
            visited[m[1]] = true;
        }
    }
    setTimeout('container.innerHTML = \'\'', 60*1000);
}

function refresh() {
    callMethod();
    setTimeout(process, 5*1000);
}

container = document.createElement('div');
document.getElementsByTagName('body')[0].appendChild(container);
setInterval(refresh, 120*1000);
void(0);

И така вашия бот би трябвало вече да е напълно оперативен (на български не звучи добре)!!!

Накратко какво прави кода – на всеки 2 минути обновява timeline-а и проверява дали има нови url-и, които да са за FarmVille. Ако има такива ги отваря в iframe-ове (все едно вие сте  цъкнали на „Get bonus“ линковете в ФБ). Може да го задействате навсякъде напрактика (освен ако не ползвате Mosaic) и да си събирате колектабълс или нафта или там каквото още имаше.

В заключение ще кажа, че докато четох повторно поста си осъзнах, че явно обичам да пиша глупави, безсмислени и непотребни приложения… или по-скоро ако трябва да избирам между направата на нещо смислено и нещо глупаво, май-май ще се спра на второто :-D … но пък това е в духа на блога ми все пак :-P

  • Twitter
  • Facebook
  • HackerNews
  • Google Bookmarks
  • Suggest to Techmeme via Twitter
  • RSS
  • PDF
  • email

TLA

2 коментара

Публикувана на 24.09.2009 от Lucho в Dev |Нонсенс

Ето някои абривиатури, които може и да знаете или да незнаете, кой знае…

ACID – Atomicity, Consistency, Isolation, Durability

CRUD - Create, Read, Update, Delete

DRY - Don’t Repeat Yourself

GNU – GNU is Not Unix (recursive acronym)

BSD – Berkeley Software Distribution

BashBourne-again shell

GPL – (GNU) General Public License

CRM – Customer Relationship Management

CMS – Content Management System

DTD – Document Type Definition

PHP - PHP: Hypertext Preprocessor (recursive acronym)

ASP - Active Server Pages

TDD - Test-driven development

BDD - Behavior Driven Development

REST - Representational State Transfer

SOAP – Simple Object Access Protocol

COTS - Commercial off-the-shelf

TFT – Thin-film transistor

LCD – Liquid Crystal Display

Естествено има още много, но според мен има голям шанс да незнаете някои от тези, а пък се срещат тук-таме :-P

  • Twitter
  • Facebook
  • HackerNews
  • Google Bookmarks
  • Suggest to Techmeme via Twitter
  • RSS
  • PDF
  • email

Share your screen

4 коментара

Публикувана на 22.08.2009 от Lucho в Dev |Firefox |HTML5 |Web |Нонсенс

Напоследък съм изгубил творческата си искра, в работата се занимавам с .NET 2 (нестига, че е .NET ами и е от 2004г :-( ) не съм почивал цяло лято и ми се ще да пиша на Ruby и Rails или Objective C за iPhone. Та сред всички тези несгоди и поради факта, че съм програмист все пак (а добрите програмисти решават проблеми ежедневно и би трябвало и своите да могат да решат!!!) предприех някои стъпки за измъкване от блатото, като една от тях беше да си пиша малко проектче за мое лично удовлетворение. Първоначалната идея изникна в главата ми по напълно случаен начин, с времето идеята се развиваше и променяше, пишех по малко код и очаквах вдъхновението ми да се върне и да ми каже какво да правя… е този момент дойде днес – тази вечер.

Първоначалната ми идея, с която няма да ви занимавам сега, включваше използване на HTML 5 Canvas – платно на което може да се рисува и дава пълен достъп до битмапа – красота! Естествено този стандарт е все още слабо разпространен сред браузърите, защото е нов (Microsoft-ския Trident още не го подържа изобщо, бахти изостаналата нация :-P ). Идеята включваше и Рейлс, но прагматичното в мен победи и пожела да запълня 99% свободен bandwith на хостинга ми (да, блога ми е толкова популярен, че ползвам <1% от линията :-( ). Това води след себе си сравнително неприятното задължение да пиша на PHP… но няма да се лъжем, на PHP се пише много бързо, ама много, много бързо и грозно и… абе селска работа! Предните седмици, докато чаках вдъхновението, реших да проуча въпроса, как мога да взема изображение от клипборда и да го плесна на кенвъса, оказа се нетолкова лесна история, но възможна все пак. Цената не е прекалено висока – ползвам Java Applet-че, което върши цялата работа всъщност. Алтернативата е Flash, но доколкото разбрах Flash 10 налагал по-строги ограничения за боравене с клипборда, а и не обичам Flash и ActionScript (винаги ме е боляло много след интервенция с тях). Големият проблем е, че някъде при прехвърлянето на битмапа от клипборда през аплета към javascript-ския код нещата стават много бавно и това може да отнеме до няколко секунди, за по-големи изображения, но като се абстрахираме от това – ТО РАБОТИИИИ!!!! Следващото нещо, което направих е функционалност за селектиране на фрагмент от кенвъса, почти като в Paint или друг редактор… и в общи линии до тази вечер бях стигнал до тук, когато ме осени идеята – selection tool-а става на crop tool и целия проект се превръща в 3-click-screen-share. Гениално наистина, print screen, paste, [optional: crop], save и получаваш линк… а и подобно нещо не съм виждал да има досега… е друг е въпросът колко често на човек му трябва подобно нещо, но като се замисля, че иначе трябва да отваряш image editor, пък после да save-ваш, пък после да го публикуваш някъде, и накрая да пратиш линк – it is retarded!

Първоначалната версия на услугата е тук: http://dailyffs.com/shotme/

За сега всички енджини без този на Microsoft подържат в някаква степен Canvas, като за FireFox 3.5 приложението върви на 100%. Естествено за view на изображението впоследствие не е необходимо нищо специално и всеки браузър би свършил работа, така че всички ще могат да видят скрийншота ви – спокойно ;-)

Ако някой има предложения или поне му е харесала идеята или пък го е отвратила, може да напише мнението си тук. Чуждият фийдбек е стимул, стимул за подобряване, изпипване и разширяване на идеята. Ако има интерес ще наема нов domain и ще се постарая да оправя забавянията, да сложа една четка, че да може да оградите примерно определено място от изображението, на което искате да наблегнете.

Хубаво е когато човек дава свобода на въображението и творчеството си, кара те да се чувстваш щастлив и да си изпълнен с идеи и енергия… даже и цената, която трябва да платиш да е малко писане на PHP :-P

  • Twitter
  • Facebook
  • HackerNews
  • Google Bookmarks
  • Suggest to Techmeme via Twitter
  • RSS
  • PDF
  • email

Дългият път на съзиданието

1 коментар

Публикувана на 06.07.2009 от Lucho в Dev |Нонсенс

Често обичам да не документирам, да не описвам нещата които правя… понякога съжалявам за това. И не толкова че видите ли след 5 години ще съм забравил за какво е бил даден проект, а по-скоро защото не записвам яките моменти, които съм преживял докато съм го разработвал.

Ето, сега ще се поправя и ще опиша стъпките, идеите, мислите, абе всичко през което минавам докато дивелъпвам проекта си по Python. В този смисъл постът, който четете в момента ще се допълва ежедневно с новости, за това стей тюнд.

Проекта представлява конзолен mp3 плейър за Линукс (уж Python е портабъл… но аз не го вярвам това, за сега :P ), като интерфейсът ще е тип „стара дос програма“ – графичен интерфейс с ascii символи. Надявам се, освен стандартните за всеки mp3 плейър нещица, да успея и да го накарам да работи с онлайн радиа (streaming). Естествено в момента си поставям цели, за които не съм напълно убеден дали ще са реализуеми… но какво пък – ще опитам! Друг фичър, който много искам да направя е да минава в бекграунд режим, за което имам някакви идеи, но пак неизвестните са доста.

Естествено вече съм попрегледал какви благинки предлага Python и какви външни компоненти (ех, колко SE  звучи това) бих могъл да ползвам. За нещастие, част от нещата изглежда са за Python 2.5, но докато неразцъкам и това твърдение е в сферата на unknown-ото.

Day 0:

И така „дей 0″ е по-скоро „вечер 0″, бутнах се под Убунтуто си и си сложих Eric (IDE за Python). Доста бутони, доста функции, дано да се работи приятно с това нещо. Тръгнах да създавам нов проект и се сетих – нямам име за него. Е… след 15 секундно размишление се спрях на „Pyp3″ („пай-пи-три“). И така вече съм готов да започвам най-нелепата част… подкарване на някой от основните модули които ще ползвам. За съжаление не намерих нищо,  което да пуска звук и да е за Python 3, така че ще се пише на Python 2.5. Това всъщност не е толкова зле, защото:

А) Рано или късно ще портнат библиотеките до 3

Б) Python 2.5 е стандартна версия за всяко Убунту и други дистрибуции

Та инсталирах audiere и numpy (дипенденси) от репобраузъра и успешно пуснах една mp3-ка (чак да не повярва човек :D ). Следваща стъпка е да разцъкам curses – нещото, което осигурява ascii интерфейса.

След един час четене не умопомрачително дългия менюъл на curse и малко конзолно тестче стигнах до следните два важни извода:

1. Curse няма готови диалогчета (за open file например) – селско (все пак има надежда, че някъде някой е написал нещо по въпроса)

2. Терминалите не са това което бяха. На 22 инчов монитор в текстов режим имам 48 реда по 136 колони, в графичен много повече… къде изчезнаха добрите стари 80×25. Може би са изчезнали заедно с DOS, кой знае :D . На малкия ми латоп (резолюция 1024х600), в текстов режим конзолата е баш 80х25 реда. Т.е. нищо не изглежда както трябва – неприятно.

Друг проблем е че трябва да поддържам доста диалогови прозорци и мишка. Решението може би е тази надстройка на curses – Urwid, която ще спести излишното копане за диалози.

Интерфейса, който за сега ми се върти в главата включва тикер за текуща песен, скролче за звука, бутони add, rem, jmp, que, ext, bkg (добавяне/махане на песен, jump по име – включва диалог, que – включва диалог, exit и преминаване в background режим), текуща плейлиста (в общи линии списък със заглавия).

Day 1:

Продължих да разцъквам Urwid и като цяло съм доста доволен. Направих прототип на плейлиста, но изникна нов проблем. В плейлистата човек може да има хиляди песни и е нормално да има скролбар, само че скролбара е фиксиран от броя редове в терминала (това значи, че е ограничен по брой позиции, на които да се мести), което неминуемо води до проблем че при преместване на скролбара с една позиция, в листата може да бъдат скипнати повече записи отколкото може да покаже. Ще се получи „прескачане“, което ще е по-скоро дразнещо от колкото полезно. Поради този факт (и това че скролбар не е имплментиран в Urwid официално :-P ) обмислям вариант да мина без скролбар, а по-скоро с филтър, който да филтрира песните по част от име и да сложа поле, което да показва на кой номер песен (страница) е плейлистата в момента. Това би помогнало и за реализацията на Jump функционалността, като просто се филтрира по ключова дума и се натисне някаква клавишна кобмбинация… нийййт. Вечерта завърши с Пранка :-)

Day 2 & 3:

За тези два дни горе-долу направих плейлистата и филтрирането и леко се отчайвам от скоростта с която напредвам, а ми предстой да свържа кода за directory browsing с плейлистата. Все пак все повече ми се избистрят идеите в главата, така че може да се каже че положението не е толкова критично. Дано дедлайна не ме притисне много…

Day 4:

Интегрирах кода за браузване из файловата система с плейлистата и добавих код за плейване на аудио файлове – даже пуснах няколко (big success)! Вече съм една идея по-спокоен, защото имам нещо работещо. И все пак ми остава queue функционалността на плейлистата, което няма да е толкова прозрчано и просто. Чудя се дали да не напиша малко тестове и паралелно с това да не рефакторна кода на няколко места, може би е добра идея (Както се вижда съм скептик относно предварителното писане на тестове… а по принцип съм скептик и относно писането на тестове ИЗОБЩО, но се старая да променя това!!!). Намерих още една библиотека, която би била полезна в проекта – Mutagen, служи за четене на тагове от разнообразни аудио формати и ще ми помогне с title/author в плейлистата.

Day 5 & 6:

Уж беше събота и неделя, а свърших доста малко неща. Все пак позавърших изгледа на плейъра и четенето/показването на ID3 таговете. Реших да отложа правенето на опашка, защото е мега досадно и не е толкова фън, колкото плейването на стрийминг и рънването в бекграунд. Плейването на стрийминг се оказа доста нетривиална задача, която ми отвори един куп проблеми, та и там нещатата не са розови. Трябва да почна да пиша тестове… ех тези ш****и тестове…

Day 7 & 8:

Оказа се, че Audiere е тотално скаран с всичките ми идеи да го подкарам с http стрийм… то не бяха наименовани пайпове, сокети, даже се мъчих да му вкарам numpy-ски масив от float32, но след дълги среднощни борби реших да се преориентирам към GStreamer, който е бая тежко, по-точно обемно нещо, и много исках да не опирам до него. За това пък плейва без грижи само като му се даде URI. Отначало исках да ползвам Audiere за плейване на локални файлове и Gstreamer за уеб стрийминг, но освен че е доста грозно решение, срещнах трудности в освобождаването на заетия аудио ресурс когато искам да подменя on-the-fly библиотеката. По-точно Audiere освобождаваше веднага всичко, но на GStreamer му отнемаше поне 5-6 секунди и switch-ването помежду им не ставаше гладко. В резултат на това се наложи да си напиша адаптор към GStreamer от стария код за плейване на фиайлове, който ползваше Audiere. Беше кървава баня, но се справих, даже промените по интерфейса бяха почти незначителни. За съжаление GStreamer е слабо документиран също, макар че има туториали, но референса (вкл. и този, който е в интерпретатора) е много постен. Голяма мъка беше, но сега поне мога да плейвам радио :-)

Day 9:

Гледах Ледена Епоха 3 (3D), но не беше нещо особено. Поради този факт не свърших много – оправих цветовата схема на плейъра, проведох задълбочен рисърч за пускане на application в background, който не доведе до никакви реални резултати. Впоследствие открих workaround – просто трябва да се пусне плейъра във втори терминал (ctrl+alt+f[1..6]) и да се switch-ва в него като трябва да се контролира pyp3. Останаха ми още два малки таска и после тестове.

Day 10:

Добавих възможност за конфигуриране на outlook-а на плейъра, като се опишат цветовете на отделните части от ascii интерфейса в конфигурационен файл. Готино е когато нещата са максимално customisable. Сложих и event handler, който да следи по кутлурен начин дали дадена песен е свършила. Това ми отне сумати време, защото няма кой знае колко полезно инфо в нета… или трябва да падне голямо четене, докато се разбере по-точно. Много мразя, когато се занимавам с непопулярни неща, защото са слабо документирани и само ми късат нервите! Освен това в крайна сметка при четене от online stream не пристига event за край на stream-а ако се прекъсне връзката, което е хипер малумно, защото на това се надявах най-вече :( . Оправих разни бъгове и с това приключвам официално работа по Pyp3 (е имам да пиша тестове, но за тях няма да блогвам).

Final Conclusion:

Използвани компоненти: GStreamer, Urwid, Mutagen, Audiere (GStreamer-а го замени впоследствие)

Функционалност:

- плейване на файлове и стрийминг

- филтриране, jump, add/del, select, directory browsing dialog (само интегриране)

- auto save/load на плейлистата и цветовата гама на плейъра

- play/pause/stop/next/prev, fastforward/slowbackward ( :-D ), ID3 tags, текущо време на плейване, state на плейъра, volume

- autoplay next track, autoreconnect to stream on lost connection

След една камара време и безсъние резултата не е чак толкова грандиозен, но това се дължи основно на факта, че падна голяма борба заради слабите документации и защото трябваше да switch-на от Audiere към GStreamer. Съответно голяма част от времето отиде за направата на, иначе, не особено сложни неща.

Неща за които не ми стигна времето:

- Queue – малко ме е яд за това, защото има полза от опашка

- Rating – не ползвам такива неща… но може да има смисал

Все пак от много време не бях писал нещо, което да ми е на сърце и да ме ентусиазира, така че, въпреки всички трудности съм happy :-)

pyp3

  • Twitter
  • Facebook
  • HackerNews
  • Google Bookmarks
  • Suggest to Techmeme via Twitter
  • RSS
  • PDF
  • email

The King of Quines

0 коментара

Публикувана на 05.05.2009 от Lucho в Dev

Quine не е миспелнато Queen, а програма, която извежда сама себе си и се надявам не само мен ме freak out-ва това. Все едно някой андройд да разбере, че не е човек, а машина. Почти толкова тъжно е както когато малкото роботче в AI на Спилбърг отчаяно искаше да намери феята, за да го превърне в истинско момче и майка му да го обича… драма драма.

За типичния Quine е удобно да се ползва printf-оподобни функции, които да имат еднакъв форматиращ низ и аргумент за форматирането. По този начин се получава нещо като вложено построяване на низа за печатане. Друг подход е функционалния, който е представен по-надолу (Javascript частта).

Предполагам, че все още на никой нищо не му е ясно и тъй като не мога да направя по-дълго отрицание от това, ето няколко варианта написани на някои от скриптовите езици, с които съм имал вземане-даване (популярните езици изискващи компилация имат твърде дълги Quine-ита).


Python

_='_=%r;print(_%%_)';print(_%_)

Какво прави кода: записва в променливата _ форматиращия низ, като %r значи да се изведе repr на обекта (това ще изведе текстово представяне на обекта, ако обекта е низ ще изведе и единични кавички), а %% е escape-ване на %. После се извиква print, като се форматира низът от _ сам със себе си (%).

_=’_=%r;print(_%%_)’;print(_%_) -> _=‘_=%r;print(_%%_)’;print(_%_)


Ruby

_="_=%p;puts _%%_";puts _%_

Какво прави кода: прави същото, което и горния код, но тук вместо %r имаме %p, функцията за отпечатване се казва puts и нямаме нужда от скоби за извикването на функция (обичам Ruby).


PHP

<?php $f='<?php $f=%c%s%c; printf($f,39,$f,39); ?>'; printf($f,39,$f,39); ?>

Какво прави кода: да, познахте, кода прави същото, което и предните два, с тази разлика, че php изисква допълнителен незначещ crap, който да се зарови около кода (<?…), печатащата функция е printf, която има синтаксис сходен с printf от C, а за да оградим резултата в единични кавички се изписва ascii символ 39, което както се досещате е единична кавичка.


Javascript

( function (x) { return "(" + x + ")(" + x + ")"; } )( function (x) { return "(" + x + ")(" + x + ")"; } )

Какво прави кода: тук става вече по-интересно, защото кода не прави това, което предните 3 функции правеха. Записа много прилича на Quine на Scheme и да си призная една част от него е загадка за мен (например защо като подадем като параметър на функция друга функция, получения аргумент е записа/кода на подадената функция, а не обект с адрес. Може това да е представянето, незнам). Първо и двете анонимни функции са еднакви, като втората е аргумент на първата и при изпълнение ще се запише два пъти със скоби отляво и отдясно, което е и изходния запис. Скобите са нужни, за да окаже in-place изпълнение на първата анонимна функция и че втората анонимна функция е аргумент на първата. Може да пробвате този код като го напишете в адресната лента на browser-а си (тествано с FireFox):

javascript: ( function (x) { return „(“ + x + „)(“ + x + „)“; } )( function (x) { return „(“ + x + „)(“ + x + „)“; } )


  • Twitter
  • Facebook
  • HackerNews
  • Google Bookmarks
  • Suggest to Techmeme via Twitter
  • RSS
  • PDF
  • email

Switch to our mobile site