Kategoria: Na każdy temat

W dziale „Na każdy temat” umieszczam różne wpisy nie będące pełnymi artykułami. Są to różne ciekawostki, skrypty oraz sposoby rozwiązywania różnych problemów informatycznych.

Wprowadzenie do Laravel Dusk

Czym jest Laravel Dusk

Laravel Dusk jest narzędziem do automatyzowania przeglądarki i testowania stron budowanych w Laravelu. Narzędzie to uruchamia i steruje ChromeDriver, dzięki czemu mamy możliwość automatycznego testowania naszych aplikacji w przeglądarce.

Test-driven-development w Laravel Dusk

Test driven development to technika tworzenia oprogramowania, która opiera się na cyklu trzech następujących po sobie czynności: test czerwony -> test zielony -> refactoring. Więcej informacji na temat TDD można znaleźć w sieci, ja natomiast polecam książkę „TDD. Techniki programowania sterowanego testami” Dariusza Woźniaka, kod tej książki jest pisany w C#, ale zawarte w niej informacje są uniwersalne dla wszystkich języków programowania.

Dla potrzeb naszego artykułu musimy o TDD wiedzieć tyle, że najpierw piszemy test który zakończy się niepowodzeniem, później piszemy kod który powoduje że test kończy się powodzeniem, następnie robimy refactoring i przechodzimy do pisania kolejnego testu, tym samym zapętlając cykl.

Instalacja Laravel Dusk

Tworzymy standardowy projekt w laravelu: tworzymy nowy projekt, konfigurujemy dostęp do bazy danych, uruchamiamy migracje. Następnie przechodzimy do katalogu projektu i wykonujemy poniższe czynności.

Na początek instalujemy Laravel Dusk przy pomocy composera:

composer require --dev laravel/dusk

Następnie wykonujemy polecenie, które integruje Laravel Dusk z naszym projektem:

php artisan dusk:install


Od tego momentu możemy wykonywać testy poleceniem:

php artisan dusk


Jeśli na swoim komputerze napotkasz problemy z wersją ChromeDriver, użyj poniższego polecenia aby użyć innej wersji:

php artisan dusk:chrome-driver 74

(74 to numer wersji ChromeDriver)

Dodatkowo można przyznać odpowiednie uprawnienia, wykonując polecenie:

chmod -R 0755 vendor/laravel/dusk/bin/

Pierwszy Test

Załóżmy że w naszej aplikacji będzie strona profilowa pod adresem /profile.

Tworzymy test poleceniem:

php artisan dusk:make ProfilePageTest

Zostanie utworzony plik tests/Browser/ProfilePageTest.php a w nim klasa testów ProfilePageTest. Dodajmy do tej klasy pierwszą metodę testującą:

public function testIfProfilePageHasHeader()
{
    $this->browse(function (Browser $browser) {
        $browser->visit('/profile')
                ->assertSeeIn('h3.page-title', 'My Profile');
    });
}

Powyższy test uruchamia przeglądarkę (przeglądarka jest “headless” więc jej nie zobaczymy, gdyż działa w tle). W przeglądarce odwiedzany jest adres /profile a następnie sprawdzane jest czy na stronie istnieje element h3 z klasą css page-title, zawierający tekst “My Profile”.

Tutaj mała uwaga: nasza aplikacja musi być uruchomiona, żeby testy zadziałały, czyli najpierw uruchamiamy php artisan serve (lub serwujemy ją z serwera) i dopiero wtedy w drugiej konsoli odpalamy:

php artisan dusk

Test zwróci błąd, ponieważ strona /profile nie istnieje. Zróbmy prostą “zaślepkę” tej strony w pliku routes/web.php

Route::get('/profile', function(\Illuminate\Http\Request $request) {
    return '<h3 class="page-title">My Profile</h3>';
});

Po dodaniu powyższej reguły routingu test się wykona, ponieważ strona istnieje i zawiera element oczekiwany w teście.

Drugi test: sesja użytkownika

Strona profilowa zapewne będzie dostępna tylko dla zalogowanych użytkowników. Napiszmy kolejny test, który sprawdza, czy na stronie istnieje element h4 zawierający nazwę zalogowanego użytkownika.

public function testIfProfilePageShowsUserName()
{
    $this->browse(function (Browser $browser) {
        $user = User::find(self::TEST_USER_ID);
        $browser->loginAs($user)
                ->visit('/profile')
                ->assertSeeIn('h4', $user->name);
    });
}

Powyższy kod zwraca z bazy danych encję użytkownika, id użytkownika jest brane w tym przypadku ze stałej TEST_USER_ID, możesz ją dodać w pliku tests/Browser/ProfilePageTest.php lub tests/DuskTestCase.php, decyzję zostawiam Tobie. W moim kodzie stała jest zdefiniowana następująco: const TEST_USER_ID = 596, w bazie mam dodanego użytkownika o id = 596.

Uruchamiamy testy, powyższy test oczywiście kończy się niepowodzeniem, ponieważ nasza strona nie zawiera elementu h4 z nazwą użytkownika, zmieńmy więc nasz kod routingu do następującej postaci:

Route::get('/profile', function(\Illuminate\Http\Request $request) {
    $user = Auth::user();
    return '<h3 class="page-title">My Profile</h3>' .
           (empty($user) ? '' : '<h4>' . $user->name . '</h4>');
});

Po ponownym uruchomieniu testów, otrzymamy prawidłowy wynik, ponieważ powyższy kod pobiera zalogowanego użytkownika i wstawia jego nazwę do elementu h4.

W tym momencie należy przejść do refactoringu, na początek proponowałbym przenieść kod z routingu do kontrolera i widoku. Następnie można napisać kolejny test dla strony /profile lub stworzyć klasę testów dla kolejnej strony.

Usprawnienia testów: strony

Laravel Dusk zawiera funkcjonalność Pages, która pozwala nam stworzyć klasę definiującą zadania, które chcemy wykonać na danej stronie podczas jej testowania. Klasa Page pozwala również zdefiniować skróty do różnych selektorów. Więcej na ten temat znajdziecie w sekcji Pages w dokumentacji Laravel Dusk, ja pokażę tylko jak przerobić nasz test, żeby używał klasy zamiast stringa z urlem ‘/profile’.

Na początek tworzymy klasę stronypoleceniem:

php artisan dusk:page Profile

Klasa Profile zostanie utworzona w pliku tests/Browser/Pages/Profile.php, jedyną rzeczą którą musimy w niej zmienić to wartość zwracana z metody url():

public function url()
{
    return '/profile';
}

Następnie w naszych testach zamieniamy wszystkie wystąpienia ->visit(‘/profile’) na ->visit(new Profile) i dodajemy instrukcję use Tests\Browser\Pages\Profile;

Wykonujemy testy, żeby potwierdzić że nic nie popsuliśmy. Działa!

Testowanie z Laravel Dusk
Testy napisane w Laravel Dusk i przykład pomyślnie wykonanych testów

Co się zmieniło? Na tym etapie nic, testy sprawdzają dokładnie to samo co wcześniej i zwracają ten sam wynik, ale dzięki użyciu klasy Tests\Browser\Pages\Profile mamy możliwość tworzenia kolejnych testów w bardziej zorganizowany sposób. Dodatkowo sama klasa zawiera asercję sprawdzającą czy po nawigacji do strony /profile strona ta faktycznie się otwiera.

Dalsze możliwości

Opisane powyżej działania to tylko podstawa żeby zacząć przygodę z testowaniem przy pomocy Laravel Dusk, możliwości tego narzędzia są jednak dużo większe. Dusk udostępnia bogatą paletę metod do interakcji z interfejsem użytkownika a nawet testowanie komponentów VueJs. O testowaniu interfejsu użytkownika opowiem więcej w osobnym artykule. Zachęcam do zapoznania się z wszystkimi możliwościami interakcji na stronie https://laravel.com/docs/6.x/dusk#interacting-with-elements

Przykład z życia

Dostałem do przepisania działającą aplikację zawierającą masę legacy code. Postanowiłem napisać kod od zera, ale z zachowaniem istniejącej struktury adresów url, endpointów API, tabel w bazie danych. 

Przepisywanie kodu metoda po metodzie jest kiepskim pomysłem, ponieważ chcemy stworzyć aplikację o tych samych funkcjonalnościach ale z dużo lepszym kodem odpowiadającym współczesnym standardom kodowania, z wykorzystaniem wzorców projektowych oraz dostępnych w Laravelu rozwiązań. Przyjąłem więc plan zakładający użycie Laravel Dusk do sprawdzenia czy wszystkie funkcjonalności w nowej aplikacji odpowiadają funkcjonalnościom ze starej. Praca nad projektem zaczęła się więc od stworzenia zestawu testów sprawdzających czy wszystkie strony zawierają wymagane elementy, w kolejnych etapach powstaną testy sprawdzające czy odpowiednie dane pojawiają się na stronach i czy interakcje z elementami na stronie działają zgodnie z założeniami. Dopiero po stworzeniu tego zestawu testów przystąpimy do tworzenia kodu. 

Inne podejście, przez wiele źródeł traktowane jako lepsze, zakłada pisanie pojedynczego testu i zaraz po nim kodu, ja jednak zdecydowałem się napisać najpierw pełny zestaw testów, aby móc rozdzielić pracę nad poszczególnymi modułami na różnych programistów i samemu, jako team leader sprawdzać postęp prac nad kodem.

Oczywiście testy pisane w Laravel Dusk należy traktować jako funkcjonalne i integracyjne, ich pisanie nie zwalnia to programistów z obowiązku pisania testów jednostkowych.

 

Odtwarzacz radia internetowego w Python dla Raspberry Pi

Radio

Któż nie lubi posłuchać radia, jedni słuchają dla muzyki, inni dla informacji, a jeszcze inni po prostu włączają radio jako tło. W dzisiejszych czasach nie jesteśmy już ograniczeni tylko do stacji radiowych, które odbiera nasz odbiornik fm, możemy słuchać audycji z całego świata. W niniejszym artykule pokażę jak zbudować swój własny odbiornik radiowy działający na mini-komputerze Raspberry Pi, sterowany przez przeglądarkę z dowolnego urządzenia w sieci wi-fi. Sercem systemu będzie aplikacja w języku Python.

Czego użyjemy

Na początek wystarczy Raspberry Pi z systemem Raspbian i podłączone do niego słuchawki, na końcu artykułu przedstawię możliwości rozbudowy naszego radia.

Kod źródłowy napiszemy w języku Python 3, do stworzenia prostego interfejsu webowego wykorzystamy framework Flask, zaś za odtwarzanie dźwięku odpowiadać będzie aplikacja Music Player Daemon (mpd) oraz prosty interfejs konsolowy o nazwie mpc. Lista stacji radiowych będzie pobierana z pliku YAML.

Instalacja zależności

Aby zainstalować wszystkie potrzebne narzędzia w systemie Ubuntu lub Raspbian należy wykonać polecenia:

sudo apt-get update
sudo apt-get install mpd mpc python-pip
pip install -U Flask oyaml

Kodujemy

Stwórzmy katalog w którym będzie się znajdował nasz projekt a w nim plik main.py.

W pliku main.py utwórzmy klasę i stwórzmy jej obiekt:

class Radio:
    def __init__(self):
        None

radio = Radio()

Następnie dodajemy metodę odpowiedzialną za komunikację z daemonem mpd:

def mpcCommand(self, cmd):
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
    return p.stdout.read()

Możemy już w tym momencie spróbować odtworzyć pierwszy stream dodając w metodzie __init__() kod:

self.mpcCommand(["mpc", "add", "http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-einws"])
self.mpcCommand(["mpc", "play"])

Zaimportujemy też moduł subprocess:

import subprocess

Po wykonaniu aplikacji stream zacznie się odtwarzać, a aplikacja się zakończy. Aby zakończyć odtwarzanie musimy w konsoli systemowej wykonać polecenie mpc stop.

Jeśli wykonamy polecenie mpc playlist, zobaczymy że do naszej playlisty została dodana stacja „http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-einws”. W celu uproszczenia komunikacji naszego skryptu z mpd, przed każdym rozpoczęciem odtwarzania będziemy czyścić listę i dodawać wybraną przez nas stację. Implementacja sprowadza się do dodania linii self.mpcCommand(["mpc", "clear"]) przed innymi wywołaniami self.mpcCommand(). Dodatkowo na końcu naszej metody __init__(self) możemy dodać:

while True:
  None

Spowoduje to, że aplikacja będzie uruchomiona dopóki nie przerwiemy jej działania, na przykład kombinacją klawiszy CTRL+C. Przerwanie pracy aplikacji nie spowoduje jednak przerwania odtwarzania strumienia przez demon mpd, dlatego musimy dodać metodę exitHandler() oraz zadeklarować jej wywołanie po zakończeniu aplikacji.

Dodajemy moduł atexit:

import atexit

oraz metodę:

def exitHandler(self):
    self.mpcCommand(["mpc", "stop"])
    self.mpcCommand(["mpc", "clear"])

Jak widać metoda zatrzymuje odtwarzanie i czyści playlistę. Aby python wykonał tą metodę po zakończeniu aplikacji, należy metodzie __init__() dodać linijkę:

atexit.register(self.exitHandler)

Linia ta musi być umieszczona przed pętlą while True.

Kolejnym krokiem będzie wczytanie listy stacji z pliku YAML. Przykładowy plik znajduje się tutaj, natomiast jego wczytanie wygląda następująco:

stationsFile = open("stations.yml", "r")
data = yaml.load(stationsFile)

self.stations = []

for k in data:
    self.stations.append({
        "name": k,
        "url": data[k]
    })

Powyższy kod wczytuje zawartość pliku, ładuje go do zmiennej data a następnie tworzy listę słowników self.stations. Aby kod zadziałał musimy dodać jeszcze jeden moduł:

import oyaml as yaml

Użyłem oyaml zamiast PyYaml, ponieważ PyYaml nie zawsze wczytuje listę stacji w takiej kolejności jaką ustaliliśmy w pliku .yml, oyaml rozwiązuje ten problem.

Następnie usuwamy pętlę while True a zamiast niej wstawiamy kod:

self.initWebUi()

Jest to wywołanie metody, której definicja wygląda następująco:

def initWebUi(self):
    app = Flask(__name__, template_folder="template")

    @app.route("/", methods=["GET", "POST"])
    def control_page(title="Radio control"):
        if request.method == "POST":
            if request.form["submit"] == "Play":
                self.currentStationUrl = str(request.form["station"])
                self.mpcCommand(["mpc", "clear"])
                self.mpcCommand(["mpc", "add", self.currentStationUrl])
                self.mpcCommand(["mpc", "play"])
            elif request.form["submit"] == "Stop":
                self.mpcCommand(["mpc", "stop"])

        return render_template("/control.html", title=title, stations=self.stations, currentStationUrl=self.currentStationUrl)

    app.run(host="0.0.0.0", port=1234)

Dodajemy też moduły:

from flask import Flask
from flask import render_template
from flask import request

Metoda initWebUi() inicjuje framework flask i definuje prosty routing wewnątrz którego jest akcja control_page wyświetlająca szablon z pliku template/control.html oraz obsługująca komendy „Play” i „Stop”. Plik szablonu znajduje się tutaj.

Dodatkowo w metodzie __init__() musimy dodać:

self.currentStationUrl = None

W tym momencie możemy otworzyć w przeglądarce adres http://0.0.0.0:1234/ i zobaczymy prosty panel pozwalający na wybór stacji i rozpoczęcie lub zatrzymanie odtwarzania.

Pełny kod aplikacji umiesciłem się w repozytorium na GitHub https://github.com/jakubthedeveloper/PythonInternetRadio, znajduje się w nim kod z artykułu z kilkoma usprawnieniami, na przykład możliwość podania w argumentach wywołania skryptu adresu i portu na którym ma działać nasze webowe UI. W pliku README.md znajdziemy również informację jak uruchomić projekt na mini-komputerze Raspberry Pi.

Dodatkowo kod w repozytorium został zrefaktoryzowany, poszczególne funkcje zostały przeniesione do odpowiednich klas, dodałem też unit testy.

Rozwój projektu

W momencie gdy na słuchawkach podpiętych do Raspberry Pi słyszymy stację radiową wybraną w naszym webowym interfejsie mamy doskonały punkt wyjścia, żeby zbudować coś ciekawszego. Kilka pomysłów:

  • Możemy użyć zewnętrznego głośnika, np. połączonego z Raspberry przez bluetooth
  • Możemy użyć nakładki wzmacniacza audio dla Raspberry Pi i podłączyć dowolny głośnik
  • Możemy użyć starego radioodbiornika, z którego wymontujemy całą elektronikę a w jej miejsce wstawimy Raspberry i moduł wzmacniacza podłączony do głośnika, który służył w wykorzystanym urządzeniu.
  • Możemy do naszej konstrukcji wstawić powerbank i uczynić ją bardziej przenośną
  • Możemy zamienić interfejs webowy na bluetooth i stworzyć interfejs mobilny na Androida lub iOS, w ten sposób naszym radiem będziemy mogli sterować nawet tam gdzie nie mamy dostępu do sieci Wi-fi
  • Możemy stworzyć fizyczny interfejs dla naszego radia, zawierający takie elementy jak: przyciski do wywoływania zdefiniowanych stacji radiowych, wyświetlacz wyświetlający nazwę aktualnej stacji, kontrolę głośności (można to zrobić przez komendę `mpc volume [+-]<num>` lub sprzętowo), kontrolę tonów niskich/wysokich.
  • Można zbudować old-schoolowo wyglądające urządzenie, na przykład używając obudowy i głośnika z radioodbiornika Unitra Kasprzak
  • Można zbudować futurystycznie wyglądające urządzenie, na przykład budując panel przypominający kokpit statku kosmicznego

Zachęcam do eksperymentowania i podsyłania waszych realizacji.

Aktualizacja

Już po napisaniu powyższego artykułu dokonałem wielu modyfikacji, które znajdziecie w repozytorium projektu. Jedną z nich jest modyfikacja interfejsu webowego z wykorzystaniem Bootstrap i jQuery:

Przykład użycia

Moje radyjko zbudowane z wykorzystaniem rozwiązania przedstawionego w niniejszym artykule opiera się na następującej architekturze:

Powiadamianie o nowej poczcie z Arduino

Eksperyment

Mieszanie kreatywności z nudą i odrobiną wolnego czasu bywa zaskakujące w skutkach, u mnie dziś taka mieszana zaowocowała urządzeniem, które pokazuje powiadomienie o nieprzeczytanej poczcie w postaci ikony koperty narysowanej flamastrem na kawałku tektury, powiadomienie wyskakuje zza monitora po nadejściu nowej wiadomości i chowa się gdy wszystkie wiadomości są przeczytane.

Tutaj możecie zobaczyć urządzenie w akcji:

Architektura

Do zbudowania „powiadamiacza” użyłem:

  1. Arudino Duemilanove
  2. Kontrolera serw PCA9685
  3. Serwa TowerPro MG996

Kod jest napisany w:

  1. Język C dla Arduino
  2. Python 3 do sprawdzania poczty.

Kompletny zestaw prezentuje się następująco:

Kod

Kod projektu umieściłem na GitHubie: https://github.com/jakubthedeveloper/RealMailNotification

Aplikację napisaną w pythonie uruchamiamy poleceniem:

python3 checker.py [-h] [--serial-port SERIAL_PORT] [--imap-server IMAP_SERVER] --imap-user IMAP_USER

Jeśli nie podamy adresu serwera IMAP, zostanie użyty adres imap.gmail.com, domyślną wartością parametru –serial-port jest /dev/ttyUSB0, natomiast parametr –imap-user jest obowiązkowy. Przykład:

python3 checker.py --imap-user moje.konto@gmail.com

Więcej informacji o uruchomieniu skryptu znajduje się w pliku readme.

Po uruchomieniu, skrypt sprawdza pocztę na serwerze i wysyła na port szeregowy (usb) tekst ‚mail’ lub ‚nomail’, zależnie czy są nieprzeczytane wiadomości czy też nie.

Aplikacja dla Arduino nasłuchuje na porcie szeregowym i ustawia serwo w jednej z dwóch predefiniowanych pozycji, zależnie od otrzymanej komendy. Poziome ustawienie zamocowanej do serwo tekturki pozwala jej się schować za monitorem, natomiast w ustawieniu pionowym tektura wystaje nad górną krawędź monitora.

Filmik z testów:

Problemy jakie przyszło rozwiązać

Największym problemem było znalezienie sposobu na zamontowanie urządzenia z tyłu monitora, na szczęście z pomocą przyszły nawiercone kątowniki, śrubki i trytytki 🙂

 

Czym zajmuje się programista?

Na pytanie „Czym zajmuje się programista?” przyszło mi odpowiedzieć w życiu co najmniej kilkanaście razy w rozmowach z rodziną i znajomymi, za każdym razem odpowiedź na to pytanie była nieco inna, w zależności od poziomu znajomości świata IT mojego rozmówcy.

Najogólniej mówiąc, programowanie polega na pisaniu programów komputerowych w specjalnym języku zrozumiałym dla komputerów.


Niezależnie czy pojęcia takie jak “Web-development” lub “backend” są ci znane, czy może brzmią dla ciebie jak nazwy magicznych wywarów, ten artykuł jest dla ciebie. Jeśli słyszałeś kiedyś rozmowę dwóch programistów lub czytałeś co programiści piszą w internecie (również na tym blogu) i stwierdziłeś że nie masz pojęcia o co w tym wszystkim chodzi, a chciałbyś to zrozumieć przynajmniej w stopniu podstawowym, zachęcam do lektury niniejszego tekstu.

Przedstawię kilka dialogów z różnymi osobami, podczas których starałem się wyjaśnić, czym zajmuję się zawodowo. Na końcu artykułu przedstawię czym się zajmuję moimi słowami, bez odniesienia do konkretnego poziomu wiedzy czytelnika.

(więcej…)

Optymalizacja z głową

Jednym z zagadnień należących do zakresu pracy programisty jest rozwiązywanie różnego rodzaju problemów, wśród nich znajduje się optymalizacja algorytmów.

Problemy tego typu polegają na tym, że mamy do zaimplementowania pewną funkcjonalność, która musi działać w określonych warunkach, określonym czasie i spełniać zadane założenia. Zatem nie wystarczy że coś działa, musi to też działać odpowiednio szybko i bez nadmiernego zużywania zasobów.

Prosty przykład

Załóżmy że mamy wskazówkę, która obraca się wokół tarczy zawsze o 90 stopni w prawo.

Początkowe położenie to 0 stopni.

Naszym zadaniem jest napisanie funkcji, która określa w jakim położeniu znajdzie się wskazówka po określonej liczbie obrotów.

(więcej…)

Junior, Regular, Senior… i co dalej?

Problem sufitu

W pewnym momencie mojej kariery na stanowisku programisty stanąłem przed dylematem „co dalej?”. Z piętnastoletnim doświadczeniem zawodowym, masą ukończonych projektów, zadowolonych klientów, sporą siecią kontaktów i całkiem niezłą renomą wśród współpracowników poczułem że dotarłem do „sufitu” czyli tam gdzie wyżej się już nie da pójść.

Z jednej strony chciałem nadal zajmować się programowaniem, architekturą systemów, rozwiązywaniem problemów, z drugiej jednak odczułem już lekkie zmęczenie patrzeniem się w IDE oraz konsolę przez cały dzień mojej pracy, postanowiłem więc rozejrzeć się za czymś co pozwoli mi być nadal blisko programowania, ale może trochę więcej pracować w inny sposób, z ludźmi. Po kilku rozmowach z moją Business Manager oraz po jej rozmowach z innymi osobami na szczeblu menadżerskim doszliśmy do wniosku, że to czego szukam to rola Team Leadera.

(więcej…)

Jak stworzyć film z audio i obrazka przy pomocy ffmpeg (linux/ffmpeg)

Załóżmy, że chcemy wrzucić na YouTube plik muzyczny z obrazkiem.

Mamy plik wave z muzyką dobrej jakości i nie chcemy go przepuszczać przez żaden enkoder przy renderowaniu filmu. Z pomocą przychodzi ffmpeg, w moim przykładzie używam go pod linuksem.

Plik z muzyką nazwałem test.wav, plik z obrazkiem test.jpg, aby wygenerować film wystarczy wykonać polecenie:

ffmpeg -loop 1 -y -i test.jpg -i test.wav -shortest -acodec copy -vcodec libx264 -pix_fmt yuv420p output.mkv

Kolejność parametrów ma znaczenie!

Parmeter -acodec copy sprawi, że zawartość ścieżki dźwiękowej zostanie skopiowana z oryginału, bez transkodowania.
Parametr -shortest sprawia, że długość filmu będzie taka jak długość ścieżki audio. Istotne jest, żeby nie umieścić tego parametru przed plikiem .jpg, ponieważ plik z obrazkiem ma nieskończoną długość i nasz film będzie się renderował w nieskończoność.
Wybrałem format wyjściowy mkv, ponieważ dał on najlepsze rezultaty w kwestii jakości filmu.

Ważną rzeczą jest to, żeby plik z obrazkiem miał rozdzielczość podzielną przez 2, najlepiej żeby obrazek miał taki rozmiar jaki chcemy uzyskać w wyjściowym filmie, np. 3840×2160 dla 4k.

Python i MIDI

Przymierzam się do napisania edytora brzmień do mojego syntezatora Korg Triton Le, na początek zrobiłem kilka eksperymentów w pythonie, żeby zobaczyć jak sprawnie będzie szła komunikacja z interfejsem MIDI. Do komunikacji z syntezatorem używam interfejsu USB-MIDI Roland UM-ONE.

Na początek zainstalowałem bibliotekę rtmidi (https://github.com/patrickkidd/pyrtmidi) i sprawdziłem czy wykrywa ona prawidłowo porty MIDI.

import rtmidi
import random
import time

midiout = rtmidi.RtMidiOut()
ports = range(midiout.getPortCount())

if ports:
print("Available MIDI output ports:")

for i in ports:
print(str(i) + ': ' + midiout.getPortName(i))

else:
print('No MIDI output ports available')
exit()

Po wykonaniu powyższego kodu otrzymałem:

Available MIDI output ports:
0: Midi Through 14:0
1: UM-ONE 28:0

Jest dobrze, python widzi mój interfejs.

Poeksperymentowałem trochę z wysyłaniem komunikatów MIDI do urządzenia i w rezultacie napisałem poniższy kod: (więcej…)

Oprogramowanie deweloperskie z lat 80-90.

Mamy rok 2019 a w mojej szufladzie wciąż leżą dwie dyskietki 5.25″. Nie sądzę, żeby się jeszcze kiedyś do czegoś przydały, traktuję je raczej jak namacalny fragment poprzedniej epoki w historii IT.

Dyskietki 5,25″ „KL100 (Keil 8051) Professional Development Package Demo” oraz „Wgłąb języka C”.

Pierwsza dyskietka to dodatek do książki „Wgłąb języka C” Adama Sapka, zawiera ona kod źródłowy do przykładów z książki.

Druga to „KL100 (Keil 8051) Professional Development Package (Demo)”. Dość enigmatyczna nazwa, ale po małej wizycie u wujka google, dowiadujemy się, że jest to oprogramowanie do programowania 8-bitowych mikrokontrolerów 8051, powstałych na początku lat osiemdziesiątych poprzedniego wieku. Z lekką dozą przesady można powiedzieć, że to takie ówczesne arduino 😉

Uczę dziecko programować

Jakiś czas temu moja sześcioletnia córka miała powiedzieć w przedszkolu czym zajmują się rodzice i bezbłędnie powiedziała że jestem programistą, ale do końca nie wiedziała o co w tym chodzi.

Dziś, gdy siedziałem i czytałem książkę o Pythonie, przyszła do mnie mówiąc jakie obliczenia matematyczne umie robić. Jako że miałem komputer z odpalonym linuksem pod ręką, odpaliłem interpreter pythona i zacząłem wpisywać równania, które mówiła córka: 1+1, 2+2, później odejmowanie, a nawet pokazałem jej dzielenie i co się dzieje gdy podzielimy przez zero. Widziałem w jej oczach zainteresowanie, więc zacząłem opowiadać że to właśnie na tym polega programowanie, że mówimy komputerowi żeby coś policzył a on to bardzo szybko robi. Aby pokazać że nie tylko o liczenie możemy poprosić nasz komputer wpisałem w pythonie:

>>> import turtle
>>> turtle.forward(50)
>>> turtle.left(90)
>>> turtle.forward(50)

Na ekranie zaczęło się coś rysować, a rysowanie to jest hobby mojej córki, więc zainteresowanie się nasiliło do tego stopnia, że już po chwili mieliśmy narysowany prosty domek.

(więcej…)

Praca z time trackerami

Czasami ludzie pytają mnie gdzie pracuję, odpowiadam że w domu. Często wtedy jestem wypytywany o szczegóły, zwłaszcza jeśli mój rozmówca nie miał wcześniej styczności z pracą zdalną. No i gdy tak opowiadam o tajnikach sztuki „remote work”, rozmowa w którymś momencie dojdzie do momentu: „masz fajnie, bo nikt cię nie kontroluje…”, no i wówczas tłumaczę, że używam aplikacji do logowania czasu pracy, które również robią zrzuty ekranu. I w tym momencie dla czar pryska, rozmówca zaczyna szukać drugiego dna, inwigilacji, ograniczenia wolności osobistych i tym podobnych straszności.

Tutaj dochodzimy do tematu niniejszego artykułu: jak się pracuje z time-trackerami i dlaczego nie jest to takie straszne.

(więcej…)

Komunikator napisany w Javie w 2008 roku.

Jakże miłe było moje zaskoczenie, gdy przeglądając katalogi ze starymi projektami znalazłem komunikator, który pisałem ponad 10 lat temu jako pracę licencjacką na Uniwersytecie Łódzkim. Jeszcze większym zaskoczeniem było dla mnie to, że komunikator zadziałał od ręki.

Na screenie widać konsole uruchamiające serwer i klienta oraz interfejs graficzny klienta. Ładny, prawda? 🙂

Komunikator jest napisany w Javie i składa się z dwóch części: klienta i serwera. Wiadomości zapisują się w bazie MySql.