Gausi
Beiträge: 8538
Erhaltene Danke: 475
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Do 22.09.05 15:23
Die Playlist von Winamp einlesen
Bei der Veröffentlichung meiner mp3-Verwaltung wurde ich immerhin von 2 Usern angesprochen, wie ich dort die Playlist von Winamp einlese. Ich habe mich daher entschlossen, das hier für die Allgemeinheit hinzustellen.
Diese Funktionen wurden erfolgreich getestet mit Winamp v2.80. Mit Winamp 3.x könnte es Probleme geben - aber man ist sich wohl ziemlich einig, dass die 3er Version etwas vermurkst war. Ob das mit der neuen 5er klappt, kann ich nicht sagen.
Ich verdiene nicht 100% der Lorbeeren dafür. Das gröbste hat caty in diesem Beitrag schon vorher erledigt. Ich habe die eine Funktion dort nur erweitert und einige andere hinzugefügt.
Für weitere Informationen verweise ich auf www.winamp.com/nsdn/winamp/sdk/
Zunächst einmal brauchen wir zur besseren Lesbarkeit ein paar Konstanten
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| const WINAMP_BUTTON1 : integer = 40044; WINAMP_BUTTON2 : integer = 40045; WINAMP_BUTTON3 : integer = 40046; WINAMP_BUTTON4 : integer = 40047; WINAMP_BUTTON5 : integer = 40048; WINAMP_VOLUMEUP : integer = 40058; WINAMP_VOLUMEDOWN: integer = 40059; IPC_GETLISTLENGTH : integer = 124; IPC_GETLISTPOS :integer = 125; IPC_GETPLAYLISTFILE : integer = 211; IPC_GETPLAYLISTTITLE : integer = 212;
IPC_GET_SHUFFLE : integer = 250; IPC_GET_REPEAT : integer = 251; |
Wir brauchen nicht alle diese Konstanten zum Auslesen der Playlist, aber am Ende komme ich noch auf ein paar weitere Sachen zu sprechen, wofür man die brauchen kann.
Ein Hinweis zwischendurch: Gebraucht werden die Units Windows, Messages und SysUtils
Zuerst eine Funktion, die einen Eintrag aus der Playlist zurückliefert. Eingabeparameter ist der Index des gewünschten Stückes in der Playlist - Beginn der Zählung bei 0. Wird ein negativer Parameter übergeben, wird der aktuell gewählte Titel bestimmt:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| function GetWinampTitel(data:Integer): String; var hwndWinamp, TempHandle : THandle; dat2: array[0..500] of Char; TrackPos: Integer; temp, MPointer: Cardinal; begin hwndWinamp:= FindWindow('Winamp v1.x',nil); if hwndWinamp= 0 then begin result:='' end else begin if data<0 then TrackPos:= SendMessage(hwndWinamp,WM_USER,0 , IPC_GETLISTPOS) else TrackPos:=data;
MPointer:= SendMessage(hwndWinamp,WM_USER,TrackPos , IPC_GETPLAYLISTTITLE); GetWindowThreadProcessId(hwndWinamp,TempHandle); hwndWinamp:= OpenProcess(PROCESS_ALL_ACCESS,False,TempHandle); ReadProcessMemory(hwndWinamp, Pointer(MPointer), @dat2,500,temp); CloseHandle(hwndWinamp); Result:= string(dat2); end; end; |
Um die komplette Playlist auszulesen, benötigen wir natürlich noch eine Information darüber, wie lang die Liste ist:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| function GetWinampPlayListLength:integer; var hwndWinamp:THandle; begin hwndWinamp:= FindWindow('Winamp v1.x',nil); if hwndWinamp= 0 then begin result:=-1 end else begin result := SendMessage(hwndWinamp,WM_USER,0 , IPC_GETLISTLENGTH); end; end; |
Bevor wir uns nun eine for-Schleife basteln, die uns die komplette Liste liefert, noch eine weitere Funktion. Was bei Winamp in der Liste steht, ist ja eigentlich gar nicht so interessant. Viel interessanter ist es, den Dateinamen des Listeneintrages zu erhalten. Das ist jetzt nicht mehr schwer - die Funktion ist fast identisch mit der Titel-Funktion - Wir senden nur eine andere Message an das Winamp-Fenster.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
| function GetWinampFilename(data:Integer): String; var hwndWinamp, TempHandle : THandle; dat2: array[0..500] of Char; TrackPos: Integer; temp, MPointer: Cardinal; begin hwndWinamp:= FindWindow('Winamp v1.x',nil); if hwndWinamp= 0 then begin result:='' end else begin if data<0 then TrackPos:= SendMessage(hwndWinamp,WM_USER,0 , IPC_GETLISTPOS) else TrackPos:=data;
MPointer:= SendMessage(hwndWinamp,WM_USER,TrackPos , IPC_GETPLAYLISTFILE); GetWindowThreadProcessId(hwndWinamp,TempHandle); hwndWinamp:= OpenProcess(PROCESS_ALL_ACCESS,False,TempHandle); ReadProcessMemory(hwndWinamp, Pointer(MPointer), @dat2,500,temp); CloseHandle(hwndWinamp); Result:= string(dat2); end; end; |
Jetzt können wir diese drei Funktionen z.B. so anwenden:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| procedure TForm1.Button1Click(Sender: TObject); var i:integer; begin for i:=0 to GetWinampPlayListLength-1 do begin listbox1.Items.Add(GetWinampFilename(i)); listbox2.Items.Add(GetWinampTitel(i)); end; end; |
So weit, so gut. Damit dürfte da Prinzip klar sein. Man kann aber z.B. auch nicht nur den aktuellen Titel bestimmen ( GetWinampFilename(-1)), man kann auch den nächsten und vorigen Titel bestimmen. Dazu muss man berücksichtigen, ob Shuffle oder Repeat aktiviert ist. Shuffle macht eine Vorhersage des nächsten Titels unmöglich, bei Repeat wird vom Ende der Liste wieder an den Anfang gesprungen. Das Prinzip der Funktionen sollte klar sein: Man bestimmt die Position des aktuellen Titels, und bestimmt dann den Titel davor bzw. danach.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86:
| function GetWinampNextTitel:string; var hwndWinamp, TempHandle : THandle; dat2: array[0..500] of Char; TrackPos,maxpos: Integer; temp, MPointer: Cardinal; begin hwndWinamp:= FindWindow('Winamp v1.x',nil); if hwndWinamp= 0 then begin result:='' end else begin if SendMessage(hwndWinamp,WM_USER,0 , IPC_GET_SHUFFLE)=1 then result:='N/A [random]' else begin TrackPos := SendMessage(hwndWinamp,WM_USER,0 , IPC_GETLISTPOS); maxpos := SendMessage(hwndWinamp,WM_USER,0 , IPC_GETLISTLENGTH); if maxpos-1 > Trackpos then inc(TrackPos) else begin if SendMessage(hwndWinamp,WM_USER,0 , IPC_GET_REPEAT)=1 then TrackPos:=0 else begin result:='N/A [no repeat]'; exit; end; end; MPointer:= SendMessage(hwndWinamp,WM_USER,TrackPos , IPC_GETPLAYLISTTITLE); GetWindowThreadProcessId(hwndWinamp,TempHandle); hwndWinamp:= OpenProcess(PROCESS_ALL_ACCESS,False,TempHandle); ReadProcessMemory(hwndWinamp, Pointer(MPointer), @dat2,500,temp); CloseHandle(hwndWinamp); if fileexists(GetWinampFilename(Trackpos)) then Result := string(dat2) else Result := 'N/A [File not found]'; end; end; end;
function GetWinampPrevTitel:string; var hwndWinamp, TempHandle : THandle; dat2: array[0..500] of Char; TrackPos,maxpos: Integer; temp, MPointer: Cardinal; begin hwndWinamp:= FindWindow('Winamp v1.x',nil); if hwndWinamp= 0 then begin result:='' end else begin if SendMessage(hwndWinamp,WM_USER,0 , IPC_GET_SHUFFLE)=1 then result:='N/A [random]' else begin TrackPos := SendMessage(hwndWinamp,WM_USER,0 , IPC_GETLISTPOS); maxpos := SendMessage(hwndWinamp,WM_USER,0 , IPC_GETLISTLENGTH); if Trackpos > 0 then dec(TrackPos) else begin if SendMessage(hwndWinamp,WM_USER,0 , IPC_GET_REPEAT)=1 then TrackPos:=maxpos-1 else begin result:='N/A [no repeat]'; exit; end; end; MPointer:= SendMessage(hwndWinamp,WM_USER,TrackPos , IPC_GETPLAYLISTTITLE); GetWindowThreadProcessId(hwndWinamp,TempHandle); hwndWinamp:= OpenProcess(PROCESS_ALL_ACCESS,False,TempHandle); ReadProcessMemory(hwndWinamp, Pointer(MPointer), @dat2,500,temp); CloseHandle(hwndWinamp); if fileexists(GetWinampFilename(Trackpos)) then Result := string(dat2) else Result := 'N/A [File not found]'; end; end; end; |
Und wenn man jetzt Winamp veranlassen möchte, den nächsten Titel auch abzuspielen, dann geht das so: Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| procedure WinampPlayNext; var hwndWinamp: THandle; begin hwndWinamp:= FindWindow('Winamp v1.x',nil); if hwndWinamp<>0 then SendMessage(hwndWinamp,WM_COMMAND, WINAMP_BUTTON5, 0); end; |
Was passiert, wenn man WINAMP_BUTTON5 durch eine der anderen Button-Konstanten ersetzt, überlasse ich dem interessierten Leser zur Übung.
Viel Spass damit!
_________________ We are, we were and will not be.
|