6 Windows
, MMSystem
, KOL
;
9 {#Replace[= object(][= class(]}
10 {#Replace[@Self][Self]}
11 {#Replace[@ Self][Self]}
14 { -- MultiMedia player object -- }
18 {++}(*TMediaPlayer = class;*){--}
19 PMediaPlayer
= {-}^{+}TMediaPlayer
;
21 TMPState
= ( mpNotReady
, mpStopped
, mpPlaying
, mpRecording
, mpSeeking
,
23 {* Available states of TMediaPlayer. }
24 TMPDeviceType
= ( mmAutoSelect
, mmVCR
, mmVideodisc
, mmOverlay
, mmCDAudio
, mmDAT
,
25 mmScanner
, mmAVIVideo
, mmDigitalVideo
, mmOther
, mmWaveAudio
,
27 {* Available device types of TMediaPlayer. }
28 TMPTimeFormat
= ( tfMilliseconds
, tfHMS
, tfMSF
, tfFrames
, tfSMPTE24
, tfSMPTE25
,
29 tfSMPTE30
, tfSMPTE30Drop
, tfBytes
, tfSamples
, tfTMSF
);
30 {* Available time formats, used with properties Length and Position. }
31 TMPNotifyValue
= (nvSuccessful
, nvSuperseded
, nvAborted
, nvFailure
);
32 {* Available notification flags, which can be passed to TMediaPlayer.OnNotify
33 event handler (if it is set). }
34 TMPOnNotify
= procedure( Sender
: PMediaPlayer
; NotifyValue
: TMPNotifyValue
) of object;
35 {* Event type for TMediaPlayer.OnNotify event. }
38 TSoundChannel
= ( chLeft
, chRight
);
39 {* Available sound channels. }
40 TSoundChannels
= set of TSoundChannel
;
41 {* Set of available sound channels. }
43 { ----------------------------------------------------------------------
47 ----------------------------------------------------------------------- }
48 TMediaPlayer
= object( TObj
)
49 {* MediaPlayer incapsulation object. Can open and play any supported
50 by system multimedia file. (To play wave only, it is possible to
51 use functions PlaySound..., which can also play it from memory and
54 Please note, that while debugging, You can get application exception
55 therefore standalone application is working fine. (Such results took
56 place for huge video). )
65 FOnNotify
: TMPOnNotify
;
66 FDeviceType
: TMPDeviceType
;
69 FTimeFormat
: TMPTimeFormat
;
70 FBaseKeyCDAudio
: HKey
;
71 FoldKeyValCDData
: DWORD
;
72 FoldKeyValCDAudio
: String;
73 FAutoRestore
: procedure of object;
74 FAudioOff
: array[ TSoundChannel
] of Boolean;
77 function GetErrorMessage
: String;
78 function GetState
: TMPState
;
79 procedure SetPause(const Value
: Boolean);
80 procedure SetTrack(Value
: Integer);
81 function GetCapability( const Index
: Integer ): Boolean;
82 function GetICapability( const Index
: Integer ): Integer;
83 procedure SetDisplay(const Value
: HWND
);
84 function GetDisplayRect
: TRect
;
85 function GetDeviceType
: TMPDeviceType
;
86 procedure SetFileName(const Value
: String);
87 function GetBState( const Index
: Integer ): Boolean;
88 function GetIState( const Index
: Integer ): Integer;
89 function GetPosition
: Integer;
90 procedure SetPosition(Value
: Integer);
91 function GetTimeFormat
: TMPTimeFormat
;
92 procedure SetTimeFormat(const Value
: TMPTimeFormat
);
93 procedure SetDisplayRect(const Value
: TRect
);
94 function GetPause
: Boolean;
95 function GetAudioOn(Chn
: TSoundChannels
): Boolean;
96 procedure SetAudioOn(Chn
: TSoundChannels
; const Value
: Boolean);
97 function GetVideoOn
: Boolean;
98 procedure SetVideoOn(const Value
: Boolean);
99 function DGVGetSpeed
: Integer;
100 procedure DGVSetSpeed(const Value
: Integer);
103 destructor Destroy
; {-}virtual;{+}{++}(*override;*){--}
104 {* Please remember, that if CDAudio (e.g.) is playing, it is not stop
105 playing when TMediaPlayer object destroying unless performing command
109 property FileName
: String read FFileName write SetFileName
;
110 {* Name of file, containing multimedia, if any (some multimedia devices
111 do not require file, corresponding to device rather then file. Such as
112 mmCDAudio, mmScanner, etc. Use in that case DeviceType property to
113 assign to desired type of multimedia and then open it using Open method).
114 When new string is assigned to a FileName, previous media is closed
115 and another one is opened automatically. }
116 property DeviceType
: TMPDeviceType read GetDeviceType write FDeviceType
;
117 {* Type of multimedia. For opened media, real type is returned. If no
118 multimedia (device or file) opened, it is possible to set DeviceType to
119 desired type before opening multimedia. Use such way for opening
120 devices rather then for opening multimedia, stored in files. }
121 property DeviceID
: Integer read FDeviceID
;
122 {* Returns DeviceID, corresponded to opened multimedia (0 is returned
123 if no media opened. }
124 property TimeFormat
: TMPTimeFormat read GetTimeFormat write SetTimeFormat
;
125 {* Time format, used to set/retrieve information about Length or Position.
126 Please note, that not all formats are supported by all multimedia devices.
127 Only tfMilliseconds (is set by default) supported by all devices. Following
128 table shows what devices are supporting certain time formats:
130 |&L=<tr><td>%0</td><td>
132 <L tfMilliseconds> All multimedia device types. <E>
133 <L tfBytes> mmWaveAudio <E>
134 <L tfFrames> mmDigitalVideo <E>
135 <L tfHMS (hours, minutes, seconds)> mmVCR (video cassete recorder), mmVideodisc.
136 It is necessary to parse retrieved Length or Position or to prepare
137 value before assigning it to Position using typecast to THMS. <E>
138 <L tfMSF (minutes, seconds, frames)> mmCDAudio, mmVCR. It is necessary to
139 parse value retrieved from Length or Position properties or value to
140 assign to property Position using typecast to TMSF type. <E>
141 <L tfSamples> mmWaveAudio <E>
142 <L tfSMPTE24, tfSMPTE25, tfSMPTE30, tfSMPTE30DROP (Society of Motion Picture
143 and Television Engineers)> mmVCR, mmSequencer. <E>
144 <L tfTMSF (tracks, minutes, seconds, frames)> mmVCR <E>
146 property Position
: Integer //index MCI_STATUS_POSITION read GetIState
147 read GetPosition write SetPosition
;
148 {* Current position in milliseconds. Even if device contains several tracks,
149 this is the position from starting of first track. To determine position
150 in current Track, subtract TrackStartPosition. }
151 property Track
: Integer read FTrack write SetTrack
;
152 {* Current track (from 1 to TrackCount). Has no sence, if tracks are not
153 supported by opened multimedia device, or no tracks present. }
154 property TrackCount
: Integer index MCI_STATUS_NUMBER_OF_TRACKS read GetIState
;
155 {* Count of tracks for opened multimedia device. If device does not support
156 tracks, or tracks not present (e.g. there are no tracks found on CD),
157 value 1 is returned by system (but this not a rule to determine if
158 tracks are available). }
159 property Length
: Integer index MCI_STATUS_LENGTH read GetIState
;
160 {* Length of multimedia in milliseconds. Even if device has tracks,
161 this the length of entire multimedia. }
162 property Display
: HWnd read FDisplay write SetDisplay
;
163 {* Window to represent animation. It is recommended to create neutral
164 control (e.g. label, or paint box, and assign its TControl.Handle to
165 this property). Has no sense for multimedia, which HasVideo = False
166 (no animation presented). }
167 property DisplayRect
: TRect read GetDisplayRect write SetDisplayRect
;
168 {* Rectangle in Display window, where animation is shown while playing
169 animation. To restore default value, pass Bottom = Top = 0 and Right =
171 property Error
: Integer read FError
;
172 {* Error code. Is set after every operation. If 0, no errors detected. It
173 is also possible to retrieve description string for error using
174 property ErrorMessage. }
175 property ErrorMessage
: String read GetErrorMessage
;
176 {* Brief description of Error. }
177 property State
: TMPState read GetState
;
178 {* Current state of multimedia. }
179 property Pause
: Boolean read GetPause write SetPause
;
180 {* True, if multimedia currently not playing (or not open). Set this property
181 to True to pause playing, and to False to resume. }
182 property Wait
: Boolean read FWait write FWait
;
183 {* True, if operations will be performed synchronously (i.e. execution will
184 be continued only after completing operation). If Wait is False (default),
185 control is returned immediately to application, without waiting of completing
186 of operation. It is possible in that case to get notification about finishing
187 of previous operation in OnNotify event handler (if any has been set). }
189 property TrackStartPosition
: Integer index
$80000000 or MCI_STATUS_POSITION
191 {* Returns given track starting position (in units, specisied by TimeFormat
192 property. E.g., if TimeFormat is set to (default) tfMilliseconds, in
194 property TrackLength
: Integer index
$80000000 or MCI_STATUS_LENGTH read GetIState
;
195 {* Returns given track length (in units, specified by TimeFormat property). }
196 property OnNotify
: TMPOnNotify read FOnNotify write FOnNotify
;
197 {* Called when asynchronous operation completed. (By default property Wait is
198 set to False, so all operations are performed asynchronously, i.e. control
199 is returned to application ithout of waiting of completion operation).
200 Please note, that syatem can make several notifications while performing
201 operation. To determine if operation completed, check State property.
202 E.g., to find where playing is finished, check in OnNotify event handler
203 if State <> mpPlaying.
204 |<br>Though TMediaPlayer works fine with the most of multimedia formats
205 (at least it is tested for WAV, MID, RMI, AVI (video and sound), MP3 (soound),
206 MPG (video and sound) ),
207 there are some problems with getting notifications about finishing MP3
208 playing: when OnNotify is called, State returned is mpPlaying yet. For
209 that case I can advice to check also playing time and compare it with
210 Length of multimedia. }
211 property Width
: Integer read FWidth
;
212 {* Default width of video display (for multimedia, having video animation). }
213 property Height
: Integer read FHeight
;
214 {* Default height of video display (for multimedia, having video animation). }
216 function Open
: Boolean;
217 {* Call this method to open device, which is not correspondent to file. For
218 multimedia, stored in file, Open is called automatically when FileName
221 Multimedia is always trying to be open shareable first. If it is not
222 possible, second attempt is made to open multimedia without sharing. }
223 property Alias
: String read FAlias write FAlias
;
224 {* Alias for opened device. Must be set before opening (before changing
226 function Play( StartPos
, PlayLength
: Integer ): Boolean;
227 {* Call this method to play multimedia. StartPos is relative to
228 starting position of opened multimedia, even if it has tracks. If value
229 passed for StartPos is -1, current position is used to start from.
230 If -1 passed as PlayLength, multimedia is playing to the end of media.
231 Note, that after some operation (including Play) current position is
232 moved and it is necessary to pass 0 as StartPos to play multimedia
233 from its starting position again. To provide playing the same
234 multimedia several times, call:
235 ! with MyMediaPlayer do
237 To Play single track, call:
238 ! with MyMediaPlayer do
240 ! Track := N; // set track to desired number
241 ! Play( TrackStartPosition, TrackLength );
244 {* Closes multimedia. Later it can be reopened using Open method. Please
245 remember, that if CDAudio (e.g.) is playing, it is not stop playing
246 when Close is called. To stop playing, first perform command
249 {* Ejects media from device. It is possible to check first, if this operation
250 is supported by the device - see CanEject. }
252 {* Backward operation to Eject - inserts media to device. This operation is
253 very easy and does not take in consideration if CD data / audio is playing
254 automatically when media is inserted. To prevent launching CD player or
255 application, defined in autostart.inf file in rootof CD, use Insert method
257 procedure DisableAutoPlay
;
258 {* Be careful when using this method - this affects user settings such as 'Autoplay
259 CD audio disk' and 'Autorun CD Data disk'. At least do not forget to restore
260 settings later, using RestoreAutoPlay method. When You use Insert method
261 to insert CD into device, DisableAutoPlay also is called, but in that case
262 restoring is made automatically at least when TMediaPlayer object is
264 procedure RestoreAutoPlay
;
265 {* Restores settings CD autoplay settings, changed by calling DisableAutoPlay
266 method (which must be called earlier to save settings and change it to
267 disable CD autoplay feature). It is not necessary to call RestoreAutoPlay
268 only in case, when method Insert was used to insert CD into device (but
269 calling it restores settings therefore - so it is possible to restore
270 settings not only when object TMediaPlayer destroyed, but earlier. }
272 {* Does the same as DoorClose, but first disables auto play settings, preventing
273 system from running application defined in Autorun.inf (in CD root) or
274 launching CD player application. Such settings will be restored at least
275 when TMediaPlayer object is destroyed, but it is possible to call
276 RestoreAutoPlay earlier (but there is no sence to call it immediately
277 after performing Insert method - at least wait several seconds or start
278 playing track first). }
279 function Save( const aFileName
: String ): Boolean;
280 {* Saves multimedia to a file. Check first, if this operation is supported
282 property Ready
: Boolean index MCI_STATUS_READY read GetBState
;
283 {* True if Device is ready. }
284 function StartRecording( FromPos
, ToPos
: Integer ): Boolean;
285 {* Starts recording. If FromPos is passed -1, recording is starting from
286 current position. If ToPos is passed -1, recording is continuing up
287 to the end of media. }
288 function Stop
: Boolean;
289 {* Stops playing back or recording. }
291 property IsCompoundDevice
: Boolean index MCI_GETDEVCAPS_COMPOUND_DEVICE read GetCapability
;
292 {* True, if device is compound. }
293 property HasVideo
: Boolean index MCI_GETDEVCAPS_HAS_VIDEO read GetCapability
;
294 {* True, if multimedia has videoanimation. }
295 property HasAudio
: Boolean index MCI_GETDEVCAPS_HAS_AUDIO read GetCapability
;
296 {* True, if multimedia contains audio. }
297 property CanEject
: Boolean index MCI_GETDEVCAPS_CAN_EJECT read GetCapability
;
298 {* True, if device supports "open door" and "close door" operations. }
299 property CanPlay
: Boolean index MCI_GETDEVCAPS_CAN_PLAY read GetCapability
;
300 {* True, if multimedia can be played (some of deviceces are only for recording,
302 property CanRecord
: Boolean index MCI_GETDEVCAPS_CAN_RECORD read GetCapability
;
303 {* True, if multimedia can be used to record (video or/and audio). }
304 property CanSave
: Boolean index MCI_GETDEVCAPS_CAN_SAVE read GetCapability
;
305 {* True, if multimedia device supports saving to a file. }
306 property Present
: Boolean index MCI_STATUS_MEDIA_PRESENT read GetBState
;
307 {* True, if CD or videodisc inserted into device. }
309 property AudioOn
[ Chn
: TSoundChannels
]: Boolean read GetAudioOn write SetAudioOn
;
310 {* Returns True, if given audio channels (both if [chLeft,chRight], any if [])
311 are "on". This property also allows to turn desired channels on and off. }
312 property VideoOn
: Boolean read GetVideoOn write SetVideoOn
;
313 {* Returns True, if video is "on". Allows to turn video signal on and off. }
315 //-- for "CDAudio" only:
316 property CDTrackNotAudio
: Boolean index
$80000000 or MCI_CDA_STATUS_TYPE_TRACK read GetBState
;
317 {* True, if current Track is not audio. }
319 //-- for "digitalvideo":
320 property DGV_CanFreeze
: Boolean index
$4002 {MCI_DGV_GETDEVCAPS_CAN_FREEZE} read GetCapability
;
321 {* True, if can freeze. }
322 property DGV_CanLock
: Boolean index
$4000 {MCI_DGV_GETDEVCAPS_CAN_LOCK} read GetCapability
;
323 {* True, if can lock. }
324 property DGV_CanReverse
: Boolean index
$4004 {MCI_DGV_GETDEVCAPS_CAN_REVERSE} read GetCapability
;
325 {* True, if can reverse playing. }
326 property DGV_CanStretchInput
: Boolean index
$4008 {MCI_DGV_GETDEVCAPS_CAN_STR_IN} read GetCapability
;
327 {* True, if can stretch input. }
328 property DGV_CanStretch
: Boolean index
$4001 {MCI_DGV_GETDEVCAPS_CAN_STRETCH} read GetCapability
;
329 {* True, if can stretch output. }
330 property DGV_CanTest
: Boolean index
$4009 {MCI_DGV_GETDEVCAPS_CAN_TEST} read GetCapability
;
331 {* True, if supports Test. }
332 property DGV_HasStill
: Boolean index
$4005 {MCI_DGV_GETDEVCAPS_HAS_STILL} read GetCapability
;
333 {* True, if has still images in video. }
334 property DGV_MaxWindows
: Integer index
$4003 {MCI_DGV_GETDEVCAPS_MAX_WINDOWS} read GetICapability
;
335 {* Returns maximum windows supported. }
336 property DGV_MaxRate
: Integer index
$400A {MCI_DGV_GETDEVCAPS_MAXIMUM_RATE} read GetICapability
;
337 {* Returns maximum possible rate (frames/sec). }
338 property DGV_MinRate
: Integer index
$400B {MCI_DGV_GETDEVCAPS_MINIMUM_RATE} read GetICapability
;
339 {* Returns minimum possible rate (frames/sec). }
341 property DGV_Speed
: Integer read DGVGetSpeed write DGVSetSpeed
;
342 {* Returns speed of digital video as a ratio between the nominal frame
343 rate and the desired frame rate where the nominal frame rate is designated
344 as 1000. Half speed is 500 and double speed is 2000. The allowable speed
345 range is dependent on the device and possibly the file, too. }
347 //-- for AVI only (mmDigitalVideo, AVI-format):
348 property AVI_AudioBreaks
: Integer index
$8003 {MCI_AVI_STATUS_AUDIO_BREAKS} read GetIState
;
349 {* Returns the number of times that the audio definitely broke up.
350 (We count one for every time we're about to write some audio data
351 to the driver, and we notice that it's already played all of the
353 property AVI_FramesSkipped
: Integer index
$8001 {MCI_AVI_STATUS_FRAMES_SKIPPED} read GetIState
;
354 {* Returns number of frames not drawn during last play. If this number
355 is more than a small fraction of the number of frames that should have
356 been displayed, things aren't looking good. }
357 property AVI_LastPlaySpeed
: Integer index
$8002 {MCI_AVI_STATUS_LAST_PLAY_SPEED} read GetIState
;
358 {* Returns a number representing how well the last AVI play worked.
359 A result of 1000 indicates that the AVI sequence took the amount
360 of time to play that it should have; a result of 2000, for instance,
361 would indicate that a 5-second AVI sequence took 10 seconds to play,
362 implying that the audio and video were badly broken up. }
365 //-- for "vcr" (video cassete recorder):
366 property VCR_ClockIncrementRate
: Integer index
$401C {MCI_VCR_GETDEVCAPS_CLOCK_INCREMENT_RATE} read GetICapability
;
368 property VCR_CanDetectLength
: Boolean index
$4001 {MCI_VCR_GETDEVCAPS_CAN_DETECT_LENGTH} read GetCapability
;
369 {* True, if can detect Length. }
370 property VCR_CanFreeze
: Boolean index
$401B {MCI_VCR_GETDEVCAPS_CAN_FREEZE} read GetCapability
;
371 {* True, if supports command "freeze". }
372 property VCR_CanMonitorSources
: Boolean index
$4009 {MCI_VCR_GETDEVCAPS_CAN_MONITOR_SOURCES} read GetCapability
;
373 {* True, if can monitor sources. }
374 property VCR_CanPreRoll
: Boolean index
$4007 {MCI_VCR_GETDEVCAPS_CAN_PREROLL} read GetCapability
;
375 {* True, if can preroll. }
376 property VCR_CanPreview
: Boolean index
$4008 {MCI_VCR_GETDEVCAPS_CAN_PREVIEW} read GetCapability
;
377 {* True, if can preview. }
378 property VCR_CanReverse
: Boolean index
$4004 {MCI_VCR_GETDEVCAPS_CAN_REVERSE} read GetCapability
;
379 {* True, if can play in reverse direction. }
380 property VCR_CanTest
: Boolean index
$4006 {MCI_VCR_GETDEVCAPS_CAN_TEST} read GetCapability
;
381 {* True, if can test. }
382 property VCR_HasClock
: Boolean index
$4003 {MCI_VCR_GETDEVCAPS_HAS_CLOCK} read GetCapability
;
383 {* True, if has clock. }
384 property VCR_HasTimeCode
: Boolean index
$400A {MCI_VCR_GETDEVCAPS_HAS_TIMECODE} read GetCapability
;
385 {* True, if has time code. }
386 property VCR_NumberOfMarks
: Integer index
$4005 {MCI_VCR_GETDEVCAPS_NUMBER_OF_MARKS} read GetICapability
;
387 {* Returns number of marks. }
388 property VCR_SeekAccuracy
: Integer index
$4002 {MCI_VCR_GETDEVCAPS_SEEK_ACCURACY} read GetICapability
;
389 {* Returns seek accuracy. }
391 //-- for mmWaveAudio:
392 property Wave_AvgBytesPerSecond
: Integer index
$4004 {MCI_WAVE_STATUS_AVGBYTESPERSEC} read GetIState
;
393 {* Returns current bytes per second used for playing, recording, and saving. }
394 property Wave_BitsPerSample
: Integer index
$4006 {MCI_WAVE_STATUS_BITSPERSAMPLE} read GetIState
;
395 {* Returns current bits per sample used for playing, recording, and saving PCM formatted data. }
396 property Wave_SamplesPerSecond
: Integer index
$4003 {MCI_WAVE_STATUS_SAMPLESPERSEC} read GetIState
;
397 {* Returns current samples per second used for playing, recording, and saving. }
399 function SendCommand( Cmd
, Flags
: Integer; Buffer
: Pointer ): Integer;
400 {* Low level access to a device. To get knoq how to use it, see sources. }
403 function asmSendCommand( Flags
, Cmd: Integer
{;var Buffer in stack} ): Integer
;
404 {* Assembler version of SendCommand - only for advanced programmers. It
405 can be called from assembler only, and last parameter (but without
406 first member of the structure, dwCallback) must be placed
407 to stack just before calling asmSendCommand. Also, @Self must be
408 placed already in EBX, second parameter (Cmd) in EDX, and third (Flags)
409 in EAX. This method also retirns error code (0, if success), and
410 additionally ZF flag set if success. }
413 {$IFDEF USE_CONSTRUCTORS}
414 constructor CreateMediaPlayer
( const
AFileName: String
; AWindow: HWND );
415 {$ENDIF USE_CONSTRUCTORS}
419 var MediaPlayers
: PList
;
421 function NewMediaPlayer( const FileName
: String; Window
: HWND
): PMediaPlayer
;
422 {* Creates TMediaPlayer instance. If FileName is not empty string, file is opening
426 TPlayOption
= ( poLoop
, poWait
, poNoStopAnotherSound
, poNotImportant
);
427 {* Options to play sound. poLoop, when sound is playing back repeatedly until
428 PlaySoundStop called. poWait, if sound is playing synchronously (i.e. control
429 returns to application after the sound event completed). poNoStopAnotherSound
430 means that another sound playing can not be stopped to free resources needed to
431 play requested sound. poNotImportant means that if driver busy, function
432 will return immediately returning False (with no sound playing). }
433 TPlayOptions
= set of TPlayOption
;
434 {* Options, available to play sound from memory or resource or to play standard
435 sound event using PlaySoundMemory, PlaySoundResourceID, PlaySoundResourceName,
438 function PlaySoundMemory( Memory
: Pointer; Options
: TPlayOptions
): Boolean;
439 {* Call it to play sound already stored in memory. (It is possible to preload
440 sound from resource (e.g., using Resurce2Stream function) or to load sound from
442 function PlaySoundResourceID( Inst
, ResID
: Integer; Options
: TPlayOptions
): Boolean;
443 {* Call it to play sound, stored in resource. It is also possible to stop playing
444 certain sound, asynchronously playing from a resource, using PlaySoundStopResID.
445 |<br>
446 In this implementation, sound is played from memory and always with poWait
447 option turned on (i.e. synchronously). }
448 function PlaySoundResourceName( Inst
: Integer; const ResName
: String; Options
: TPlayOptions
): Boolean;
449 {* Call it to play sound, stored in (named) resource. It is also possible to stop
450 playing certain sound, asynchronously playing from a resource, using
451 PlaySoundStopResName.
452 |<br>
453 In this implementation, sound is played from memory and always with poWait
454 option turned on (i.e. synchronously). }
455 function PlaySoundEvent( const EventName
: String; Options
: TPlayOptions
): Boolean;
456 {* Call it to play standard event sound. E.g., 'SystemAsterisk', 'SystemExclamation',
457 'SystemExit', 'SystemHand', 'SystemQuestion', 'SystemStart' sounds are defined
458 for all Win32 implementations. }
459 function PlaySoundFile( const FileName
: String; Options
: TPlayOptions
): Boolean;
460 {* Call it to play waveform audio file. (This also can be done using
461 TMediaPlayer, but for wide set of audio and video formats). }
462 function PlaySoundStop
: Boolean;
463 {* Call it to stop playing sounds, which are yet playing (after calling
464 PlaySountXXXXX functions above to play sounds asynchronously). }
466 function WaveOutChannels( DevID
: Integer ): TSoundChannels
;
467 {* Returns available sound output channels for given wave out device. Pass
468 -1 (or WAVE_MAPPER) to get channels for wave mapper. If only mono
469 output available, [ chLeft ] is returned. }
470 function WaveOutVolume( DevID
: Integer; Chn
: TSoundChannel
; NewValue
: Integer ): Word;
471 {* Sets volume for given channel. If NewValue = -1 passed, new value is not set.
472 Always returns current volume level for a channel (if successful). Volume varies
473 in diapason 0..65535. If passed value > 65535, low word of NewValue is used
474 to set both chLeft and chRight channels. }
480 {++}(*TControl1 = class;*){--}
481 PControl1
= {-}^{+}TControl1
;
482 TControl1
= object( TControl
)
485 ////////////////////////////////////////////////////////////////////////
491 ////////////////////////////////////////////////////////////////////////
493 { -- TMediaPlayer -- }
495 {$IFDEF USE_CONSTRUCTORS}
496 function NewMediaPlayer( const FileName
: String; Window
: HWND
): PMediaPlayer
;
498 new( Result
, CreateMediaPlayer( FileName
, Window
) );
500 {$ELSE not_USE_CONSTRUCTORS}
502 function _NewMediaPlayer
: PMediaPlayer
;
504 New( Result
, Create
);
506 function NewMediaPlayer( const FileName
: String; Window
: HWND
): PMediaPlayer
;
513 MOV ECX, [MediaPlayers
]
517 MOV [MediaPlayers
], EAX
525 CALL TMediaPlayer.SetFileName
527 MOV EDX, [EBX].TMediaPlayer.FError
533 MOV DL, MCI_GETDEVCAPS_HAS_VIDEO
//$3
534 CALL TMediaPlayer.GetCapability
541 CALL TMediaPlayer.SetDisplay
543 POP [EBX].TMediaPlayer.FDisplay
549 {$ELSE ASM_VERSION} //Pascal
550 function NewMediaPlayer( const FileName
: String; Window
: HWND
): PMediaPlayer
;
554 New( Result
, Create
);
555 {+}{++}(*Result := PMediaPlayer.Create;*){--}
557 if MediaPlayers
= nil then
558 MediaPlayers
:= NewList
;
559 MediaPlayers
.Add( Result
);
560 //Result.FTimeFormat := tfMilliseconds; //by default...
561 Result
.FileName
:= FileName
;
562 if Result
.FError
<> 0 then
563 //MsgOK( 'Error #' + Int2Str( Result.Error ) + ' when opening multimedia:'#13 +
564 // Result.ErrorMessage )
567 if Result
.HasVideo
then
568 Result
.Display
:= Window
;
569 Result
.FDisplay
:= Window
;
573 {$ENDIF USE_CONSTRUCTORS}
576 procedure MMNotifyProc( var Msg
: TMsg
);
582 MOV EDX, [MediaPlayers
]
585 MOV ECX, [EDX].TList.FCount
586 MOV ESI, [EDX].TList.FItems
587 MOV EDI, [EBX].TMsg.lParam
590 CMP [EAX].TMediaPlayer.FDeviceID
, EDI
593 MOV ECX, [EAX].TMediaPlayer.fOnNotify.TMethod.Code
597 MOV EAX, [EDX].TMediaPlayer.fOnNotify.TMethod.Data
598 MOV ECX, [EBX].TMsg.wParam
610 {$ELSE ASM_VERSION} //Pascal
611 procedure MMNotifyProc( var Msg
: TMsg
);
615 if MediaPlayers
<> nil then
616 for I
:= 0 to MediaPlayers
.Count
- 1 do
618 MP
:= MediaPlayers
.Items
[ I
];
619 if MP
.FDeviceID
= Msg
.lParam
then
621 if Assigned( MP
.fOnNotify
) then
622 MP
.FOnNotify( MP
, TMPNotifyValue( Msg
.wParam
- 1 ) );
632 procedure TMediaPlayer
.Close
;
634 MOV ECX, [EAX].FDeviceID
640 INC EAX // EAX = MCI_NOTIFY
646 MOV [EBX].FDeviceID
, EAX
652 {$ELSE ASM_VERSION} //Pascal
653 procedure TMediaPlayer
.Close
;
654 var GenParm
: TMCI_Generic_Parms
;
656 if FDeviceID
= 0 then Exit
;
657 GenParm
.dwCallback
:= 0;
658 //if SendCommand( MCI_CLOSE, MCI_NOTIFY, @GenParm ) = 0 then
659 if SendCommand( MCI_CLOSE
, MCI_WAIT
, @GenParm
) = 0 then
664 {$IFDEF ASM_noVERSION}
665 destructor TMediaPlayer
.Destroy
;
671 MOV [EBX].FOnNotify.TMethod.Code
, EDX
673 MOV EAX, [MediaPlayers
]
680 PUSH [EAX].TList.fCount
685 MOV [MediaPlayers
], ECX
688 MOV ECX, [EBX].FAutoRestore.TMethod.Code
693 LEA EAX, [EBX].FFileName
695 LEA EAX, [EBX].FoldKeyValCDAudio
701 {$ELSE ASM_VERSION} //Pascal
702 destructor TMediaPlayer
.Destroy
;
707 I
:= MediaPlayers
.IndexOf( @Self
);
711 MediaPlayers
.Delete( I
);
713 if MediaPlayers
.Count
= 0 then
718 if Assigned( FAutoRestore
) then
721 FoldKeyValCDAudio
:= '';
727 procedure TMediaPlayer
.DoorClose
;
732 PUSH ECX // dwTimeFormat
733 //PUSH ECX // dwCallback
735 MOV AX, MCI_SET_DOOR_CLOSED
or MCI_NOTIFY
// $201
737 MOV DX, MCI_SET
// $80D
744 {$ELSE ASM_VERSION} //Pascal
745 procedure TMediaPlayer
.DoorClose
;
746 var SetParm
: TMCI_Set_Parms
;
748 Assert( (FDeviceID
= 0) or CanEject
, 'Device not support door close operation' );
749 SendCommand( MCI_SET
, MCI_SET_DOOR_CLOSED
or MCI_NOTIFY
, @SetParm
);
754 procedure TMediaPlayer
.Eject
;
759 PUSH ECX // dwTimeFormat
760 //PUSH ECX // dwCallback
762 MOV AX, MCI_SET_DOOR_OPEN
or MCI_NOTIFY
// $101
764 MOV DX, MCI_SET
// $80D
771 {$ELSE ASM_VERSION} //Pascal
772 procedure TMediaPlayer
.Eject
;
773 var SetParm
: TMCI_Set_Parms
;
775 Assert( (FDeviceID
= 0) or CanEject
, 'Device not support eject' );
776 SendCommand( MCI_SET
, MCI_SET_DOOR_OPEN
or MCI_NOTIFY
, @SetParm
);
781 function TMediaPlayer
.GetCapability( const Index
: Integer ): Boolean;
790 {$ELSE ASM_VERSION} //Pascal
791 function TMediaPlayer
.GetCapability( const Index
: Integer ): Boolean;
793 Result
:= Boolean( GetICapability( Index
) );
798 function TMediaPlayer
.GetICapability(const Index
: Integer): Integer;
802 MOV EAX, [EBX].FDeviceID
806 PUSH EDX // dwItem
:= Index
808 //PUSH ECX // dwCallback
810 MOV AX, MCI_WAIT
or MCI_GETDEVCAPS_ITEM
// $102
812 MOV DX, MCI_GETDEVCAPS
// $80B
814 //POP ECX // dwCallback
821 XCHG EAX, EDX // Result
:= dwRetirn
825 {$ELSE ASM_VERSION} //Pascal
826 function TMediaPlayer
.GetICapability(const Index
: Integer): Integer;
827 var DevCapParm
: TMCI_GetDevCaps_Parms
;
830 if FDeviceID
<> 0 then
832 DevCapParm
.dwItem
:= Index
;
833 if SendCommand( MCI_GETDEVCAPS
, MCI_WAIT
or MCI_GETDEVCAPS_ITEM
, @DevCapParm
) = 0 then
834 Result
:= DevCapParm
.dwReturn
;
840 function TMediaPlayer
.GetDeviceType
: TMPDeviceType
;
843 MOV DL, MCI_GETDEVCAPS_DEVICE_TYPE
// $4
846 {$ELSE ASM_VERSION} //Pascal
847 function TMediaPlayer
.GetDeviceType
: TMPDeviceType
;
849 Result
:= TMPDeviceType( GetICapability( MCI_GETDEVCAPS_DEVICE_TYPE
) { - 512 } );
854 function TMediaPlayer
.GetDisplayRect
: TRect
;
860 MOV EAX, MCI_ANIM_WHERE_DESTINATION
// $40000
865 PUSH EDX // rc
= (0,0,0,0)
866 //PUSH ECX // dwCallback
867 MOV DX, MCI_WHERE
or MCI_WAIT
// $843
869 //POP ECX // dwCallback
876 POP [EDI].TRect.Right
877 POP [EDI].TRect.Bottom
882 {$ELSE ASM_VERSION} //Pascal
883 function TMediaPlayer
.GetDisplayRect
: TRect
;
884 var RectParms
: TMCI_Anim_Rect_Parms
;
886 Result
:= MakeRect( 0, 0, 0, 0 );
888 if SendCommand( MCI_WHERE
, MCI_ANIM_WHERE_DESTINATION
or MCI_WAIT
, @RectParms
) = 0 then
889 Result
:= RectParms
.rc
;
894 procedure TMediaPlayer
.SetDisplayRect(const Value
: TRect
);
899 MOV ECX, [EDX].TRect.Right
900 OR ECX, [EDX].TRect.Bottom
903 MOV EAX, [EBX].FHeight
904 ADD EAX, [EDX].TRect.Top
905 PUSH EAX // rc.Bottom
906 MOV EAX, [EBX].FWidth
907 ADD EAX, [EDX].TRect.Left
912 PUSH [EDX].TRect.Bottom
913 PUSH [EDX].TRect.Right
916 PUSH [EDX].TRect.Left
918 //PUSH ECX // dwCallback
919 MOV EAX, MCI_ANIM_RECT
or MCI_ANIM_PUT_DESTINATION
or MCI_WAIT
926 {$ELSE ASM_VERSION} //Pascal
927 procedure TMediaPlayer
.SetDisplayRect(const Value
: TRect
);
928 var RectParms
: TMCI_Anim_Rect_Parms
;
930 if (Value
.Bottom
= 0) and (Value
.Right
= 0) then
932 {special case, use default width and height}
934 RectParms
.rc
:= MakeRect(Left
, Top
, Left
+FWidth
, Top
+FHeight
);
936 else RectParms
.rc
:= Value
;
937 SendCommand( MCI_PUT
, MCI_ANIM_RECT
or MCI_ANIM_PUT_DESTINATION
or MCI_WAIT
,
943 function TMediaPlayer
.GetErrorMessage
: String;
951 CALL mciGetErrorString
952 POP EDX // EDX = @Result
960 CALL System.
@LStrFromPChar
963 {$ELSE ASM_VERSION} //Pascal
964 function TMediaPlayer
.GetErrorMessage
: String;
966 ErrMsg
: array[0..1023{129 - in win32.hlp, 128 bytes are always sufficient, but...}] of Char;
968 if not mciGetErrorString(FError
, ErrMsg
, SizeOf(ErrMsg
)) then
975 function TMediaPlayer
.GetState
: TMPState
;
978 MOV DL, MCI_STATUS_MODE
// $4
986 {$ELSE ASM_VERSION} //Pascal
987 function TMediaPlayer
.GetState
: TMPState
;
989 Result
:= TMPState( GetIState( MCI_STATUS_MODE
) - 524 );
993 {$IFDEF ASM_noVERSION} //alias
994 function TMediaPlayer
.Open
: Boolean;
996 MOV [FMMNotify
], offset[MMNotifyProc
]
1000 MOV ECX, [EBX].FDeviceID
1003 PUSH ECX // lpstrAlias
1004 PUSH [EBX].FFileName
// lpstrElementName
1005 MOVZX EAX, [EBX].FDeviceType
1008 MOV DH, MCI_OPEN_ELEMENT
shr 8 // MCI_OPEN_ELEMENT
= $200
1010 MOV DX, MCI_OPEN_TYPE
or MCI_OPEN_TYPE_ID
1014 PUSH EAX // lpstrDeviceType
1017 OR AX, MCI_NOTIFY
or MCI_OPEN_SHAREABLE
//$101
1019 MOV DX, MCI_OPEN
//$803
1021 PUSH EAX // wDeviceID
1026 AND AH, $FE // Flag
:= Flag
and not MCI_OPEN_SHAREABLE
1031 POP EDX // EDX = wDeviceID
1036 MOV [EBX].FDeviceID
, EDX
1037 MOV [EBX].FWidth
, EAX
1038 MOV [EBX].FHeight
, EBX
1041 MOV DL, MCI_GETDEVCAPS_HAS_VIDEO
// $3
1047 MOV EDX, [EBX].FDisplay
1057 MOV [EBX].FWidth
, EAX
1060 MOV [EBX].FHeight
, EAX
1064 MOV word ptr [EBX].FAudioOff
, AX
1066 MOVZX EDX, [EBX].FTimeFormat
1070 MOV EAX, [EBX].FDeviceID
1076 {$ELSE ASM_VERSION} //Pascal
1077 function TMediaPlayer
.Open
: Boolean;
1078 const DevTypes
: array [ TMPDeviceType
] of DWORD
= ( MCI_ALL_DEVICE_ID
,
1079 MCI_DEVTYPE_VCR
, MCI_DEVTYPE_VIDEODISC
, MCI_DEVTYPE_OVERLAY
,
1080 MCI_DEVTYPE_CD_AUDIO
, MCI_DEVTYPE_DAT
, MCI_DEVTYPE_SCANNER
,
1081 MCI_DEVTYPE_ANIMATION
, MCI_DEVTYPE_DIGITAL_VIDEO
, MCI_DEVTYPE_OTHER
,
1082 MCI_DEVTYPE_WAVEFORM_AUDIO
, MCI_DEVTYPE_SEQUENCER
);
1084 OpenParm
: TMCI_Open_Parms
;
1089 FMMNotify
:= MMNotifyProc
;
1090 if FDeviceID
<> 0 then Result
:= True { opened already } else
1092 ASSERT( (FFileName
= '') and (FDeviceType
<> mmAutoSelect
)
1093 or FileExists( FFileName
), 'Multimedia file does not exist' );
1094 ASSERT( not ((FDeviceType
in [ mmVideoDisc
, mmCDAudio
, mmVCR
, mmDigitalVideo
{more?} ])
1095 and (FFileName
<> '')), 'FileName can not be used with simple multimedia device' );
1096 FillChar(OpenParm
, SizeOf(TMCI_Open_Parms
), 0);
1097 Flag
:= MCI_OPEN_ELEMENT
;
1098 if FDeviceType
<> mmAutoSelect
then
1100 Flag
:= MCI_OPEN_TYPE
or MCI_OPEN_TYPE_ID
;
1102 if FAlias
<> '' then
1104 Flag
:= Flag
or MCI_OPEN_ALIAS
;
1105 OpenParm
.lpstrAlias
:= PChar( FAlias
);
1107 OpenParm
.lpstrDeviceType
:= Pointer( DevTypes
[ FDeviceType
] );
1108 OpenParm
.lpstrElementName
:= PChar(FFileName
);
1110 R
:= SendCommand( MCI_OPEN
, MCI_NOTIFY
or MCI_OPEN_SHAREABLE
or Flag
, @OpenParm
);
1114 R
:= SendCommand( MCI_OPEN
, MCI_NOTIFY
or Flag
, @OpenParm
);
1121 FDeviceID
:= OpenParm
.wDeviceID
;
1126 Display
:= FDisplay
;
1127 DisplayR
:= GetDisplayRect
;
1128 FWidth
:= DisplayR
.Right
-DisplayR
.Left
;
1129 FHeight
:= DisplayR
.Bottom
-DisplayR
.Top
;
1131 TimeFormat
:= FTimeFormat
;
1132 FAudioOff
[ chLeft
] := False;
1133 FAudioOff
[ chRight
] := False;
1138 {$ENDIF ASM_VERSION}
1140 {$IFDEF ASM_VERSION}
1141 function TMediaPlayer
.Play( StartPos
, PlayLength
: Integer ): Boolean;
1159 MOV AL, MCI_TO
// $8
1168 OR AL, MCI_FROM
// $4
1172 INC EAX // Flags
:= Flags
or MCI_NOTIFY
1174 MOV DX, MCI_PLAY
//$806
1181 {$ELSE ASM_VERSION} //Pascal
1182 function TMediaPlayer
.Play( StartPos
, PlayLength
: Integer ): Boolean;
1183 var PlayParm
: TMCI_Play_Parms
;
1187 if StartPos
>= 0 then
1189 PlayParm
.dwFrom
:= StartPos
;
1192 if PlayLength
>= 0 then
1194 if StartPos
>= 0 then
1195 PlayParm
.dwTo
:= StartPos
+ PlayLength
1197 PlayParm
.dwTo
:= Position
+ PlayLength
;
1198 Flags
:= Flags
or MCI_TO
;
1200 Result
:= SendCommand( MCI_PLAY
, Flags
or MCI_NOTIFY
, @PlayParm
) = 0;
1202 {$ENDIF ASM_VERSION}
1204 {$IFDEF ASM_VERSION}
1205 function TMediaPlayer
.Save( const aFileName
: String ): Boolean;
1212 MOV AX, MCI_SAVE_FILE
or MCI_NOTIFY
1219 {$ELSE ASM_VERSION} //Pascal
1220 function TMediaPlayer
.Save( const aFileName
: String ): Boolean;
1221 var SaveParm
: TMCI_SaveParms
;
1224 //if FDeviceID = 0 then Exit;
1225 SaveParm
.lpfilename
:= PChar( aFileName
);
1226 Result
:= SendCommand( MCI_SAVE
, MCI_NOTIFY
or MCI_SAVE_FILE
, @SaveParm
) = 0;
1228 {$ENDIF ASM_VERSION}
1231 function TMediaPlayer
.asmSendCommand(Flags
{in EAX}, Cmd
{in EDX}: Integer
{; var Buf in stack}): Integer
;
1238 MOV ECX, [EBX].FDeviceID
1249 AND AL, not MCI_WAIT
1271 AND AL, not MCI_NOTIFY
1283 MOV EAX, [EAX].TControl1.FHandle
1284 MOV [ESP+12], EAX // dwCallback
:= Applet.FHandle
1291 @@4: PUSH ECX // FDeviceID
=-1?0:FDeviceID
1301 MOV [EBX].FError
, EAX
1302 TEST EAX, EAX // also return
"ZF" if OK
(no errors
)
1309 {$IFDEF ASM_VERSION}
1310 function TMediaPlayer
.SendCommand(Cmd
, Flags
: Integer; Buffer
: Pointer): Integer;
1315 XCHG EAX, ECX // EAX=Flags
1316 MOV ECX, [EBX].FDeviceID
1318 PUSH Buffer
// -> Buffer
1328 AND AL, not MCI_WAIT
1350 AND AL, not MCI_NOTIFY
1353 PUSH EAX // -> Flags
1362 MOV EAX, [EAX].TControl.FHandle
1372 MOV [EBX].FError
, EAX
1374 MOV EAX, [EBX].FError
1377 {$ELSE ASM_VERSION} //Pascal
1378 function TMediaPlayer
.SendCommand(Cmd
, Flags
: Integer; Buffer
: Pointer): Integer;
1379 var Parms
: PMCI_Generic_Parms
;
1382 if FDeviceID
<> 0 then
1384 if not LongBool( Flags
and MCI_WAIT
) then
1386 Flags
:= Flags
and not MCI_WAIT
;
1388 Flags
:= Flags
or MCI_WAIT
;
1390 if LongBool( Flags
and MCI_WAIT
) or not Assigned( Applet
) then
1391 Flags
:= Flags
and not MCI_NOTIFY
;
1393 //Parms.dwCallback := Applet.FHandle;
1394 if LongBool( Flags
and (MCI_NOTIFY
{or MCI_WAIT})) then
1396 {if FDisplay <> 0 then
1397 Parms.dwCallback := FDisplay
1399 Parms
.dwCallback
:= PControl1( Applet
).FHandle
; // MakeLong( Applet.FHandle, 0 );
1401 if FDeviceID
= -1 then
1403 FError
:= mciSendCommand( FDeviceID
, Cmd
, Flags
, Integer(Buffer
) );
1407 {$ENDIF ASM_VERSION}
1409 {$IFDEF ASM_VERSION}
1410 procedure TMediaPlayer
.SetDisplay(const Value
: HWND
);
1415 MOV EAX, MCI_WAIT
or MCI_ANIM_WINDOW_HWND
1417 MOV DX, MCI_WINDOW
//$841
1421 MOV [EBX].FDisplay
, EDX
1425 {$ELSE ASM_VERSION} //Pascal
1426 procedure TMediaPlayer
.SetDisplay(const Value
: HWND
);
1427 var AniWndParm
: TMCI_Anim_Window_Parms
;
1431 AniWndParm
.Wnd
:= Value
1433 AniWndParm
.Wnd
:= 0;
1434 if SendCommand( MCI_WINDOW
, MCI_WAIT
or MCI_ANIM_WINDOW_HWND
, @AniWndParm
) <> 0 then
1437 {$ENDIF ASM_VERSION}
1439 {$IFDEF ASM_VERSION}
1440 procedure TMediaPlayer
.SetPause(const Value
: Boolean);
1450 MOV DL, MCI_RESUME
and $FF
1455 {$ELSE ASM_VERSION} //Pascal
1456 procedure TMediaPlayer
.SetPause(const Value
: Boolean);
1458 GenParm
: TMCI_Generic_Parms
;
1464 SendCommand( Cmd
, MCI_NOTIFY
, @GenParm
);
1466 {$ENDIF ASM_VERSION}
1468 {$IFDEF ASM_VERSION}
1469 procedure TMediaPlayer
.SetPosition(Value
: Integer);
1476 MOV AL, MCI_NOTIFY
or MCI_TO
//$9
1482 {$ELSE ASM_VERSION} //Pascal
1483 procedure TMediaPlayer
.SetPosition(Value
: Integer);
1484 var SeekParm
: TMCI_Seek_Parms
;
1486 SeekParm
.dwTo
:= Value
;
1487 SendCommand( MCI_SEEK
, MCI_NOTIFY
or MCI_TO
, @SeekParm
);
1489 {$ENDIF ASM_VERSION}
1491 {$IFDEF ASM_VERSION}
1492 procedure TMediaPlayer
.SetTrack(Value
: Integer);
1494 CMP EDX, [EAX].FTrack
1499 MOV DL, MCI_STATUS_NUMBER_OF_TRACKS
// $3
1507 MOV [ECX].FTrack
, EDX
1510 {$ELSE ASM_VERSION} //Pascal
1511 procedure TMediaPlayer
.SetTrack(Value
: Integer);
1514 if FTrack
= Value
then Exit
;
1520 {$ENDIF ASM_VERSION}
1522 {$IFDEF ASM_VERSION}
1523 procedure TMediaPlayer
.SetFileName(const Value
: String);
1526 MOV EAX, [EAX].FFileName
1527 CALL System.
@LStrCmp
1535 LEA EAX, [EAX].FFileName
1536 CALL System.
@LStrAsg
1541 {$ELSE ASM_VERSION} //Pascal
1542 procedure TMediaPlayer
.SetFileName(const Value
: String);
1544 if FFileName
<> Value
then
1550 {$ENDIF ASM_VERSION}
1552 {$IFDEF ASM_VERSION}
1553 function TMediaPlayer
.GetBState( const Index
: Integer ): Boolean;
1562 {$ELSE ASM_VERSION} //Pascal
1563 function TMediaPlayer
.GetBState( const Index
: Integer ): Boolean;
1565 Result
:= (GetIState( Index
) and 1) = 1;
1567 {$ENDIF ASM_VERSION}
1569 {$IFDEF ASM_VERSION}
1570 function TMediaPlayer
.GetIState(const Index
: Integer): Integer;
1574 MOV ECX, [EBX].FTrack
1577 AND byte ptr [ESP+3], $7F
1578 XOR EAX, EAX // flags
= 0
1580 MOV AX, MCI_WAIT
or MCI_STATUS_ITEM
1601 {$ELSE ASM_VERSION} //Pascal
1602 function TMediaPlayer
.GetIState(const Index
: Integer): Integer;
1603 var StatusParm
: TMCI_Status_Parms
;
1607 StatusParm
.dwItem
:= Index
and $7FFFFFFF;
1612 StatusParm
.dwTrack
:= FTrack
;
1615 if SendCommand( MCI_STATUS
, MCI_WAIT
or MCI_STATUS_ITEM
or Flags
, @StatusParm
) = 0 then
1616 Result
:= StatusParm
.dwReturn
;
1618 {$ENDIF ASM_VERSION}
1620 {$IFDEF ASM_VERSION}
1621 function TMediaPlayer
.GetPosition
: Integer;
1624 MOV DL, MCI_STATUS_POSITION
//$2
1627 {$ELSE ASM_VERSION} //Pascal
1628 function TMediaPlayer
.GetPosition
: Integer;
1630 Result
:= GetIState( MCI_STATUS_POSITION
);
1632 {$ENDIF ASM_VERSION}
1634 {$IFDEF ASM_VERSION}
1635 function TMediaPlayer
.GetTimeFormat
: TMPTimeFormat
;
1638 MOV DL, MCI_STATUS_TIME_FORMAT
// $6
1641 {$ELSE ASM_VERSION} //Pascal
1642 function TMediaPlayer
.GetTimeFormat
: TMPTimeFormat
;
1644 Result
:= TMPTimeFormat( GetIState( MCI_STATUS_TIME_FORMAT
) );
1646 {$ENDIF ASM_VERSION}
1648 {$IFDEF ASM_VERSION}
1649 procedure TMediaPlayer
.SetTimeFormat(const Value
: TMPTimeFormat
);
1657 MOV AX, MCI_SET_TIME_FORMAT
or MCI_NOTIFY
1658 MOV DX, MCI_SET
//$80D
1662 MOV [EBX].FTimeFormat
, DL
1666 {$ELSE ASM_VERSION} //Pascal
1667 procedure TMediaPlayer
.SetTimeFormat(const Value
: TMPTimeFormat
);
1668 var SetParm
: TMCI_Set_Parms
;
1670 ASSERT( (FDeviceID
= 0) or (Value
= tfMilliseconds
)
1671 or (Value
in [ tfBytes
, tfSamples
]) and (DeviceType
= mmWaveAudio
)
1672 or (Value
= tfFrames
) and (DeviceType
in [ mmVCR
, mmVideoDisc
, mmDigitalVideo
])
1673 or (Value
= tfHMS
) and (DeviceType
in [ mmVCR
, mmVideoDisc
])
1674 or (Value
in [ tfMSF
, tfTMSF
]) and (DeviceType
in [ mmCDAudio
, mmVCR
])
1675 or (Value
in [ tfSMPTE24
, tfSMPTE25
, tfSMPTE30
, tfSMPTE30Drop
])
1676 and (DeviceType
in [ mmSequencer
, mmVCR
]),
1677 'Time format not supported by multimedia device' );
1678 SetParm
.dwTimeFormat
:= Ord( Value
);
1679 if SendCommand( MCI_SET
, MCI_NOTIFY
or MCI_SET_TIME_FORMAT
, @SetParm
) = 0 then
1680 FTimeFormat
:= Value
;
1682 {$ENDIF ASM_VERSION}
1684 function TMediaPlayer
.GetPause
: Boolean;
1686 Result
:= State
<> mpPlaying
;
1689 const Key_CD_AutoPlay
: PChar
= 'AudioCD\Shell';
1690 Key_CD_AutoRun
: PChar
= 'Software\Microsoft\Windows\CurrentVersion\Policies\Explorer';
1691 Val_CD_AutoRun
: PChar
= 'NoDriveTypeAutoRun';
1693 {$IFDEF ASM_VERSION}
1694 procedure TMediaPlayer
.Insert
;
1697 CALL DisableAutoPlay
1699 MOV [EAX].FAutoRestore.TMethod.Code
, offset[RestoreAutoPlay
]
1702 {$ELSE ASM_VERSION} //Pascal
1703 procedure TMediaPlayer
.Insert
;
1706 FAutoRestore
:= RestoreAutoPlay
;
1709 {$ENDIF ASM_VERSION}
1711 {$IFDEF ASM_VERSION}
1712 procedure TMediaPlayer
.DisableAutoPlay
;
1716 MOV EDX, [Key_CD_AutoRun
]
1717 MOV EAX, HKEY_CURRENT_USER
1718 CALL RegKeyOpenWrite
1720 MOV EDX, [Val_CD_AutoRun
]
1724 MOV [EBX].FOldKeyValCDData
, EAX
1744 MOV EAX, HKEY_CURRENT_USER
1745 MOV EDX, [Key_CD_AutoPlay
]
1748 CALL RegKeyOpenWrite
1754 MOV EAX, HKEY_CLASSES_ROOT
1756 CALL RegKeyOpenWrite
1759 MOV [EBX].FBaseKeyCDAudio
, ECX
1762 LEA ECX, [EBX].FoldKeyValCDAudio
1764 MOV ECX, [EBX].FoldKeyValCDAudio
1779 {$ELSE ASM_VERSION} //Pascal
1780 procedure TMediaPlayer
.DisableAutoPlay
;
1783 K1
:= RegKeyOpenWrite( HKEY_CURRENT_USER
, Key_CD_AutoRun
);
1784 FoldKeyValCDData
:= RegKeyGetDw( K1
, Val_CD_AutoRun
);
1785 if (FoldKeyValCDData
and $20) = 0 then
1787 RegKeySetDw( K1
, Val_CD_AutoRun
, FoldKeyValCDData
or $20 );
1791 FBaseKeyCDAudio
:= HKEY_CURRENT_USER
;
1792 K2
:= RegKeyOpenWrite( FBaseKeyCDAudio
, Key_CD_AutoPlay
);
1795 FBaseKeyCDAudio
:= HKEY_CLASSES_ROOT
;
1796 K2
:= RegKeyOpenWrite( FBaseKeyCDAudio
, Key_CD_AutoPlay
);
1798 FoldKeyValCDAudio
:= RegKeyGetStr( K2
, '' );
1799 if FoldKeyValCDAudio
<> '' then
1801 RegKeySetStr( K2
, '', '' );
1805 {$ENDIF ASM_VERSION}
1807 {$IFDEF ASM_VERSION}
1808 procedure TMediaPlayer
.RestoreAutoPlay
;
1813 MOV [EBX].FAutoRestore.TMethod.Code
, EAX
1814 MOV EAX, [EBX].FoldKeyValCDData
1823 MOV EAX, HKEY_CURRENT_USER
1824 MOV EDX, [Key_CD_AutoRun
]
1825 CALL RegKeyOpenWrite
1828 MOV EDX, [Val_CD_AutoRun
]
1833 MOV ECX, [EBX].FoldKeyValCDAudio
1837 MOV EAX, [EBX].FBaseKeyCDAudio
1838 MOV EDX, [Key_CD_AutoPlay
]
1839 CALL RegKeyOpenWrite
1849 {$ELSE ASM_VERSION} //Pascal
1850 procedure TMediaPlayer
.RestoreAutoPlay
;
1853 FAutoRestore
:= nil;
1854 if (FoldKeyValCDData
and $20) = 0 then
1856 K1
:= RegKeyOpenWrite( HKEY_CURRENT_USER
, Key_CD_AutoRun
);
1857 RegKeySetDw( K1
, Val_CD_AutoRun
, FoldKeyValCDData
);
1861 if FoldKeyValCDAudio
<> '' then
1863 K2
:= RegKeyOpenWrite( FBaseKeyCDAudio
, Key_CD_AutoPlay
);
1864 RegKeySetStr( K2
, '', FoldKeyValCDAudio
);
1868 {$ENDIF ASM_VERSION}
1870 {$IFDEF ASM_VERSION}
1871 function TMediaPlayer
.StartRecording(FromPos
, ToPos
: Integer): Boolean;
1876 INC EAX // MCI_NOTIFY
1884 @@noTo: PUSH ECX // dwTo
1901 {$ELSE ASM_VERSION} //Pascal
1902 function TMediaPlayer
.StartRecording(FromPos
, ToPos
: Integer): Boolean;
1903 var RecordParm
: TMCI_Record_Parms
;
1907 if FromPos
>= 0 then
1909 RecordParm
.dwFrom
:= FromPos
;
1914 RecordParm
.dwTo
:= ToPos
;
1915 Flags
:= Flags
or ToPos
;
1917 Result
:= SendCommand( MCI_RECORD
, Flags
or MCI_NOTIFY
, @RecordParm
) = 0;
1919 {$ENDIF ASM_VERSION}
1921 {$IFDEF ASM_VERSION}
1922 function TMediaPlayer
.Stop
: Boolean;
1934 {$ELSE ASM_VERSION} //Pascal
1935 function TMediaPlayer
.Stop
: Boolean;
1936 var GenParm
: TMCI_Generic_Parms
;
1938 Result
:= SendCommand( MCI_STOP
, MCI_NOTIFY
, @GenParm
) = 0;
1940 {$ENDIF ASM_VERSION}
1942 function TMediaPlayer
.GetAudioOn(Chn
: TSoundChannels
): Boolean;
1944 if Chn
= [ chLeft
, chRight
] then
1945 Result
:= not FAudioOff
[ chLeft
] and not FAudioOff
[ chRight
]
1948 Result
:= not FAudioOff
[ chLeft
] or not FAudioOff
[ chRight
]
1951 if chLeft
in Chn
then
1952 Result
:= not FAudioOff
[ chLeft
]
1954 //if chRight in Chn then
1955 Result
:= not FAudioOff
[ chRight
];
1959 procedure TMediaPlayer
.SetAudioOn(Chn
: TSoundChannels
; const Value
: Boolean);
1961 SetParm
: TMCI_Set_Parms
;
1963 if Chn
= [ chLeft
, chRight
] then
1964 What
:= MCI_SET_AUDIO_ALL
1965 else if Chn
= [ chLeft
] then
1966 What
:= MCI_SET_AUDIO_LEFT
1967 else if Chn
= [ chRight
] then
1968 What
:= MCI_SET_AUDIO_RIGHT
1970 if chLeft
in Chn
then
1971 FAudioOff
[ chLeft
] := not Value
;
1972 if chRight
in Chn
then
1973 FAudioOff
[ chRight
] := not Value
;
1974 SetParm
.dwAudio
:= What
;
1978 What
:= MCI_SET_OFF
;
1979 SendCommand( MCI_SET
, What
or MCI_WAIT
or MCI_SET_AUDIO
, @SetParm
);
1982 function TMediaPlayer
.GetVideoOn
: Boolean;
1984 Result
:= not FVideoOff
;
1987 procedure TMediaPlayer
.SetVideoOn(const Value
: Boolean);
1988 var SetParm
: TMCI_Set_Parms
;
1991 FVideoOff
:= not Value
;
1995 What
:= MCI_SET_OFF
;
1996 SendCommand( MCI_SET
, MCI_WAIT
or MCI_SET_VIDEO
or What
, @SetParm
);
1999 function TMediaPlayer
.DGVGetSpeed
: Integer;
2001 Result
:= GetIState( $4003 {MCI_DGV_STATUS_SPEED} );
2004 procedure TMediaPlayer
.DGVSetSpeed(const Value
: Integer);
2006 TMCI_DGV_Set_Parms
= packed record
2013 var DGVSetParm
: TMCI_DGV_Set_Parms
;
2015 DGVSetParm
.dwSpeed
:= Value
;
2016 SendCommand( MCI_SET
, MCI_WAIT
or $20000 {MCI_DGV_SET_SPEED}, @DGVSetParm
);
2019 { -- PlaySound interafce functions -- }
2021 const PlaySndFlags
: array[ TPlayOption
] of Integer = ( SND_LOOP
, not SND_ASYNC
,
2022 SND_NOSTOP
, SND_NOWAIT
);
2024 function PlaySoundMemory( Memory
: Pointer; Options
: TPlayOptions
): Boolean;
2026 Result
:= PlaySound( Memory
, hInstance
, MakeFlags( @Options
, PlaySndFlags
)
2027 or SND_MEMORY
or SND_NODEFAULT
);
2030 function PlaySoundResourceID( Inst
, ResID
: Integer; Options
: TPlayOptions
): Boolean;
2031 { This does not work (at least, if resource stored in res-file as RC_DATA.
2033 Result := PlaySound( Pointer( ResID ), Inst, MakeFlags( @Options, PlaySndFlags )
2034 or SND_RESOURCE or SND_NODEFAULT );
2037 { This works, but only synchronously.
2040 MS := NewMemoryStream;
2041 Resource2Stream( MS, Inst, Pointer( ResID ), RT_RCDATA );
2042 Result := PlaySoundMemory( MS.Memory, Options + [poWait] );
2046 { This works asynchronously as it is set in Options (if needed). }
2047 var Find
, Res
: THandle
;
2051 Find
:= FindResource( Inst
, Pointer( ResID
), RT_RCDATA
);
2054 Res
:= LoadResource( Inst
, Find
);
2057 Ptr
:= LockResource( Res
);
2060 Result
:= PlaySoundMemory( Ptr
, Options
);
2066 function PlaySoundResourceName( Inst
: Integer; const ResName
: String; Options
: TPlayOptions
): Boolean;
2067 var Find
, Res
: THandle
;
2071 Find
:= FindResource( Inst
, PChar( ResNAme
), RT_RCDATA
);
2074 Res
:= LoadResource( Inst
, Find
);
2077 Ptr
:= LockResource( Res
);
2080 Result
:= PlaySoundMemory( Ptr
, Options
);
2086 function PlaySoundEvent( const EventName
: String; Options
: TPlayOptions
): Boolean;
2088 Result
:= PlaySound( PChar( EventName
), 0, MakeFlags( @Options
, PlaySndFlags
)
2089 or SND_ALIAS
or SND_NODEFAULT
);
2092 function PlaySoundFile( const FileName
: String; Options
: TPlayOptions
): Boolean;
2094 Result
:= PlaySound( PChar( FileName
), 0, MakeFlags( @Options
, PlaySndFlags
)
2095 or SND_FILENAME
or SND_NODEFAULT
);
2098 function PlaySoundStop
: Boolean;
2100 Result
:= PlaySound( nil, 0, SND_PURGE
);
2103 function WaveOutChannels( DevID
: Integer ): TSoundChannels
;
2104 var WC
: TWaveOutCaps
;
2107 if waveOutGetDevCaps( DevID
, @WC
, sizeof( WC
) ) = MMSYSERR_NOERROR
then
2109 if WC
.wChannels
= 2 then
2110 Result
:= [ chLeft
, chRight
]
2112 if WC
.dwSupport
= 1 then
2113 Result
:= [ chLeft
];
2117 function WaveOutVolume( DevID
: Integer; Chn
: TSoundChannel
; NewValue
: Integer ): Word;
2122 if waveOutGetVolume( DevID
, @V
) = MMSYSERR_NOERROR
then
2126 if Chn
= chRight
then
2130 NewValue
:= NewValue
shl 16;
2133 V
:= V
and $FFFF0000;
2134 if NV
>= $10000 then
2136 NewValue
:= (NV
and $FFFF) or (NV
shl 16);
2139 Result
:= Word( V1
);
2141 waveOutSetVolume( DevID
, V
or DWORD(NewValue
) );