Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4 | daniel-mar | 1 | { |
2 | SXMedia Components - Beta 1 |
||
3 | -------------------------------- |
||
4 | Copyright 1999 Dean Ellis |
||
5 | http://www.sillex.freeserve.co.uk |
||
6 | |||
7 | This unit is part of the SXMedia Component Set. This code is |
||
8 | supplied as is with no guarantees and must be used at your own |
||
9 | risk. |
||
10 | |||
11 | No modifications to this code must be made without the express |
||
12 | permission of the author. Please report any problems to |
||
13 | support@sillex.freeserve.co.uk |
||
14 | |||
15 | You may use these components to create any freeware/shareware |
||
16 | applications that you wish. If the components are to be used in |
||
17 | a commercail product then credit for developement of these components |
||
18 | should be given. |
||
19 | |||
20 | Credits : |
||
21 | |||
22 | Developer : Dean Ellis |
||
23 | Testers : Dominique Louis |
||
24 | Ivan Blecic |
||
25 | } |
||
26 | unit SXMovie; |
||
27 | |||
28 | {$INCLUDE DelphiXcfg.inc} |
||
29 | |||
30 | interface |
||
31 | |||
32 | uses |
||
33 | Windows, Classes, SysUtils, ActiveX, Math, Dialogs, |
||
34 | DXSounds, DXDraws, |
||
35 | {$IFDEF StandardDX} |
||
36 | DirectDraw, DirectSound, DirectShow9, |
||
37 | {$IFDEF DX7} |
||
38 | {$IFDEF D3DRM} |
||
39 | Direct3DRM, |
||
40 | {$ENDIF} |
||
41 | Direct3D; |
||
42 | {$ENDIF} |
||
43 | {$IFDEF DX9} |
||
44 | Direct3D9, Direct3D, D3DX9, {Direct3D8,} DX7toDX8; |
||
45 | {$ENDIF} |
||
46 | {$ELSE} |
||
47 | DShow, DirectX; |
||
48 | {$ENDIF} |
||
49 | |||
50 | type |
||
51 | TMovieOptions = (VideoAndSound, VideoOnly); |
||
52 | TDisplay = (FullScreen, WideScreen, OriginalSize); |
||
53 | |||
54 | TScreenRect = class(TPersistent) |
||
55 | private |
||
56 | FLeft: integer; |
||
57 | FRight: integer; |
||
58 | FTop: integer; |
||
59 | FBottom: integer; |
||
60 | procedure SetLeft(Value: integer); |
||
61 | procedure SetRight(Value: integer); |
||
62 | procedure SetTop(Value: integer); |
||
63 | procedure SetBottom(Value: integer); |
||
64 | protected |
||
65 | public |
||
66 | procedure Assign(Value: TScreenRect); |
||
67 | published |
||
68 | property Left: integer read FLeft write SetLeft; |
||
69 | property Right: integer read FRight write SetRight; |
||
70 | property Top: integer read FTop write SetTop; |
||
71 | property Bottom: integer read FBottom write SetBottom; |
||
72 | end; |
||
73 | |||
74 | |||
75 | TSXMovie = class; |
||
76 | |||
77 | TMovieThread = class(TThread) |
||
78 | private |
||
79 | { Private declarations } |
||
80 | FSXMovie: TSXMovie; |
||
81 | protected |
||
82 | procedure Execute; override; |
||
83 | public |
||
84 | property SXMovie: TSXMovie read FSXMovie write FSXMovie; |
||
85 | end; |
||
86 | |||
87 | TSXMovie = class(TComponent) |
||
88 | private |
||
89 | FMovieThread: TMovieThread; |
||
90 | FDXDraw: TDXDraw; |
||
91 | FDXSound: TDXSound; |
||
92 | FMMStream: IMultiMediaStream; |
||
93 | FPrimaryVidStream: IMediaStream; |
||
94 | FDDStream: IDirectDrawMediaStream; |
||
95 | FSample: IDirectDrawStreamSample; |
||
96 | FSurface: IDirectDrawSurface; |
||
97 | FDXSurface: TDirectDrawSurface; |
||
98 | FRect: TRect; |
||
99 | FDestRect: TRect; |
||
100 | FScreenRect: TScreenRect; |
||
101 | FFilename: TFilename; |
||
102 | FPlaying: Boolean; |
||
103 | FDoFlip: Boolean; |
||
104 | {Event} |
||
105 | FOnMovieEnd: TNotifyEvent; |
||
106 | FOnBeforeRender: TNotifyEvent; |
||
107 | FOnAfterRender: TNotifyEvent; |
||
108 | procedure SetFilename(Value: TFilename); |
||
109 | procedure SetScreenRect(Value: TScreenRect); |
||
110 | procedure DoMovieEnd; |
||
111 | procedure DoBeforeRender; |
||
112 | procedure DoAfterRender; |
||
113 | protected |
||
114 | procedure Notification(AComponent: TComponent; Operation: TOperation); override; |
||
115 | procedure SetMovieStateRun; |
||
116 | procedure SetMovieStateStop; |
||
117 | procedure CreateMediaStream; virtual; |
||
118 | procedure SetupMediaSample; virtual; |
||
119 | public |
||
120 | constructor Create(AOwner: TComponent); override; |
||
121 | destructor Destroy; override; |
||
122 | procedure UpDate; virtual; |
||
123 | // function SetDisplay(Value:TDisplay):Boolean; |
||
124 | procedure DisplayRect(Top, Left, Right, Bottom: integer); |
||
125 | procedure Play; |
||
126 | procedure Stop; |
||
127 | {} |
||
128 | published |
||
129 | property DXDraw: TDXDraw read FDXDraw write FDXDraw; |
||
130 | property DXSound: TDXSound read FDXSound write FDXSound; |
||
131 | property Filename: TFilename read FFilename write SetFilename; |
||
132 | property Playing: Boolean read FPlaying; |
||
133 | property DoFlip: Boolean read FDoFlip write FDoFlip; |
||
134 | property DestinationRectangle: TScreenRect read FScreenRect write SetScreenRect; |
||
135 | property OnMovieEnd: TNotifyEvent read FOnMovieEnd write FOnMovieEnd; |
||
136 | property OnBeforeRender: TNotifyEvent read FOnBeforeRender write FOnBeforeRender; |
||
137 | property OnAfterRender: TNotifyEvent read FOnAfterRender write FOnAfterRender; |
||
138 | end; |
||
139 | |||
140 | implementation |
||
141 | |||
142 | uses Graphics; |
||
143 | |||
144 | procedure TScreenRect.SetLeft(Value: integer); |
||
145 | begin |
||
146 | FLeft := Value; |
||
147 | end; |
||
148 | |||
149 | procedure TScreenRect.SetRight(Value: integer); |
||
150 | begin |
||
151 | FRight := Value; |
||
152 | end; |
||
153 | |||
154 | procedure TScreenRect.SetTop(Value: integer); |
||
155 | begin |
||
156 | FTop := Value; |
||
157 | end; |
||
158 | |||
159 | procedure TScreenRect.SetBottom(Value: integer); |
||
160 | begin |
||
161 | FBottom := Value; |
||
162 | end; |
||
163 | |||
164 | procedure TScreenRect.Assign(Value: TScreenRect); |
||
165 | begin |
||
166 | Left := Value.Left; |
||
167 | Right := Value.Right; |
||
168 | Top := Value.Top; |
||
169 | Bottom := Value.Bottom; |
||
170 | end; |
||
171 | |||
172 | { Important: Methods and properties of objects in VCL can only be used in a |
||
173 | method called using Synchronize, for example, |
||
174 | |||
175 | Synchronize(UpdateCaption); |
||
176 | |||
177 | and UpdateCaption could look like, |
||
178 | |||
179 | procedure TMovieThread.UpdateCaption; |
||
180 | begin |
||
181 | Form1.Caption := 'Updated in a thread'; |
||
182 | end; } |
||
183 | |||
184 | { TMovieThread } |
||
185 | |||
186 | procedure TMovieThread.Execute; |
||
187 | begin |
||
188 | { Place thread code here } |
||
189 | if Assigned(SXMovie) then |
||
190 | SXMovie.SetMovieStateRun; |
||
191 | while (not Terminated) and Assigned(SXMovie) do |
||
192 | begin |
||
193 | Synchronize(SXMovie.UpDate) |
||
194 | end; |
||
195 | if Assigned(SXMovie) then |
||
196 | SXMovie.SetMovieStateStop; |
||
197 | end; |
||
198 | |||
199 | {SXMovie} |
||
200 | |||
201 | procedure TSXMovie.SetFilename(Value: TFilename); |
||
202 | begin |
||
203 | if Value <> '' then |
||
204 | FFilename := Value; |
||
205 | end; |
||
206 | |||
207 | procedure TSXMovie.SetScreenRect(Value: TScreenRect); |
||
208 | begin |
||
209 | FScreenRect.Assign(Value); |
||
210 | end; |
||
211 | |||
212 | procedure TSXMovie.DoMovieEnd; |
||
213 | begin |
||
214 | if Assigned(FOnMovieEnd) then FOnMovieEnd(Self); |
||
215 | end; |
||
216 | |||
217 | procedure TSXMovie.DoBeforeRender; |
||
218 | begin |
||
219 | if Assigned(FOnBeforeRender) then FOnBeforeRender(Self); |
||
220 | end; |
||
221 | |||
222 | procedure TSXMovie.DoAfterRender; |
||
223 | begin |
||
224 | if Assigned(FOnAfterRender) then FOnAfterRender(Self); |
||
225 | end; |
||
226 | |||
227 | procedure TSXMovie.Notification(AComponent: TComponent; Operation: TOperation); |
||
228 | begin |
||
229 | if Operation = opRemove then |
||
230 | begin |
||
231 | if AComponent is TDXDraw then FDXDraw := nil; |
||
232 | if AComponent is TDXSound then FDXSound := nil; |
||
233 | end; |
||
234 | inherited; |
||
235 | end; |
||
236 | |||
237 | procedure TSXMovie.SetMovieStateRun; |
||
238 | begin |
||
239 | try |
||
240 | if FMMStream.SetState(STREAMSTATE_RUN) <> S_OK then |
||
241 | Exception.Create('Set Movie State Run Exception'); |
||
242 | except |
||
243 | end; |
||
244 | end; |
||
245 | |||
246 | procedure TSXMovie.SetMovieStateStop; |
||
247 | begin |
||
248 | try |
||
249 | FMMStream.SetState(STREAMSTATE_STOP); |
||
250 | finally |
||
251 | FPlaying := False; |
||
252 | end; |
||
253 | end; |
||
254 | |||
255 | procedure TSXMovie.CreateMediaStream; |
||
256 | var |
||
257 | wPath:{$IFDEF UNICODE}array of Char{$ELSE}array[0..MAX_PATH] of WChar{$ELSE}{$ENDIF}; |
||
258 | AMStream:IAMMultiMediaStream; |
||
259 | Media:IMediaStream; |
||
260 | begin |
||
261 | Media := nil; |
||
262 | AMStream := nil; |
||
263 | try |
||
264 | CoCreateinstance(CLSID_AMMULTIMEDIASTREAM,nil,CLSCTX_INPROC_SERVER,IID_IAMMULTIMEDIASTREAM,AMStream); |
||
265 | {$IFDEF UNICODE} |
||
266 | SetLength(wPath, Length(Filename) + 1); |
||
267 | StrPCopy(@wPath, Filename); |
||
268 | {$ELSE} |
||
269 | MultiByteToWideChar(CP_ACP,0,PAnsiChar(Filename),-1,wPath,Sizeof(wPAth) div sizeof(wPath[0])); |
||
270 | {$ENDIF} |
||
271 | AMStream.Initialize(STREAMTYPE_READ,AMMSF_NOGRAPHTHREAD,nil); |
||
272 | if (DXSound <> nil) and (DXSound.DSound <> nil) and (DXSound.DSound.ISound <> nil) then |
||
273 | AMStream.AddMediaStream(DXSound.DSound.ISound,{$IFDEF UNICODE}@{$ENDIF}MSPID_PrimaryAudio,AMMSF_ADDDEFAULTRENDERER,IMediaStream(nil^)); |
||
274 | AMStream.AddMediaStream(DXDraw.DDraw.IDraw,{$IFDEF UNICODE}@{$ENDIF}MSPID_PrimaryVideo,0,Media); |
||
275 | AMStream.OpenFile({$IFDEF UNICODE}@{$ENDIF}wPAth,0); |
||
276 | FMMStream := AMStream; |
||
277 | except |
||
278 | FMMStream := nil; |
||
279 | end; |
||
280 | end; |
||
281 | |||
282 | procedure TSXMovie.SetupMediaSample; |
||
283 | begin |
||
284 | try |
||
285 | FSample := nil; |
||
286 | FDDStream := nil; |
||
287 | FPrimaryVidStream := nil; |
||
288 | if FMMStream.GetMediaStream(MSPID_PrimaryVideo, FPrimaryVidStream) <> S_OK then Exit; |
||
289 | if FPrimaryVidStream.QueryInterface(IID_IDirectDrawMediaStream, FDDStream) <> S_OK then Exit; |
||
290 | if FDDStream.CreateSample(nil, PRect(nil)^, 0, FSample) <> S_OK then Exit; |
||
291 | FDXSurface := TDirectDrawSurface.Create(FDXDraw.DDraw); |
||
292 | if FSample.GetSurface(FSurface, FRect) <> S_OK then Exit; |
||
293 | FDXSurface.IDDSurface := FSurface; |
||
294 | except |
||
295 | |||
296 | end; |
||
297 | end; |
||
298 | |||
299 | procedure TSXMovie.UpDate; |
||
300 | function AspectRatio(SourceRect: TRect; var DestRect: TRect): Boolean; |
||
301 | var |
||
302 | SourceWidth, SourceHeight, DestWidth, DestHeight: Integer; |
||
303 | SourceRatio, DestRatio: Double; |
||
304 | begin |
||
305 | Result := False; |
||
306 | SourceWidth := SourceRect.Right - SourceRect.Left; |
||
307 | SourceHeight := SourceRect.Bottom - SourceRect.Top; |
||
308 | SourceRatio := SourceWidth/SourceHeight; |
||
309 | |||
310 | DestWidth := DestRect.Right - DestRect.Left; |
||
311 | DestHeight := DestRect.Bottom - DestRect.Top; |
||
312 | DestRatio := DestWidth/DestHeight; |
||
313 | if SourceRatio <> DestRatio then |
||
314 | begin |
||
315 | if DestWidth > DestHeight then |
||
316 | DestRect.Bottom := DestRect.Top + Round(DestWidth / SourceRatio) |
||
317 | else |
||
318 | DestRect.Right := DestRect.Left + Round(SourceRatio * DestHeight); |
||
319 | Result := True; |
||
320 | end; |
||
321 | end; |
||
322 | var |
||
323 | R: TRect; |
||
324 | Q: HResult; |
||
325 | begin |
||
326 | try |
||
327 | Q := FSample.Update(0, 0, nil, 0); |
||
328 | case Q of |
||
329 | HResult(MS_S_PENDING):; |
||
330 | HResult(MS_S_NOUPDATE):; |
||
331 | HResult(MS_S_ENDOFSTREAM):; |
||
332 | end; |
||
333 | if Q <> S_OK then |
||
334 | begin |
||
335 | FMovieThread.Terminate; |
||
336 | SetMovieStateStop; |
||
337 | FPlaying := False; |
||
338 | DoMovieEnd; |
||
339 | Exit; |
||
340 | end; |
||
341 | if (FSurface <> nil) and DXDraw.CanDraw then |
||
342 | begin |
||
343 | DoBeforeRender; |
||
344 | R := FDestRect; |
||
345 | if AspectRatio(FRect, R) then |
||
346 | FDestRect := R; |
||
347 | DXDraw.Surface.StretchDraw(FDestRect, FRect, FDXSurface, False); |
||
348 | with DXDraw.Surface.Canvas do |
||
349 | begin |
||
350 | Brush.Style := bsClear; |
||
351 | Font.Color := clWhite; |
||
352 | Font.Size := 8; |
||
353 | Textout(5, 5, 'SilleX Media - Beta 1'); |
||
354 | Release; |
||
355 | end; |
||
356 | DoAfterRender; |
||
357 | if DoFlip then |
||
358 | DXDraw.Flip; |
||
359 | end; |
||
360 | except |
||
361 | on E: Exception do |
||
362 | ShowMessage(E.Message); |
||
363 | end; |
||
364 | end; |
||
365 | |||
366 | procedure TSXMovie.DisplayRect(Top, Left, Right, Bottom: integer); |
||
367 | begin |
||
368 | if not (csDesigning in ComponentState) then |
||
369 | begin |
||
370 | FScreenRect.Top := Top; |
||
371 | FSCreenRect.Left := Left; |
||
372 | FScreenRect.Right := Right; |
||
373 | FScreenRect.Bottom := Bottom; |
||
374 | end; |
||
375 | end; |
||
376 | |||
377 | procedure TSXMovie.Play; |
||
378 | begin |
||
379 | if not (csDesigning in ComponentState) then |
||
380 | begin |
||
381 | FDestRect.Left := FScreenRect.Left; |
||
382 | FDestRect.Right := FScreenRect.Right; |
||
383 | FDestRect.Top := FScreenRect.Top; |
||
384 | FDestRect.Bottom := FScreenRect.Bottom; |
||
385 | FPlaying := True; |
||
386 | CreateMediaStream; |
||
387 | SetupMediaSample; |
||
388 | if FSample <> nil then |
||
389 | begin |
||
390 | FMovieThread := TMovieThread.Create(True); |
||
391 | if Assigned(FMovieThread) then |
||
392 | begin |
||
393 | FMovieThread.FreeOnTerminate := False; |
||
394 | FMovieThread.SXMovie := Self; |
||
395 | FMovieThread.Resume; |
||
396 | end; |
||
397 | end; |
||
398 | end; |
||
399 | end; |
||
400 | |||
401 | procedure TSXMovie.Stop; |
||
402 | begin |
||
403 | if not (csDesigning in ComponentState) then |
||
404 | begin |
||
405 | FPlaying := False; |
||
406 | if Assigned(FMovieThread) then |
||
407 | begin |
||
408 | if not FMovieThread.Terminated then |
||
409 | begin |
||
410 | FMovieThread.Terminate; |
||
411 | DoMovieEnd; |
||
412 | end; |
||
413 | FMovieThread.Free; |
||
414 | FMovieThread := nil; |
||
415 | end; |
||
416 | if FDXSurface <> nil then |
||
417 | begin |
||
418 | FDXSurface.Free; |
||
419 | FSurface := nil; |
||
420 | end; |
||
421 | end; |
||
422 | end; |
||
423 | |||
424 | constructor TSXMovie.Create(AOwner: TComponent); |
||
425 | begin |
||
426 | inherited Create(AOwner); |
||
427 | FScreenRect := TScreenRect.Create; |
||
428 | CoInitialize(nil); |
||
429 | end; |
||
430 | |||
431 | destructor TSXMovie.Destroy; |
||
432 | begin |
||
433 | if not (csDesigning in ComponentState) then |
||
434 | begin |
||
435 | FPlaying := False; |
||
436 | if Assigned(FMovieThread) then |
||
437 | begin |
||
438 | if not FMovieThread.Terminated then |
||
439 | FMovieThread.Terminate; |
||
440 | FMovieThread.Free; |
||
441 | FMovieThread := nil; |
||
442 | end; |
||
443 | if Assigned(FSample) then |
||
444 | FSample := nil; |
||
445 | if Assigned(FDDStream) then |
||
446 | FDDStream := nil; |
||
447 | if Assigned(FPrimaryVidStream) then |
||
448 | FPrimaryVidStream := nil; |
||
449 | if Assigned(FMMStream) then |
||
450 | FMMStream := nil; |
||
451 | if Assigned(FSurface) then |
||
452 | FSurface := nil; |
||
453 | end; |
||
454 | FScreenRect.Free; |
||
455 | CoUnInitialize; |
||
456 | inherited; |
||
457 | end; |
||
458 | |||
459 | end. |
||
460 |