Nowy utwór: Test Object No. 52

Niektórzy wiedzą, niektórzy nie 😉  Czasem sobie coś tam komponuję trochę. A to coś rockowego/gitarowego, a to coś symfonicznego, a to elektronicznego.

Kilka dni temu opublikowałem mój najnowszy utwór: Test Object No. 52. To gitarowy utwór w stylu rockowo-metalowym, napisany w A moll.

Miłego słuchania! 🙂

Zawartość niedostępna.
Wyraź zgodę na używanie plików cookie.

VideoEditor 1.0.0.20

VideoEditor 1.0.0.20 to prosty program, będący narzędziem znacznie ułatwiającym pracę ze wspaniałym ffmpeg.

Na ten moment, program umożliwia konwertowanie plików video oraz ich łatwe przycinanie.

VideoEditor 1.0.0.20

Po uruchomieniu programu, należy wejść w ustawienia i zdefiniować ścieżkę do samego ffmpeg.exe. Skąd go wziąć? Można oczywiście go sobie zbudować, ale polecam skorzystać ze strony CODEX FFMPEG, gdzie są dostępne zawsze aktualne binaria.

Następnie polecam przejrzeć zakładkę z presetami kodeków video. Kilka zawarłem jako domyślne. Jeśli umiesz obsługiwać ffmpeg, możesz zdefiniować swoje własne nowe ustawienia.

Po skonfigurowaniu programu, po prostu otwórz plik video, zaznacz punkty przycięcia filmu, jeśli chcesz, wybierz preset konwersji i naciśnij “Convert”. Podajesz nazwę nowego pliku i czekasz na zakończenie konwersji.

Program będę dalej rozwijał i dodawał nowe funkcjonalności. W planach również obsługa różnych języków i instalator.

Dla chętnych, dostępne są źródła na GitHubie.

Program można pobrać tutaj. Miłej zabawy! 🙂 

Sound analysis for visualization purposes

Music analysis – part 1
Pobieranie obrazów z Instagrama – aktualizacja

Pobieranie obrazów z Instagrama – aktualizacja

Niedawno zorientowałem się dopiero 😉 że mój skrypt do pobierania obrazów z Instagrama już nie działa z powodu zmian w systemie Instagram. Zaktualizowałem więc skrypt i można go pobrać i zainstalować w TamperMonkey. Uwaga, skrypt działa na stronie postu, nie na stronie kolekcji. Aby przejść do strony postu z podglądu zdjęcia, należy wybrać opcję “Go to post”.

W efekcie, pod zdjęciem powinien pojawić się link do obrazu.

 

Pobieranie obrazów z Instagrama

Pobieranie obrazów z Instagrama

Czasem zachodzi potrzeba pobrania zdjęcia z Instagrama w pełnej dostępnej rozdzielczości. Wbrew pozorom jest to dość proste.

W zasadzie, jedyne, co należy wykonać, to odnaleźć wpis meta nazywający się “og:image”:

<meta property="og:image" content="https://serwer/zdjecie.jpg" />

Zawartość właściwości “content” to link do zdjęcia w pełnej rozdzielczości.

Jeśli jednak chcesz pobrać większą ilość zdjęć, bądź robisz to dość często, przyda się mała automatyzacja. Napisałem do tego celu mały skrypt, który działa pod kontrolą TamperMonkey. Wszystko, co ten skrypt robi, to na dole strony (pomiędzy zdjęciem a stopką) wstawia link do zdjęcia.

Po zainstalowaniu TamperMonkey, jeśli go jeszcze nie masz, wystarczy zainstalować ten skrypt. Uwaga, skrypt działa na stronie postu, nie na stronach kolekcji. Aby przejść do strony postu z podglądu zdjęcia, należy wybrać opcję “Go to post“.

Seriale Netflix – Marvel

Na przełomie listopada i grudnia w końcu skusiłem się na bezpłatny miesiąc testów Netfliksa. Powiem tylko tyle, że efektem testów jest przedłużenie 😉

W ramach owych testów postanowiłem sprawdzić, co Netflix wyczarował do spółki z Marvelem. Skusiły mnie takie nazwiska trzymających pieczę nad produkcjami, jak Stan Lee i Joe Quesada. Zacząłem trochę krzywo, bo od Punishera.

Historia zaczyna się, gdy Punisher ukrywa się pod nowym nazwiskiem, już po wykończeniu ludzi odpowiedzialnych za wymordowanie jego rodziny. Jak to zwykle bywa, zostaje zmuszony do powrotu na ulicę. Po obejrzeniu serialu (póki co, jest jeden sezon) poczytałem trochę opinii w necie – zawsze to robię dopiero po obejrzeniu filmu. Sporo ludzi marudzi, że Punisher mało brutalny jest i że w Daredevilu (o czym niżej) jest znacznie lepszy. Hmm… wg mnie w Daredevilu jest dokładnie taki sam, identyczny charakter. Jeśli ktoś twierdzi inaczej, to krzywo oglądał oba seriale i raczej oglądał tylko obrazki 😉 W każdym razie, mnie kupili tą historią.

Idąc tym tropem, obejrzałem oba (na razie) sezony Daredevila. Ujmę to tak: jeśli ktoś zna tę postać tylko z filmu z Benem Affleckiem, to szybko zapomnijcie o swoich odczuciach z tym związanych. Serial to zupełnie inna bajka. Szczerze mówiąc, dawno nie widziałem tak dobrego serialu, a już na pewno nie marvelowego. Zgrabna fabuła, wartka akcja, postaci naprawdę świetne. No i rzecz bardzo rzadko spotykana – czarny charakter jest nareszcie fantastycznie narysowany. Wilson Fisk (przyszły Kingpin) jest wyrazisty jak mało co. Najlepiej by go określił Shrek 😉 że jest jak cebula.

Po Daredevilu przyszedł czas na The Defenders. Okazało się, że spośród 4 indywidualnych seriali, ten należy obejrzeć właśnie po Daredevilu, gdyż jest on bezpośrednią kontynuacją jego fabuły. Ponownie zmierzymy się z organizacją The Hand i Czarnym Słońcem. Opisać ten mini-serial nie jest łatwo. Bohaterowie: Daredevil jak to Daredevil, świetny. Reszty do tej pory nie znałem (filmowo, rzecz jasna). Jessica Jones wypadła rewelacyjnie, jej postać wykreowana naprawdę świetnie. Luke Cage idealnie… nijaki. W zasadzie nic o tym człowieku się nie da powiedzieć. A Iron Fist… klapa kompletna. Nie wiem, może taki był zamysł producentów, żeby zrobić z niego rozkojarzonego dzieciaka ze świecącą pięścią. W każdym razie, wiem teraz, że tych dwóch indywidualnych seriali raczej nie będę próbował oglądać. Natomiast ozdobą były dialogi Jessiki z Daredevilem. Ta dwójka wymiatała 🙂 Co do samej akcji: skonstruowana jest poprawnie, a dzięki skróceniu formatu do 8 tylko odcinków, nie ma dłużyzn. Jedyne, co mogę zarzucić mu, to łzawe zakończenie, którego jakoś chyba nie mogli sobie odmówić, oraz oczywistą, spodziewaną i sztampową ostatnią scenę. Poza tym, serial jest ok.

Po obejrzeniu Defenders, postanowiłem sprawdzić Jessikę Jones, która tam wypadła naprawdę bardzo ciekawie. Serial zupełnie różny od typowych produkcji marvelowskich – bo i bohaterka jakże inna (choć oryginalnie bardzo mocno wpleciona w życiorys Spidermana). Nie jest to typowe superbohaterskie kino, raczej kryminalny thriller. Ogląda jednak się to naprawdę dobrze, zwłaszcza pierwszą połowę. Druga połówka chyba nieco zbyt mocno skupiona na relacjach Jessiki z Kilgravem, ale tak została skreślona fabuła, więc nie ma co narzekać. Serial zdecydowanie dla dorosłych – seks i przemoc kapią z ekranu solidnymi strugami. Ogólnie szczerze polecam obejrzenie.

Na koniec… muszę przyznać, że pozytywnie mnie te seriale zaskoczyły. Znając różne produkcje Marvela, te naprawdę się wybijają ponad przeciętność. Co prawda, najprawdopodobniej (choć nie widziałem) Iron Fist i Luke Cage bedą beznadziejne, ale te wymienione powyżej jak najbardziej na plus. Brawo Netflix 🙂

Na koniec 2… Boję się otworzyć lodówkę. Boję się, że wyskoczy z niej… Claire 😉  w każdym serialu (chyba tylko w Punisheru jej nie było?) ta postać się pojawia. W sumie, być może to był zabieg pozwalający na spięcie fabuły w The Defenders, choć i tak sposób ich spotania się był lekko… hm, niezręczny 😉 no, ale sam bym chyba też tego lepiej nie zrobił, więc się tylko czepiam.

Na koniec 3 😉 czołówka z The Defenders, napisana przez Johna Paesano, wymiata. Jest też na Spotify’u, jakby co.

Zawartość niedostępna.
Wyraź zgodę na używanie plików cookie.

Lost Alpha Director’s Cut – early screenshots

As S.T.A.L.K.E.R.: Lost Alpha – Director’s Cut is getting more and more of its final look, I’ve decided to publish some screenshots.

I will be adding more images here, but I won’t add any new post anytime soon, so just check this one back from time to time.

Please note: as the game is still under development, the quality of images can vary between each other. However, all of them are quite fresh – but the final game can look a bit different.

Selektor koloru z trybem float

Selektor koloru z trybem float

Jest wiele selektorów kolorów online. Większość zwraca wyniki w wartościach RGB z zakresu <0..255>, w zapisie szesnastkowym, oraz HSL. Jednak brakuje w nich wszystkich jeszcze jednej formy podawania wyników: w formie wartości RGB w zakresie <0..1>, używanym w niektórych programach, zwłaszcza 3D. Osobiście często używam POV-Raya i za każdym razem muszę używać kalkulatora, aby przeliczyć wszystkie trzy wartości na odpowiedni zakres.

Początkowo miałem zamiar napisać malutki programik do tego celu, ale stwierdziłem, że wersja on-line będzie wygodniejsza w użyciu. Nie jest to żadne rocket science 😉 ale swoje zadanie spełnia. Może w przyszłości jakoś go rozbuduję i usprawnię, ale… nie obiecuję 😉

Jeszcze jedna uwaga… poniższe nie działa z IE… 🙁






Może się komuś przyda – mi na pewno 🙂

Pluginy aplikacji Qt5

Tworzenie systemu pluginów aplikacji działającej na różnych systemach wymagało zawsze wielokrotnej implementacji tego samego – dla każdego systemu oddzielnie, głównie z powodu sposobu dynamicznego ładowania bibliotek. W Qt jednak jest inaczej – framework ten udostępnia bardzo sprawnie działający system pluginów.

Na początek zdefiniujmy interfejs (API):

#ifndef DESIGNLAYER_API_H
#define DESIGNLAYER_API_H

#include 
#include 

namespace apophysis
	{		
	class DesignLayerAPI
		{
		public:
			virtual ~DesignLayerAPI() {};
			virtual QString getName() = 0;
		};
	}

#define DesignLayerAPI_iid "org.apophysis.DesignLayerAPI"

Q_DECLARE_INTERFACE(apophysis::DesignLayerAPI, DesignLayerAPI_iid)

#endif // DESIGNLAYER_API_H

Widzimy tu wirtualną klasę, definiującą metodę getName(). Po definicji API, następuje definicja interfejsu, po którym Qt będzie rozpoznawać nasze pluginy, implementujące te API.

Czas na plugin. Deklarujemy klasę implementującą API:

#ifndef DESIGNLAYER_IMAGE_H
#define DESIGNLAYER_IMAGE_H

#include 
#include 
#include 

class designLayerImage : public QObject, apophysis::DesignLayerAPI
	{
	Q_OBJECT
		Q_PLUGIN_METADATA(IID "org.apophysis.DesignLayerAPI" FILE "designLayerImage.json")
		Q_INTERFACES(apophysis::DesignLayerAPI)

	public:
		designLayerImage();
		QString getName() Q_DECL_OVERRIDE;
	private:
		QString theName;
	};

#endif // DESIGNLAYER_IMAGE_H

Oprócz deklaracji metod zadeklarowanych w interfejsie, widzimy tu jeszcze jedną rzecz: definicję metadanych. Po co to? Metadane pluginu można odczytać bez faktycznego ładowania biblioteki. Zapisujemy je w pliku JSON, np:

{
"type"			:	"Layer",
"name"			:	"Image layer plugin",
"shortname"		:	"ImageLayer",
"version"		:	"0.1",
"author"		:	"Apophysis internal",
"description"	:	"Used mainly for backgrounds: solid colour, gradients, images, etc."
}

Właściwa implementacja jest oczywista, żadnej magii tu nie ma:

#include "designLayerImage.h"

designLayerImage::designLayerImage()
	:
	theName(QLatin1Literal("Unnamed image layer"))
	{
	}

QString designLayerImage::getName()
	{
	return theName;
	}

OK, mamy plugin. Jak go użyć? Na szczęście, to również jest proste (i przenośne! Na pewno działa bez zmian pod Windows i Linux, pod OSX nie sprawdzałem).

Najpierw sprawdzimy w działaniu system metadanych. Załóżmy, że pluginy mamy w podkatalogu plugins (niespodzianka!):

#include 
#include 

void listPlugins()
	{
	QDir pluginsDir(qApp->applicationDirPath());
	pluginsDir.cd(QLatin1Literal("plugins"));
	foreach(QString fileName, pluginsDir.entryList(QDir::Files, QDir::Name))
		{
		QString libExt;
#if defined(Q_OS_WIN)
		libExt = QLatin1Literal("dll");
#elif defined(Q_OS_MAC)
		libExt = QLatin1Literal("bundle");
#elif defined(Q_OS_LINUX)
		libExt = QLatin1Literal("so");
#endif
		if (QFileInfo(fileName).suffix().toLower() == libExt)
			{
			QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
			qDebug() << "File:" << fileName;
			QJsonObject jsonMetaData = pluginLoader.metaData().value(QLatin1Literal("MetaData")).toObject();
			qDebug() << jsonMetaData.value(QLatin1Literal("type")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("name")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("shortname")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("version")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("author")).toString();
			qDebug() << jsonMetaData.value(QLatin1Literal("description")).toString();
			}
		}
	}

W zasadzie moglibyśmy się obejść bez sekcji sprawdzania rozszerzenia plików, ale używam tego w razie, gdyby w katalogu były jeszcze jakieś inne pliki (ot, chociażby PDB).

OK, czas na crème de la crème, czyli stworzenie instancji klasy zaimplementowanej w pluginie:

void apophysis::Design::addLayer(const QString & aLayerType)
	{
	QDir pluginsDir(qApp->applicationDirPath());
	pluginsDir.cd(QLatin1Literal("plugins"));
	foreach(QString fileName, pluginsDir.entryList(QDir::Files, QDir::Name))
		{
		QString libExt;
#if defined(Q_OS_WIN)
		libExt = QLatin1Literal("dll");
#elif defined(Q_OS_MAC)
		libExt = QLatin1Literal("bundle");
#elif defined(Q_OS_LINUX)
		libExt = QLatin1Literal("so");
#endif
		if (QFileInfo(fileName).suffix().toLower() == libExt)
			{
			QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
			QString plugintype = pluginLoader.metaData().value(QLatin1Literal("MetaData")).toObject().value(QLatin1Literal("type")).toString();
			QString pluginshortname = pluginLoader.metaData().value(QLatin1Literal("MetaData")).toObject().value(QLatin1Literal("shortname")).toString();
			if ((plugintype == QLatin1Literal("Layer")) && (pluginshortname == aLayerType))
				{
				QObject *plugin = pluginLoader.instance();
				if (plugin)
					{
					apophysis::DesignLayerAPI *layer = qobject_cast(plugin);
					if (layer)
						theLayers.append(layer);
					}
				}
			}
		}
	}

Jak widać, zarówno tworzenie, jak i używanie pluginów w tym systemie jest trywialne - i jest całkowicie przenośne.

Happy coding!