[Library] MCI v1.1 - Play/Control media files

IntroductionIn July 2007, Fincs released a popular library of functions to control Media Control Interface (MCI) devices. He called it Sound.ahk. The library is a conversion of the AutoIt standard library Sound.au3, originally provided by RazerM. A month later, Fincs released an enhanced version of the library as Media.ahk.

After doing some MCI research on msdn, I started making some changes to the library for my personal use. After a while there were enough modifications to share the changes. So as not to confuse this release with any of the previous libraries, I named this library MCI.ahk. Although there are significant differences here and there, the library maintains the same basic structure as originally released by Fincs. Credit and thanks to Fincs for providing the original AutoHotkey libraries and to RazerM for providing the original AutoIt library.

What's New/DifferentThe following are some of the new or enhanced features:

Support for Audio CDs. The MCI_OpenCDAudio function has been added to open CDAudio devices. In addition, other library functions have been added or enhanced to support CDAudio and similar devices.

Notify Callback. The MCI_Play function has been enhanced to support the MCI "notify" flag which will call a developer-defined function when the device completes (or fails to complete) the requested operation.

Wait flag. With the exception of the MCI_Play and MCI_Record functions, all library functions that manage media (Open, Close, Pause, Resume, Seek, etc.) have been modified to include the MCI "wait" flag by default. This small but important change insures that the library functions do not step on each other by forcing the mciSendString DLL function to complete the requested operation before returning control to the calling function.

Improved Error Handling/Reporting. Several important changes:

The MCI_Open and the new MCI_OpenCDAudio functions have been significantly beefed-up to trap for errors. Where possible, a developer-friendly error message is dumped to the debugger when an error occurs.

All calls to the mciExecute DLL function have been removed. This obsolete (according to msdn) function is a bit easier to use than the mciSendString DLL function but it displays a message dialog when errors occur. A message dialog is tolerable when developing/testing a script but can be catastrophic in a live script especially if the message dialog is displayed in lieu of returning the appropriate error code.

The MCI_SendString function has been enhanced to collect the associated message text when a non-zero error code is returned from the mciGetErrorString DLL function. Although the error code is still returned by the MCI_SendString function, the developer-friendly message text is dumped to the to the debugger (via outputdebug) for easy review.

Not all MCI devices are created equal. If you write a routine that works for one MCI device, don't assume that it will work for other device types. Be sure to test your script using all of the target device types. If necessary, use the MCI_DeviceType function to identify which MCI device type you're using.

Setup/Configuration. Sometimes a media file will not open, play, or operate correctly because the file's extension is not registered as a valid MCI extension or the MCI extension is assigned to the wrong device type/driver. Although I'm sure they exist, I don't know of any tools to identify and fix a bad MCI configuration. However, additions and changes to the MCI installation can be made in the registry. Be careful! See the documentation in the MCI_Open function for registry locations.

Bugs. Although it's relatively rare, MCI devices do have bugs. Sometime media doesn't play or does something freaky because of bugs in the device driver.

Seek. The MCI_Seek function presents unique challenges. It was designed to position the media to a specific location but because the core Seek command stops the media after it has been positioned, the function has been enhanced to return the device back to the state it was in before the function was called if necessary (Play or Pause). Although this methodology works for most devices, it does not work as expected for some devices (CDAudio for example) and it is probable that a call to this function will interrupt the "Notify" option of the MCI_Play function.

Debugging. Checking the return codes from the MCI_Open and MCI_OpenCDAudio functions is critical. These functions establish a connection to a MCI device and until a valid connection is made, none of the other library functions will work correctly.

Checking the return codes from the rest of the library functions brings into account the law of diminishing returns. The reason: 99% of the MCI errors occur because of programming and/or logic errors. These include errors that occur because of attempts to access a device that hasn't been opened or using a command, flag, or flag option that is not supported by the device.

There are two tools that are necessary for proper debugging:

MCI Reference Guide. This is a "must have" reference to find out what you can and cannot do with/to a MCI device. See the References section for the link.

Debugger. When a non-zero error code is returned from the mciGetErrorString DLL function, the associated error message text is dumped to the debugger in an easy-to-read format. Errors trapped by the MCI_Open and MCI_OpenCDAudio functions are also sent to the debugger in a easy-to-read format.

v0.2 (Preview)- Added the MCI_Record and MCI_Save functions. (thanks heresy)- Added "Record" example. (thanks heresy)- Enhanced the MCI_Open function to support the "new" device name (used when recording with WaveAudio device).- Removed the p_Track parameter from the MCI_Seek function. For devices that support tracks, this code did not work as expected and is not really needed. May be added back (with enhancements) in the future.- Minor updates to examples.- Minor documentation changes.- Minor changes to the forum post body.

v0.3 (Preview)- Fixed bug with notify feature of MCI_Play function when the p_hwndCallback parameter is not specified. (thanks skwire)

wow what a coincidence!
i was reading exactly same part of msdn to accomplish native ahk sound recording function and i was even the first reader of this thread!
seems you've wrapped the entire MCI functions.
Thanks for posting this!

After looking at the code, I think, in my humblest opinion, that all of the commands except for the "record" and "save" commands should be removed from the individual functions. The reason: The MCI library already supports commands to Open (needs enhancement to support the "new" media type), Stop, and Close a device. In addition, the Pause and Resume commands can be used with this device while it is opened to record.

If you're willing, I would like to PM (or email) you an example of what I'm talking about so that you can review it and verify that it works and make sense. After we're done and with your permission, I would like to add these functions and the record example to the library and examples download. Let me know.

Unfortunately, the Media Control Interface (MCI) is older technology and Microsoft has no plans to enhance it to include voice recognition (aka "speech-to-text"). Since this library is based entirely on MCI, voice recognition is out of scope.

However, quite a bit of work has been done on text-to-speech and speech-to-text technology. These are just a couple of links to give you a taste:Microsoft Speech API 5.3http://tinyurl.com/6krxcw

@ jballi:Standard example keeps throwing 'Error opening media file' on any mp3 I try to open. The files work fine with fincs' original library + player.The problem is I'm running Win98SE and the registry path specified in MCI_Open ( HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions ) does not exist in this version of Windows.Instead, an MCI Extensions section can be found in %windir%\win.ini. Mine reads as follows:

I could modify the function to include a win.ini section parser but I'd rather not mess with your code. For personal use I have simply commented out the return false line in the type check, but I'd appreciate if you'd do things right yourself. Thank you.

Standard example keeps throwing 'Error opening media file' on any mp3 I try to open. The files work fine with fincs' original library + player.

The problem is I'm running Win98SE and the registry path specified in MCI_Open ( HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions ) does not exist in this version of Windows.Instead, an MCI Extensions section can be found in %windir%\win.ini. Mine reads as follows:

<snip>

I could modify the function to include a win.ini section parser but I'd rather not mess with your code. For personal use I have simply commented out the return false line in the type check, but I'd appreciate if you'd do things right yourself. Thank you.

Thanks for reporting the problem.

You're right. The MCI_Open function assumes (incorrectly unfortunately) that you are running a 32-bit version of Windows by assuming that the MCI extensions are loaded in the registry. This test was added to this library because attempting to run an unregistered extension can produce catastrophic results (lock up, crash, etc.).

This should be an easy fix. Because of the new error trap code added to this library, the correct fix might be to remove the test entirely. I'll do some research.

I have a Window 98 machine (somewhere?) but I haven't booted it up in 4 years. Would you be willing to test the fix on your Win98 machine before I do a general release? Let me know. Thanks.