Winamp'a Plugin Yazmak
Belki ileride işinize yarar diye yazdığım ufak bir winamp plugini
paylaşmak istedim. Pluginin yaptığı şey F12 tuşuna basıldığında çalmakta
olan şarkıyı plugin ayarlarında daha önceden belirttiğimiz yere
kopyalamak. Bu ne için gerekli olur diye düşünebilirsiniz. Şöyle ki:
Diyelim ki arkadaşınızdan binlerce müzikten oluşan ufak bir müzik arşivi
aldınız. Belki çoğu müzik hoşunuza gitmeyecek. Hoşunuza gidenleri
ayıklamak istediğinizde ise çok zorlanacaksınız. Hele çoğu şarkının
winampta görünen hali(title) ile diskteki ismi farklıdır. Iç içe
klasörler de işin içine girdi mi dosyaları arar durursunuz. Benim başıma
bu durum çok geldiği için bir plugin yazayım dedim. Ufak bir araştırma
sonucu edindiğim bilgileri paylaşmak istedim.
Plugin yazabilmek için öncelikle WinampSDK yı indirip yüklemek
gerekiyor. Kurulum dosyasını aşağıdaki bağlantıdan indirebilirsiniz.
WinampSDK plugin yazabilmek için gerekli başlık dosyalarını
içermektedir. WinampSDK yı kurduğunuzda default olarak "C:\Program
Files\Winamp SDK" klasörü içine kurulmaktadır. Kullandığımız IDE
ayarlarından yada proje ayarlarından bu klasörü ortama tanıtmış olmamız
gerekmektedir.
Winamp çok sayıda plugin(eklenti) türü desteklemektedir. Winamp bu
pluginleri yüklerken hangi türde olduğunu plugin dosyalarının ön
eklerine bakarak anlar. Plugin türleri aşağıdaki gibi sıralanmaktadır.
- in_*.dll - Giriş pluginleri(input plugins). Değişik ses formatlarınının okunup winamp tarafından çalınmasını sağlayan pluginlerdir.
- out_*.dll - Çıkış pluginleri(output plugins). Sesin bilgisayar donanımı tarafından çalınabilmesini sağlayan pluginlerdir.
- gen_*.dll - Genel amaçlı pluginler (general purpose plugins). Winampın herhangi bir yerine müdahale etmek yada bilgiler almak için kullanılan pluginlerdir.
- vis_*.dll - Çalan müziğe göre görsel efektler oluşturan pluginler (visualizer plugins).
- dsp_*.dll - Ses efekt pluginleri (audio effects plugins). Ses içeriğine etki ederek değişik efektler oluşturmayı sağlayan pluginlerdir. Sesin Basslı, tizli, robotik çalması gibi.
- ml_*.dll - Ses/Görüntü kütüphanesi pluginleri (media library plugins) (bu pluginler gen_ml.dll plugini tarafından okunur)
- pmp_*.dll - Taşınabilir ortam oynatıcı pluginleri (portable media player plugins) (ml_pmp.dll tarafından okunurlar. Yani bir pluginin plugini tarafından okunurlar.)
- nsvdec_*.dll - NVS çözücü pluginleri (NSV decoder plugins)
- enc_*.dll - Ses dönüştürücü pluginleri (audio encoder plugins)
- W5S - Winamp sistem pluginleri (Winamp 5 System) "c:program fileswinampsystem" klasörü içinde uzantıları .w5s olan pluginlerdir.
- WAC - Winamp bileşen pluginleri (Winamp Component) "c:program fileswinamppluginsfreeformwacs" klasörü içinde bulunurlar .wac dosya uzantısına sahiptirler. gen_ff.dll plugini tarafından okunurlar.
Winamp her açılışında "C:\Program Files\Winamp\Plugins" klasörü
içinde bulunan pluginleri otomatik olarak yükler. Yazdığımız pluginlerin
okunabilmesi için onları bu klasöre koymamız gerekiyor. Pluginimiz
okunduğunda Winamp tercihleri kısmında aşağıdaki gibi görünecektir.
Aşağıdaki winamp pluginimizin çalışma mantığı da kabaca şöyledir. Winamp dll imiz içinde export edilmiş olan "winampGetGeneralPurposePlugin" fonksiyonunu çağırıp "winampGeneralPurposePlugin" yapısından bir instanceyi alıp içinde belirtilen callback fonksiyonlarını gerekli zamanlarda işletir. Kaynak kodlar da gerekli gördüğüm yerlerde ufak açıklamalar yaptım. Winamp ile iletişime geçmeyi plugin yüklenirken
winampın yapımıza verdiği pencere idsine windows mesajları göndererek
yapıyoruz. Winampa ne tür mesajlar gönderilerek neler elde edeceğimiz
yada neler yaptırabileceğimiz gibi bilgileri wa_ipc.h başlık dosyası
içine bakarak, inceleyerek öğreniyoruz. wa_ipc.h dosyası genel amaçlı
pluginler yazmak için gerekli fonksiyonları içeren başlık dosyasıdır.
Diğer tür pluginlerin çalışma mantığı da buna benzedir.
WinampPlugin.h
C/C++ kodu:
WinampPlugin.h
C/C++ kodu:
#pragma once #include <windows> // plugin versiyonu (değiştirilmemesi gerekiyor) #define GPPHDR_VER 0x10 // plugin ismi #define PLUGIN_NAME "BTMusicCopy" //Plugin ile ilgili bilgileri ihtiva eden yapı typedef struct { int version; // Plugin yapısının versiyonu char *description; // Pluginin ismi int (*init)(); // Plugin yüklenirken çağırılacak fonksiyon void (*config)(); // Winamp ta plugine ait ayarları göster denildiğinde çağırılacak fonksiyon void (*quit)(); // Plugin serbest bırakılırken çağırılacak fonksiyon HWND hwndParent; // Winamp penceresinin id sini tutar HINSTANCE hDllInstance; // Pluginin/Dll in instancesini tutar. }winampGeneralPurposePlugin;
WinampPlugin.cpp
C/C++ kodu:
#include "stdafx.h" #include <windows.h> #include "WinampPlugin.h" #include "Config.h" #include "NetInteropUtils.h" //WinampSDK klasörü içinde bulunmakta #include <Winamp\wa_ipc.h> using namespace WinampPlugin; using namespace System::Threading; using namespace System::IO; ref class KEY{ public: void KeyListener(); }; //Plugin yüklenirken çağırılacak fonksiyon int init(void); //Winamp ta plugine ait ayarları göster denildiğinde çağırılacak fonksiyon void config(void); //Plugin serbest bırakılırken çağırılacak fonksiyon void quit(void); //Yapının başlangıç değerlerini atıyoruz. winampGeneralPurposePlugin plugin = {GPPHDR_VER,PLUGIN_NAME,init,config,quit,0,0}; bool IsKeyDown(Keys key) { short retVal = GetKeyState((int)key); if ((retVal & 0x8000) == 0x8000) return true; else return false; } int init() { /* Pluginimiz yüklendiğinde winamp açık olduğu sürece basılan tuşları dinlemesi için bir thread oluşturuyoruz. */ Thread ^th; KEY ^object=gcnew KEY(); th=gcnew Thread(gcnew ThreadStart(object,&KEY::KeyListener)); th->Name="KeyListener"; th->Start(); return 0; } void KEY::KeyListener() { while(1){ //Threadin sistemi yormaması için 20ms de bir basılan tuşları kontrol ediyoruz. Sleep(20); //Threadin winamp ile iletişimi sırasında başka windows mesajlarının da işlenmesini sağlıyoruz. Application::DoEvents(); //F12 kısayol tuşuna basıldığında çalmakta olan dosyayı ayarlar ekranında belirtilen klasöre kopyala if (IsKeyDown(Keys::F12)) { String ^destPath=(String^)Application::UserAppDataRegistry->GetValue("DestinationPath"); //Çalmakta olan şarkının indexini al int pos=SendMessage(plugin.hwndParent,WM_WA_IPC,0,IPC_GETLISTPOS); //Indexi verilen şarkının dosya yolunu al LRESULT lpres=SendMessage(plugin.hwndParent,WM_WA_IPC,pos,IPC_GETPLAYLISTFILE); //Dönen sonucu char pointere cast ediyoruz. char *name=reinterpret_cast<char *>(lpres); //Dosya bilgisini al FileInfo ^finfo= gcnew FileInfo(NetInterops::ConvertStr(name)); try { //Dosyayı belirtilen konuma kopyala File::Copy(NetInterops::ConvertStr(name),destPath+"\\"+finfo->Name,false); //Kopyalama işlemi başarılı olursa bip sesi çaldır. Beep(1000,500); } catch (Exception^ex) { MessageBox::Show("Dosya kopyalanamadı yada zaten hedef klasörde mevcut.","",MessageBoxButtons::OK,MessageBoxIcon::Error); } } } } void config() { Config ^config =gcnew Config(); config->Show(); } void quit() { } //Winampın plugini yüklerkenki giriş noktası. extern "C" __declspec(dllexport) winampGeneralPurposePlugin * winampGetGeneralPurposePlugin() { return &plugin; }
Config.h panel sınıfının sadece ilgili kısımları.
C/C++ kodu:
.. .. private: System::Void Config_Load(System::Object^ sender, System::EventArgs^ e) { try { //Uygulamamıza ait registry ayarlarından DestinationPath değerini oku. textBoxFilePath->Text = (String^)Application::UserAppDataRegistry->GetValue("DestinationPath"); } catch(Exception ^ex){} } private: System::Void buttonSelectFolder_Click(System::Object^ sender, System::EventArgs^ e) { //Klasör seçim diyalog kutusunu göster FolderBrowserDialog ^folders=gcnew FolderBrowserDialog(); folders->RootFolder= Environment::SpecialFolder::Desktop; folders->Description= "Klasör Seçimi"; folders->SelectedPath=(String^)Application::UserAppDataRegistry->GetValue("DestinationPath"); if (::DialogResult::OK==folders->ShowDialog()) { //Diyalog kutusundan seçilen klasörü ilgili kutucuğa ata textBoxFilePath->Text=folders->SelectedPath; } } private: System::Void buttonSavePath_Click(System::Object^ sender, System::EventArgs^ e) { try { //Seçilen klasörü registry ye kaydet Application::UserAppDataRegistry->SetValue("DestinationPath", textBoxFilePath->Text); MessageBox::Show("Ayarlar kaydedilmiştir."); this->Close(); } catch(Exception ^ex){} } .. ..
Dersimizin kaynak kodları ve derlenmiş plugin dosyaları. Uygulamamızın çalışabilmesi için Visual C++ 2008 çalışma kütüphanelerinin ve .Net Framework 2.0 ın sistemimizde yüklü olması gerekmektedir. En az WinXP Sp2 kullanıyorsanız bunlar zaten yüklü olduğu için ayrıca bişi yüklemenize gerek kalmayacaktır.
Kaynak Kod:
Yararlanılan kaynak http://dev.winamp.com/wiki/Plug-in_Developer
Bir sonraki dersimizde görüşünceye kadar kendinize iyi bakın.
Bilgin Terzi ( 3ddreams )
Yorumlar
Yorum Gönder