Recently, I found a strange problem when using the MediaPlayer control program. I didn't know that I didn't know that it was MediaPlayer's question, or Delphi's MMSystem.pas itself was wrong. The problem only as the value of MediaPlay.DeviceType can only be set to DTAUTOSELECT Otherwise, whether it is AVI, or the MPG file cannot be played, I use Delphi6 and Delphi6 SP2 to test in the Win2000 and XP environments, can not succeed.
If the device type is set to an obvious error, the MediaPlay control will report an error. If the file is AVI or MPG format, select DeviceType = DTCDAUDIO, will report the MCI error, but if you use the AVI file, select DTAVIDEO, do not report any errors, file open However, whether it is through the program, or by the MEDIAPLAY's Button, it is not a file, and the length of MediaPlay.length is not correct, for example,: explay.deviceType: = DTAVIVIDEO; ExpLay.FileName: = 'D: / Windows / Clock. Avi '; Explay.Open; Explay.Play; In the case of you can only look at MediaPlayer's source code (I don't know much about Delphi) Analysis, the DeviceType of Delphi's TMEDIAPLAYER control can only be in several select the type, which is defined in several TMPDeviceTypes in MPlay.pas = (dtAutoSelect, dtAVIVideo, dtCDAudio, dtDAT, dtDigitalVideo, dtMMMovie, dtOther, dtOverlay, dtScanner, dtSequencer, dtVCR, dtVideodisc, dtWaveAudio); MCI is defined in the has the following structure: tagMCI_OPEN_PARMSA = record dwCallback: DWORD; wDeviceID: MCIDEVICEID; lpstrDeviceType: PAnsiChar; // device type lpstrElementName: PAnsiChar; lpstrAlias: PAnsiChar; end; procedure TMediaPlayer.Open in the mplay.pas; const DeviceName: array [TMPDeviceTypes] Of Pchar = ('', ',', 'DAT', 'DigitalVideo', 'Mmmovie', 'Other', 'Overlay', 'Scanner', 'SEQUENCER', 'VCR ',' Videodisc ',' Waveaudio '); ... set the DeviceType value that actually passed to MCI ................ begin ... (MPlay. Pas Lines 841) OpenParm.lpstrDeviceType: = DeviceName [fdeviceType]; // The device type you selected ... if fdeviceType <> DTAUTOSELECT THEN FFLAGS: = fflags or mci_open_type;
If FDEVICETYPE <> DTAUTOSELECT THEN / I / / Do not understand why you have to do twice a different judgment fflags: = fflags or mci_open_type else fflags: = fflags or mci_open_element; // Only this can play correctly, that is, automatic mode OpenParm.dwcallback: = Handle; Ferror: = McISendCommand (0, MCI_open, fflags, longint (@openparm)); //. . . . . .
Refer to the above situation, I choose DeviceTyPE = DTAVIVideo to be the value of 'avivideo'. This also corresponds to the value in the MCI32 item in the registry. To verify that the value using LPStrDeviceType is really available with 'avivideo' I loaded a MCI32.ocx, this control is attached in VS6, where the DeviceType property and the DeviceType attribute in the TMEDIAPLAYER are roughly equivalent, but mci32.ocx Value can be specified directly to the device name, I set the MCI32.ocxy DeviceType to 'avivideo', and the result can be played normally. In order to find out the reason, I compare the VC's MMSystem.h file and the parameters and data structures in MMSystem.PAS. There is no difference, basically judging MMSystem, PAS is no problem, then the problem must be in MPLAY.PAS . So from MPLAY.PAS, one control TDEMEDIAPLAY is also tracked, and there is no problem. If the file opens MCIopened, the device number FDEVICEID, whether it is displayed FhaasVideo or other logo, the getDeviceCaps function has no abnormal, only the getLEngth function is Ferror: = McISendCommand (FDeviceID, MCI_Status, Fflags, longint (@statusparm)); Result: = statusparm.dwreturn; return value is not normal, and actually has not returned an error, on my machine, no matter how setting TimeFormat returns 4, you The machine may not be the same as the software and the like. I haven't worked until I went online to find the data about Delphi in this area. It seems that it is DTAUTOSELECT mode, but it is necessary for me. To specify specific drivers. There is no way, open the VC again, find an example of MCI, read carefully, find problems, there is such a code mcimo.lpstrDeviceType = "mpegvideo"; ... dwflags = (dword) (MCI_Open_Element | MCI_Open_Type | ); DWResult = mciSendcommand (0, MCI_open, dwflags, (dword) (lpmci_dgv_open_parms) & mcimo); ...... The problem seems to have a little clue, and the dwflags in the VC code is specified after specifying DeviceType, not only the MCI_Open_Type flag Instead, it is brought along with the MCI_Open_Element flag. So I have returned to MPLAY.PAS, I don't understand why two code duplicate statements have been modified in the two code repeat: OpenParm.lpstrDeviceType: = DeviceName [fdeviceType]; your selected device type .... .. if fdeviceType <> DTAUTOSELECT THEN FFLAGS: = fflags or mci_open_type;
if FDeviceType <> dtAutoSelect then FFlags: = FFlags or MCI_OPEN_ELEMENT change here else FFlags: = FFlags or MCI_OPEN_ELEMENT; OpenParm.dwCallback: = Handle; FError: = mciSendCommand (0, mci_Open, FFlags, Longint (@OpenParm)); / /. . . . . . Re-build, install new controls. Test, in order to verify the new control is actually played with the device I specified, not the automatic selection device, I will test it with the following steps 1, I will write all about .avi in the registration table to describe the project backup and delete Then, the DEVICETYPE of the new control is set to DTAUTOSELECT, prompts an error, and cannot open the MCI device. This is the effect I need, and the system can automatically identify the AVI file playback device. 2, set the DEVICETYPE of the new control to DTAVIVideo, play everything is normal. Note The new control is indeed playing the AVI file with the specified device.
Conclusion: 1, how can there be such a strange statement in mplay.pas, why is a condition to be judged twice, and there is no practical meaning because MCI_Open_Type or MCI_Open_Type results still MCI_Open_Type. It is definitely the author of the control source code has certain considerations. After modifying the source code, I still feel very strange. If it is the source of the source author, then it should not be judged to the third time. It only needs to be changed: if fdeviceType <> DTAUTOSELECT THEN FFLAGS: = fflags or mci_open_type; fflags: = fflags or mci_open_element; 2, although I agree with a constant in a large project, it is used for the value such as DeviceType, which seems to hand over the user to the user, because TmpDeviceTypes definition is dead, and the system is live, like MPEGVideo, MPEGVIDEO2 Such a device, there is no definition in TmpDeviceTypes, this, I think that MCI32.oCX is better, so I have rewritten the new control directly into the device name, one media file in Open. 3. Thank Baolan Company to provide source code for all controls, if you modify in controls without source code, it is basically impossible.