Unit1.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. {========================================================================}
  2. {= (c) 1995-98 SwiftSoft Ronald Dittrich =}
  3. {========================================================================}
  4. {= All Rights Reserved =}
  5. {========================================================================}
  6. {= D 01099 Dresden = Fax.: +49(0)351-8037944 =}
  7. {= Loewenstr.7a = info@swiftsoft.de =}
  8. {========================================================================}
  9. {= Actual versions on http://www.swiftsoft.de/index.html =}
  10. {========================================================================}
  11. {= This code is for reference purposes only and may not be copied or =}
  12. {= distributed in any format electronic or otherwise except one copy =}
  13. {= for backup purposes. =}
  14. {= =}
  15. {= No Delphi Component Kit or Component individually or in a collection=}
  16. {= subclassed or otherwise from the code in this unit, or associated =}
  17. {= .pas, .dfm, .dcu, .asm or .obj files may be sold or distributed =}
  18. {= without express permission from SwiftSoft. =}
  19. {= =}
  20. {= For more licence informations please refer to the associated =}
  21. {= HelpFile. =}
  22. {========================================================================}
  23. {= $Date: 17.09.98 - 16:28:36 $ =}
  24. {========================================================================}
  25. unit Unit1;
  26. interface
  27. uses
  28. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  29. MMUtils, MMHTimer, StdCtrls, MMObj, MMCstDlg, MMDIBCv, MMLevel, MMConect,
  30. MMDesign, MMRingBf, MMDSPObj, MMWavOut, MMWave, MMWMixer, ExtCtrls,
  31. MMHook, MMAudio;
  32. type
  33. PListItem = ^TListItem;
  34. TListItem = record
  35. FileName: string;
  36. Position: Longint;
  37. Length : Longint;
  38. end;
  39. TMainForm = class(TForm)
  40. WaveMixer: TMMWaveMixer;
  41. WaveOut: TMMWaveOut;
  42. RingBuffer: TMMRingBuffer;
  43. MMDesigner1: TMMDesigner;
  44. MMConnector1: TMMConnector;
  45. Level1: TMMLevel;
  46. Level2: TMMLevel;
  47. btnStart: TButton;
  48. btnStop: TButton;
  49. btnFile: TButton;
  50. Label1: TLabel;
  51. lblPosition: TLabel;
  52. Timer: TMMHiTimer;
  53. PlayListBox: TListBox;
  54. Header: THeader;
  55. AudioFile1: TMMAudioFile;
  56. AudioFile2: TMMAudioFile;
  57. TempFile: TMMAudioFile;
  58. OpenDialog: TOpenDialog;
  59. procedure TimerTimer(Sender: TObject);
  60. procedure btnStartClick(Sender: TObject);
  61. procedure btnStopClick(Sender: TObject);
  62. procedure WaveOutStart(Sender: TObject);
  63. procedure WaveOutStop(Sender: TObject);
  64. procedure FormCreate(Sender: TObject);
  65. procedure FormDestroy(Sender: TObject);
  66. procedure btnFileClick(Sender: TObject);
  67. procedure WaveMixerClosePort(Sender: TObject; index: Integer);
  68. procedure HeaderSized(Sender: TObject; ASection, AWidth: Integer);
  69. procedure PlayListBoxDrawItem(Control: TWinControl;
  70. Index: Integer; Rect: TRect;
  71. State: TOwnerDrawState);
  72. procedure FormClose(Sender: TObject; var Action: TCloseAction);
  73. public
  74. PlayList: TList;
  75. PlayIndex: integer;
  76. CurrentFile: integer;
  77. LastEndTime: int64;
  78. end;
  79. var
  80. MainForm: TMainForm;
  81. implementation
  82. {$R *.DFM}
  83. // NOTE: Maximal playbacktime of TMMWaveOut is ~3.5 hours, then it will stop.
  84. // The Windows MMSystem works with 32 bit positions and they will overflow
  85. // if the 32 bit value is wrapped so we stop the device. It's always a good
  86. // idea to close and restart the device every 2-3 hours.
  87. // This limitation is removed in the Delphi 4 version !
  88. {-- TMainForm -----------------------------------------------------------------}
  89. procedure TMainForm.FormCreate(Sender: TObject);
  90. begin
  91. PlayList := TList.Create;
  92. end;
  93. {-- TMainForm -----------------------------------------------------------------}
  94. procedure TMainForm.FormDestroy(Sender: TObject);
  95. var
  96. i: integer;
  97. begin
  98. for i := PlayList.Count-1 downto 0 do
  99. begin
  100. Dispose(PlayList[i]);
  101. PlayList.Delete(i);
  102. end;
  103. PlayList.Free;
  104. end;
  105. {-- TMainForm -----------------------------------------------------------------}
  106. procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
  107. begin
  108. WaveOut.Close;
  109. end;
  110. {-- TMainForm -----------------------------------------------------------------}
  111. procedure TMainForm.TimerTimer(Sender: TObject);
  112. begin
  113. lblPosition.Caption := TimeToString64(WaveOut.Position,WaveOut.PositionHigh,True);
  114. { update the ListBox }
  115. if PlayListBox.ItemIndex <> CurrentFile then PlayListBox.ItemIndex := CurrentFile;
  116. end;
  117. {-- TMainForm -----------------------------------------------------------------}
  118. procedure TMainForm.btnStartClick(Sender: TObject);
  119. begin
  120. PlayIndex := 0;
  121. if PlayIndex < PlayList.Count then
  122. begin
  123. // You can also set the maxPlayTime here if you know how much is to play
  124. { WaveMixer.MaxPlayTime := PListItem(PlayList[PlayList.Count-1]).Position+
  125. PListItem(PlayList[PlayList.Count-1]).Length;}
  126. AudioFile1.FileName := PListItem(PlayList[PlayIndex]).FileName;
  127. WaveMixer.StartPos1 := PListItem(PlayList[PlayIndex]).Position;
  128. { remember the end position for this file }
  129. LastEndTime := WaveMixer.StartPos1 + AudioFile1.FileLength;
  130. inc(PlayIndex);
  131. end;
  132. if PlayIndex < PlayList.Count then
  133. begin
  134. AudioFile2.FileName := PListItem(PlayList[PlayIndex]).FileName;
  135. WaveMixer.StartPos2 := PListItem(PlayList[PlayIndex]).Position;
  136. { remember the end position for this file }
  137. LastEndTime := WaveMixer.StartPos2 + AudioFile2.FileLength;
  138. inc(PlayIndex);
  139. end;
  140. if PlayIndex > 0 then PlayListBox.ItemIndex := 0;
  141. CurrentFile := 0;
  142. WaveOut.Start;
  143. end;
  144. {-- TMainForm -----------------------------------------------------------------}
  145. procedure TMainForm.btnStopClick(Sender: TObject);
  146. begin
  147. WaveOut.Close;
  148. end;
  149. {-- TMainForm -----------------------------------------------------------------}
  150. procedure TMainForm.WaveOutStart(Sender: TObject);
  151. begin
  152. Timer.Enabled := True;
  153. btnFile.Enabled := False;
  154. btnStart.Enabled := False;
  155. end;
  156. {-- TMainForm -----------------------------------------------------------------}
  157. procedure TMainForm.WaveOutStop(Sender: TObject);
  158. begin
  159. Timer.Enabled := False;
  160. btnFile.Enabled := True;
  161. btnStart.Enabled := True;
  162. end;
  163. {-- TMainForm -----------------------------------------------------------------}
  164. procedure TMainForm.WaveMixerClosePort(Sender: TObject; index: Integer);
  165. begin
  166. { the WaveMixer has closed a port, the files was done... }
  167. { other files to play ??? }
  168. if PlayIndex < PlayList.Count then
  169. begin
  170. if index = 0 then
  171. begin
  172. { set the next file and Position }
  173. AudioFile1.FileName := PListItem(PlayList[PlayIndex]).FileName;
  174. WaveMixer.StartPos1 := PListItem(PlayList[PlayIndex]).Position;
  175. { remember the total endposition for this file }
  176. LastEndTime := WaveMixer.StartPos1 + AudioFile1.FileLength;
  177. end
  178. else if index = 1 then
  179. begin
  180. { set the next file and Position }
  181. AudioFile2.FileName := PListItem(PlayList[PlayIndex]).FileName;
  182. WaveMixer.StartPos2 := PListItem(PlayList[PlayIndex]).Position;
  183. { remember the total endposition for this file }
  184. LastEndTime := WaveMixer.StartPos2 + AudioFile2.FileLength;
  185. end;
  186. { Notify the WaveMixer that the Input has changed }
  187. WaveMixer.InputDone[index] := False;
  188. inc(PlayIndex);
  189. end
  190. else
  191. { no other file to play, set MaxPlayTime }
  192. { so WaveOut stops if the last file is done }
  193. WaveMixer.MaxPlayTime := LastEndTime;
  194. CurrentFile := CurrentFile+1;
  195. end;
  196. {-- TMainForm -----------------------------------------------------------------}
  197. procedure TMainForm.btnFileClick(Sender: TObject);
  198. const
  199. CrossFadeTime = 2500; {ms}
  200. var
  201. NewItem: PListItem;
  202. Pos,Len: Longint;
  203. i: integer;
  204. begin
  205. { setup a simple playlist so we can demonstrate how to handle it }
  206. if OpenDialog.Execute then
  207. begin
  208. for i := 0 to OpenDialog.Files.Count-1 do
  209. begin
  210. TempFile.FileName := OpenDialog.Files[i];
  211. Len := TempFile.FileLength;
  212. if (PlayList.Count > 0) then
  213. with PListItem(PlayList[PlayList.Count-1])^ do
  214. Pos := Max(Position+Length-CrossFadeTime,0)
  215. else
  216. Pos := 0;
  217. New(NewItem);
  218. with NewItem^ do
  219. begin
  220. FileName := TempFile.FileName;
  221. Length := Len;
  222. Position := Pos;
  223. end;
  224. PlayList.Add(NewItem);
  225. PlayListBox.Items.Add(NewItem.FileName+'|'+TimeToString(Pos)+'|'+TimeToString(Len));
  226. end;
  227. end;
  228. end;
  229. {-- TMainForm -----------------------------------------------------------------}
  230. procedure TMainForm.PlayListBoxDrawItem(Control: TWinControl;
  231. Index: Integer; Rect: TRect;
  232. State: TOwnerDrawState);
  233. var
  234. P: Integer;
  235. R: TRect;
  236. C: array[0..255] of Char;
  237. S,S2: string;
  238. begin
  239. R := Rect;
  240. { find the separator in the string }
  241. P := Pos('|', PlayListBox.Items[Index]);
  242. { draw the name }
  243. S := Copy(PlayListBox.Items[Index], 1, P - 1);
  244. R.Right := R.Left + (Header.SectionWidth[0]);
  245. ExtTextOut(PlayListBox.Canvas.Handle, R.Left, R.Top, ETO_CLIPPED or
  246. ETO_OPAQUE, @R, StrPCopy(C, S), Length(S), nil);
  247. S2 := Copy(PlayListBox.Items[Index], P+1, Length(PlayListBox.Items[Index])-P);
  248. P := Pos('|', S2);
  249. S := Copy(S2, 1, P - 1);
  250. { move the rectangle to the next column }
  251. R.Left := R.Left + (Header.SectionWidth[0]);
  252. R.Right:= R.Left + Header.SectionWidth[1];
  253. ExtTextOut(PlayListBox.Canvas.Handle, R.Left, R.Top, ETO_CLIPPED or
  254. ETO_OPAQUE, @R, StrPCopy(C, S), Length(S), nil);
  255. S := Copy(S2, P+1, Length(S2)-P);
  256. { move the rectangle to the next column }
  257. R.Left := R.Left + Header.SectionWidth[1];
  258. R.Right:= R.Left + Header.SectionWidth[2];
  259. ExtTextOut(PlayListBox.Canvas.Handle, R.Left, R.Top, ETO_CLIPPED or
  260. ETO_OPAQUE, @R, StrPCopy(C, S), Length(S), nil);
  261. end;
  262. {-- TMainForm -----------------------------------------------------------------}
  263. procedure TMainForm.HeaderSized(Sender: TObject; ASection, AWidth: Integer);
  264. begin
  265. PlayListBox.Invalidate;
  266. end;
  267. end.