Click here to Skip to main content
16,021,181 members
Articles / Desktop Programming / MFC
Article

Using MCI to control multimedia

Rate me:
Please Sign up or sign in to vote.
3.55/5 (17 votes)
11 Feb 20044 min read 180.8K   64   25
MP3, AVI, WAVetc.: MCI exposes low level functionality that allows gives you amazing multimedia powers!

Introduction

The Media Control Interface exposed through winmm.dll can provide your multimedia applications with a device-independent layer that exposes capabilities for controlling audio and visual peripherals. With it, your code can pretty much support ANY multimedia device! You could quite literally create applications that utilized waveform (MP3, .wav, etc.), MIDI, CD audio, and digital-video. Imagine the possibilities! I know what you're thinking, DirectX right? Well, take it from someone who's swapped sound buffers for years. The real power of MCI is in its ease of use (sometimes to a fault), and portability (no redistributables). This is of course in no way putting down the power and flexibility of DX.

MCI basically provides two ways of accessing the low level multimedia devices. Through a cryptic structure of message (think lots and lots of structures to create), or passing strings into the interface. (I should note that it's not an either or thing; you can use both). The two methods are exposed as two interfaces (semantically speaking), the Command Message Interface, CMI, and the Command String Interface, CSI. winmm.dll provides a function for each. mciSendCommand sends the well defined structures and constants into the CMI while mciSendString passes command strings, which need to follow a certain format, into the CSI. The focus in this article will be on the CSI. Mainly because it's a lot easier to get up to speed and start doing pretty amazing things with.

mciSendString

This function takes a string, identified by lpString, and sends it to the identified MCI device.

MCIERROR mciSendString(
  LPCTSTR lpString,
  LPTSTR lpszRetVal,
  UINT length,
  HANDLE hwndCallback
);

All the command information should be included in the lpString parameter. The RetVal parameter represents a pointer to the buffer that will receive any returned information. If you are not interested in responses, the value can be null. If you are expecting any return information (for example, if you are querying for status information), you must specify the length of the return buffer with the length value. The final argument will be left null for the purposes of this discussion.

The above function declaration can be implemented with minimal difficulty in .NET. The rest of the article focuses on building a very very very very basic console based media player that will quite literally play any Windows supported media format. Including AVI and MPEG movies!

Of course, the first step is having the InteropServices namespace declared. Next, I create a signature for mcsSendString.

C#
using System;
using System.Runtime.InteropServices;

[DllImport("winmm.dll")]
extern static int mciSendString(string command, 
  IntPtr responseBuffer,int bufferLength, int nothing);

I use an IntPtr here so I can use a HGlobal to store the response string. It's just a preference so I feel like a C++ programmer. You can also use integer type arrays, a StringBuilder, or whatever else works for you.

The simple player we are creating will use the CSI "play" command string identified by the format below:

"play {0} {1} {2}"

The value of {0} would be the device you want to play, {1} and {2} would be used for any flags you might want to add into the mix. The full set of possible combinations is highlighted in the list below:

ValueMeaningMeaning
cdaudiofrom position to position
digitalvideofrom position
fullscreen
repeat
reverse
to position
window
sequencerfrom position to position
vcrat time
from position
reverse
scan
to position
videodiscfast
from position
reverse
scan
slow
speed integer
to position
waveaudiofrom position to position

This list was acquired form MSDN. You can find the full set at this URL:

As you might have already imagined, cdaudio represents the CD audio device type, as do sequencer, AVIVideo, waveform, videodisc, and sequencer (MIDI) their given device types. For the purposes of our simple console based media player, we will not be utilizing any advanced functionality. All we will specify is "play {0}" where {0} represents the file to play. The interface will automatically select the device based on either the extension recorded in the registry, or the [mci extension] section of the SYSTEM.INI file.

Finally, we place the code below in the Main method of the console application:

C#
while(true)

{
   Console.WriteLine("Type in the fully qualified" + 
                " path to the file you want to play");
   string file = Console.ReadLine();
   if(file != "end")
   {
      string command = string.Format("play {0}",file);
      IntPtr response = Marshal.AllocHGlobal(128);
      int err = mciSendString(command,response,128,0); 
      Console.WriteLine("{0} error(s)",err); 
   }else
     break;

}

It basically asks the user for a file name and plays it. I'm not sure about this but I think I once read somewhere that MCI will only pass 128 bytes of data at a time; hence the hardcoded 128 to represent that boundary. Although I do know that there is a limit, the actual number has escaped my mind.

That's it! All you need to do to start writing your own complex MP3 players, recorders, rippers and much much more. Believe it or not MCI even allows accessing media at external URLs. Simply replace the local file name with a fully qualified URI (include the 'http:\\' too). Before you get too happy though, be advised that sendString does not handle spaces in file names very well.

Final thoughts

Enjoy :-)

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
Hi I'm Edward Moemeka,
For more interesting articles about stuff check out my blog at http://moemeka.blogspot.com
To correspond, email me at edward.moemeka@synertry.com
To support my company, thus help me feed my family, check out our awesome online preview at www.synertry.com. Remember, its in alpha Wink | ;-)

Comments and Discussions

 
Questionis it possible to duplicate channels using MCI commands ? Pin
srdusad13-May-10 19:24
srdusad13-May-10 19:24 
GeneralThank you~ Pin
hwalts26-May-08 12:22
hwalts26-May-08 12:22 
GeneralComplete Programming N00B Pin
nem50092-Mar-08 10:30
nem50092-Mar-08 10:30 
Questioncan i choose the output sound card?? Pin
Ibrahim Dwaikat10-Nov-07 11:55
Ibrahim Dwaikat10-Nov-07 11:55 
QuestionHow to record the voice using asp.net Pin
Tarun Dudhatra2-Oct-07 23:56
Tarun Dudhatra2-Oct-07 23:56 
QuestionHow to increase the speed while playing a wave file Pin
srikanth rao nadipelli20-Apr-07 20:23
srikanth rao nadipelli20-Apr-07 20:23 
GeneralFew comments... Pin
mikker_12328-Apr-06 13:07
mikker_12328-Apr-06 13:07 
GeneralRe: Few comments... Pin
begray20-Jan-07 20:50
begray20-Jan-07 20:50 
QuestionUsing MCI play Video with Audio Pin
kidconan13-Sep-05 16:29
kidconan13-Sep-05 16:29 
AnswerRe: Using MCI play Video with Audio Pin
brian scott29-Dec-05 6:34
brian scott29-Dec-05 6:34 
GeneralRe: Using MCI play Video with Audio Pin
kidconan29-Dec-05 16:35
kidconan29-Dec-05 16:35 
GeneralMultimedia Pin
kidconan17-Aug-05 18:34
kidconan17-Aug-05 18:34 
Questionhow to a play a required mp3 song in the required output device when there are more than one sound card present in the system....plz very very urgent.... Pin
Cpp guy22-Jun-05 1:13
Cpp guy22-Jun-05 1:13 
GeneralImplementing the Progressbar Pin
Member 185549415-Apr-05 2:57
Member 185549415-Apr-05 2:57 
Questionwhat about recording? Pin
eXception!4-Mar-05 4:30
eXception!4-Mar-05 4:30 
QuestionHow to Read Subtitles ? Pin
tot2ivn24-Feb-05 17:31
tot2ivn24-Feb-05 17:31 
Generalcallbacks Pin
paulhemmings24-Feb-05 12:49
paulhemmings24-Feb-05 12:49 
GeneralWAV file mixing Pin
CalicoSkies16-Feb-05 15:59
CalicoSkies16-Feb-05 15:59 
I have been looking for a way to mix several WAV files into a single WAV file (so that each sound from the separate WAV files plays simultaneously). Information on how to do this seems elusive. Is there a way to do this easily with MCI?

I've been working with DirectX (specifically, DirectMusic and DirectSound) in my application. DirectX is able to mix sounds before it passes the audio to the sound card.. Is there perhaps a way to simply have it re-direct the audio to a WAV file on the hard drive instead?

Eric
GeneralI have a problem Pin
Ima Bagheri5-Feb-05 0:19
Ima Bagheri5-Feb-05 0:19 
GeneralRe: I have a problem Pin
Edward Moemeka5-Feb-05 7:36
Edward Moemeka5-Feb-05 7:36 
Questionhow to get sound instantaneous level? Pin
xfy7-Nov-04 3:46
xfy7-Nov-04 3:46 
Generalspaces in paths Pin
Anonymous1-Sep-04 6:13
Anonymous1-Sep-04 6:13 
GeneralRe: spaces in paths Pin
Anonymous2-Sep-04 16:04
Anonymous2-Sep-04 16:04 
Generalduration of a wav file Pin
elxharoon13-Jul-04 22:57
elxharoon13-Jul-04 22:57 
GeneralRe: duration of a wav file Pin
Edward Moemeka14-Jul-04 16:21
Edward Moemeka14-Jul-04 16:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.