You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

winamp.dpr 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. {*
  2. * winamp.dpr -> Code for winamp.dll for DMDirc
  3. * DMDirc - Open Source IRC Client
  4. * Copyright (c) 2006-2017 DMDirc Developers
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22. * SOFTWARE.
  23. *}
  24. // References:
  25. // http://krizzprograming.blogspot.com/2007/08/controlling-winamp-programmatically.html
  26. // http://forums.winamp.com/showthread.php?threadid=85389
  27. library winamp;
  28. uses
  29. windows, messages, SysUtils, Classes;
  30. function VirtualFreeEx(hProcess:HANDLE; lpAddress:LPVOID; dwSize:DWORD ; dwFreeType : DWORD):WINBOOL; external 'kernel32' name 'VirtualFreeEx';
  31. function VirtualAllocEx(hProcess:HANDLE; lpAddress:LPVOID; dwSize:SIZE_T ; flAllocationType : DWORD; flProtect : DWORD):POINTER; external 'kernel32' name 'VirtualAllocEx';
  32. type
  33. extendedFileInfoStruct = packed record
  34. filename: pchar;
  35. metadata: pchar;
  36. ret: pchar;
  37. retlen: integer;
  38. end;
  39. const
  40. WM_WINAMP = WM_USER;
  41. function getPlayState(data: PChar):integer; stdcall;
  42. var
  43. hand: THandle;
  44. res: LongInt;
  45. B: array[0..255] of char;
  46. begin
  47. result := 1;
  48. B := 'Error finding window';
  49. hand := FindWindow('Winamp v1.x', nil);
  50. if hand <> 0 then begin
  51. B := 'Error getting data';
  52. result := 0;
  53. res := SendMessage(hand, WM_WINAMP, 0, 104);
  54. if res = 1 then B := 'Playing'
  55. else if res = 3 then B := 'Paused'
  56. else B := 'Stopped';
  57. StrCopy(data,B);
  58. end;
  59. end;
  60. function getArtistTitle(data: PChar):integer; stdcall;
  61. var
  62. hand: THandle;
  63. B: array[0..255] of char;
  64. tempHand: THandle;
  65. memLoc: LongInt;
  66. temp: LongWord;
  67. begin
  68. result := 1;
  69. B := 'Error finding window';
  70. hand := FindWindow('Winamp v1.x', nil);
  71. if hand <> 0 then begin
  72. B := 'Error getting data';
  73. result := 0;
  74. memLoc := SendMessage(hand, WM_WINAMP, 0, 125); // Get number of current track
  75. memLoc := SendMessage(hand, WM_WINAMP, memLoc, 212); // And now its name
  76. GetWindowThreadProcessId(hand, @tempHand);
  77. hand := OpenProcess(PROCESS_ALL_ACCESS, False, tempHand);
  78. ReadProcessMemory(hand, Pointer(memLoc), @B, sizeof(B)-1, temp);
  79. CloseHandle(hand);
  80. StrCopy(data,B);
  81. end;
  82. end;
  83. function getMetaData(metadata: PChar): PChar;
  84. var
  85. hand: THandle;
  86. readhand: THandle;
  87. B: array[0..255] of char;
  88. C: array[0..255] of char;
  89. tempHand: THandle;
  90. memPtr: Pointer;
  91. memLoc: LongInt;
  92. temp: LongWord;
  93. extinfo: extendedFileInfoStruct;
  94. begin
  95. B := '';
  96. C := '';
  97. Result := '';
  98. hand := FindWindow('Winamp v1.x', nil);
  99. if hand <> 0 then begin
  100. memLoc := SendMessage(hand, WM_WINAMP, 0, 125); // Get number of current track
  101. memLoc := SendMessage(hand, WM_WINAMP, memLoc, 211); // And now its filename
  102. GetWindowThreadProcessId(hand, @tempHand);
  103. readhand := OpenProcess(PROCESS_ALL_ACCESS, False, tempHand);
  104. ReadProcessMemory(readhand, Pointer(memLoc), @C, sizeof(C)-1, temp);
  105. extinfo.filename := C;
  106. extinfo.metadata := metadata;
  107. extinfo.ret := B;
  108. extinfo.retlen := sizeof(B)-1;
  109. // This doesn't actually work yet :/
  110. // memPtr is nil
  111. memPtr := VirtualAllocEx(tempHand, nil, 2048, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  112. if memPtr <> nil then begin
  113. WriteProcessMemory(readhand, memPtr, (@extinfo), sizeof(extendedFileInfoStruct), temp);
  114. SendMessage(readhand, WM_WINAMP, LongInt(memPtr), 290);
  115. end;
  116. StrCopy(Result, B);
  117. if memPtr <> nil then begin
  118. VirtualFreeEx(readhand, memPtr, 0, MEM_RELEASE);
  119. end;
  120. CloseHandle(readhand);
  121. end;
  122. end;
  123. function getArtist(data: PChar):integer; stdcall;
  124. var
  125. B: PChar;
  126. begin
  127. B := getMetaData('artist');
  128. StrCopy(data,B);
  129. if (B <> '') then Result := 0 else Result := 1;
  130. end;
  131. function getTitle(data: PChar):integer; stdcall;
  132. var
  133. B: PChar;
  134. begin
  135. B := getMetaData('title');
  136. StrCopy(data,B);
  137. if (B <> '') then Result := 0 else Result := 1;
  138. end;
  139. function getAlbum(data: PChar):integer; stdcall;
  140. var
  141. B: PChar;
  142. begin
  143. B := getMetaData('album');
  144. StrCopy(data,B);
  145. if (B <> '') then Result := 0 else Result := 1;
  146. end;
  147. function getLength(data: PChar):integer; stdcall;
  148. var
  149. hand: THandle;
  150. res: LongInt;
  151. begin
  152. result := 1;
  153. StrCopy(data, 'Error finding window');
  154. hand := FindWindow('Winamp v1.x', nil);
  155. if hand <> 0 then begin
  156. result := 0;
  157. res := SendMessage(hand, WM_WINAMP, 1, 105);
  158. StrCopy(data, PChar(inttostr(res)));
  159. end;
  160. end;
  161. function getTime(data: PChar):integer; stdcall;
  162. var
  163. hand: THandle;
  164. res: LongInt;
  165. begin
  166. result := 1;
  167. StrCopy(data, 'Error finding window');
  168. hand := FindWindow('Winamp v1.x', nil);
  169. if hand <> 0 then begin
  170. result := 0;
  171. res := SendMessage(hand, WM_WINAMP, 0, 105);
  172. StrCopy(data, PChar(inttostr(res div 1000)));
  173. end;
  174. end;
  175. function getFormat(data: PChar):integer; stdcall;
  176. var
  177. B: array[0..255] of char;
  178. begin
  179. Result := 0;
  180. B := 'Unknown';
  181. StrCopy(data,B);
  182. end;
  183. function getBitrate(data: PChar):integer; stdcall;
  184. var
  185. hand: THandle;
  186. res: LongInt;
  187. begin
  188. result := 1;
  189. StrCopy(data, 'Error finding window');
  190. hand := FindWindow('Winamp v1.x', nil);
  191. if hand <> 0 then begin
  192. result := 0;
  193. res := SendMessage(hand, WM_WINAMP, 1, 126);
  194. StrCopy(data, PChar(inttostr(res)));
  195. end;
  196. end;
  197. exports getPlayState, getArtistTitle, getArtist, getTitle, getAlbum, getLength, getTime, getFormat, getBitrate;
  198. begin
  199. end.