Click here to Skip to main content
Email Password   helpLost your password?

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.

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:

Value Meaning Meaning
cdaudio from position to position
digitalvideo from position
fullscreen
repeat
reverse
to position
window
sequencer from position to position
vcr at time
from position
reverse
scan
to position
videodisc fast
from position
reverse
scan
slow
speed integer
to position
waveaudio from 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:

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 :-)

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralThank you~
hwalts
13:22 26 May '08  
Big Grin
GeneralComplete Programming N00B
nem5009
11:30 2 Mar '08  
I've been trying to come up with a simple way to play music files for a few weeks now. Your way seems pretty intuitive, but i still can't get it to work. i pretty much copied your code verbatim, but it's still getting like 121 errors when i try to build. I don't have any knowledge of the system namespace, everything i've done up to this point has been with the std namespace, so i don't know if i'm missing a preprocessor or not, but this is what i've got so far:

------------------------------------------------------------------------------------------------------

#include "stdafx.h"
#include
#include
#include
#include
#include "Mmsystem.h"


using System;
using System.Runtime.InteropServices;


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

void main()
{
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;
}
}

---------------------------------------------------------------------------------------------------

any input would be tremendously helpful.

Questioncan i choose the output sound card??
Ibrahim Dwaikat
12:55 10 Nov '07  
If i have more than one sound card, how can I choose the output soundcard of them using MCI???

Visit Me

www.engibrahim.tk

GeneralHow to record the voice using asp.net
TarDuk
0:56 3 Oct '07  
It is the nice one. and works well but i want to record the voice using microphone is it possible if yes then how
QuestionHow to increase the speed while playing a wave file
srikanth rao nadipelli
21:23 20 Apr '07  
hello moemeka,
the article u have submitted is really good.U have shownhow we can useMCi commands to play different files. Now going a step further,I tried to increase/decrease the speed of the wave file while playing but i could nt succeed in doing it. Kindly giveme an idea of how i can increase or decrease the speed of a wave file it is being played as it can be done in Sound Recorder present in Windows.
srikanth

Srikanth Rao

GeneralFew comments...
mikker_123
14:07 28 Apr '06  
First of all I would love if this article is better rated and viewable... because you can easily do a lot of things with just few commands.

I needed option to play sounds one after another (async)... and after a bunch of problems (mciSendString call don't work on background ThreadsFrown) I came up with this solution (if anyone has suggestions... please... by all means -> say):

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Runtime.InteropServices;
using System.Threading;

namespace PeleSoundPlay
{
public class SoundPlayAll : Control
{
[DllImport("winmm.dll")]
private static extern long mciSendString(string strCommand,
StringBuilder strReturn, int iReturnLength, IntPtr hwndCallback);

public SoundPlayAll()
{
CreateHandle();
}

public void Play(string s)
{
al.Add(s);
DeQueue();
}

private ArrayList al = new ArrayList();
private bool playing = false;
private void DeQueue()
{
if (playing)
return;

string soundToPlay = "";

if (al.Count == 0)
return;

soundToPlay = al[0].ToString();
al.RemoveAt(0);

PlaySound(soundToPlay);
}

private delegate void PlaySoundDelegate(string soundToPlay);
private void PlaySound(string soundToPlay)
{
playing = true;
string sCommand = "open \"" + soundToPlay + "\" type mpegvideo alias MediaFile";
mciSendString(sCommand, null, 0, IntPtr.Zero);

sCommand = "
play MediaFile notify";
mciSendString(sCommand, null, 0, this.Handle);
}

// Declare the nofify constant
public const int MM_MCINOTIFY = 953;

// Override the WndProc function in the form
protected override void WndProc(ref Message m)
{
if (m.Msg == MM_MCINOTIFY)
{
// dunno why it won't work when I don't have this line... help?
Thread.Sleep(1);

string sCommand = "
close MediaFile";
mciSendString(sCommand, null, 0, IntPtr.Zero);

playing = false;
DeQueue();
}

base.WndProc(ref m);
}
}
}
Also this is great link for more information about mciSendString.

And finally... using C#.NET 2.0 only thing signature of function doesn't cause any problems to me:
        [DllImport("winmm.dll")]
private static extern long mciSendString(string strCommand,
StringBuilder strReturn, int iReturnLength, IntPtr hwndCallback);

GeneralRe: Few comments...
begray
21:50 20 Jan '07  
Great! Thanks!

Previously i've made my own solution (using aplication main wndproc), but experienced strange bug with not receiving MM_MCINOTIFY message. Your solution is very simple and neat Smile And finally, it works!!
QuestionUsing MCI play Video with Audio
kidconan
17:29 13 Sep '05  
How can I know the video file which I play, have audio or not?
If I play video without audio file and I call MCIWndSetvolume(lvol), My Application will freeze.
Pls, help me!
Thanks,
Ly Nguyen

Di khap the gian khong ai tot bang me
Gian kho cuoc doi khong nang ganh bang cha
AnswerRe: Using MCI play Video with Audio
brian scott
7:34 29 Dec '05  
Hi!   I think your problem is that if you want to play an .avi file with no audio stream, attempting to set the volume annoys the system!!   You can set a conditional so that if there is only one stream, you skip the volume command.   Look at the excellent code project article by A. Riazi on extracting avi frames - I lifted and modified this code snippet from there.   You need to add vfw32.lib to your project and include "vfw.h".

BOOL ExtractAVIFrames(CString szFileName)
{
      AVIFileInit();

      PAVIFILE avi;
      int res=AVIFileOpen(&avi, szFileName, OF_READ, NULL);
//
      AVIFILEINFO avi_info;
      AVIFileInfo(avi, &avi_info, sizeof(AVIFILEINFO));
//
      int streams=avi_info.dwStreams;   // see if there is more than one stream
                                                         // i.e. video+sound
//
      if(streams>1)
         {
            // set your volume, else skip that command
         }
//
}
//
This may be rather crude, but it seems to overcome the problem - at least it worked for me!!   Hope it is of some value!

Brian
GeneralRe: Using MCI play Video with Audio
kidconan
17:35 29 Dec '05  
Thanks a lot!
It is very helpful to me!
Best wishes!
Ly NguyenSmile

Di khap the gian khong ai tot bang me
Gian kho cuoc doi khong nang ganh bang cha
GeneralMultimedia
kidconan
19:34 17 Aug '05  
How can I play 3 AVIfiles at the same time? pls help me.

Di khap the gian khong ai tot bang me
Gian kho cuoc doi khong nang ganh bang cha
Generalhow 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....
farooq.k
2:13 22 Jun '05  
Hi! every one!!!

plz can can one specify a procedure for playing the mp3 songs in the required sound card when there are more than one sound card present in the system using MCIWND classes.... i have searched the whole msdn but im not able to get the solution...plz help me ..its urgent....


actually for wave songs we can specify the required device id when playing the wave song , when the song is to be played...

plz can any specify the solution

Farooq.k
GeneralImplementing the Progressbar
rfeiyuokiloyuiyuaetyrt
3:57 15 Apr '05  
Hi,
I want the code for implementing the progress bar in the GUI and that should be related to the song played.Means it is just similar to the GUI of Winamp,there in leftside we can see the plots plotted according to the frequency of the song.

Thanks.
With Regards,
Lavanya

Generalwhat about recording?
eXception!
5:30 4 Mar '05  
Thanks for this effort!

But ı have 2 questions:
-is it possible to record sound from microphone?
-is it possible to change properties of the recording? i mean
record quality,frequency,bitrate,channels vs...i need to reduce the
recorded file size.

need immediate help?

thanks for your interest
GeneralHow to Read Subtitles ?
tot2ivn
18:31 24 Feb '05  
I'm currently writing a Media Player.
However, I've no idea how to read the subtitle files.

Anyone has experience or knows some way to do that ?
Please, help me out.

THanks a lot

There are still many things eternal !!
Generalcallbacks
paulhemmings
13:49 24 Feb '05  
this was great. what i'd really like to do though is build a playlist. there are two ways i can see to do this. one is to poll everynow and then to see if the current song has finished, or the better way would be to give it a callback fn and turn notify on.

i've searched around and can't find any examples of people passing a callback fn.

anyone got any sample code?
GeneralWAV file mixing
Nightfox
16:59 16 Feb '05  
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
Ima Bagheri
1:19 5 Feb '05  
Hello
I am a C#.net programmer
Please help me how can I Use Com interoperability
or another methods to display video in an existing
interface such as Form or PictureBox Control.
Thanks a lot
GeneralRe: I have a problem
Jerod Edward Moemeka
8:36 5 Feb '05  
Hi,
there are actually a few approaches available to you. If you have Visual Stusdio .net, the easiest way is to simple use the Winbdows Media Player ActiveX control in your application. Anotyher approach requires DirectX 9 or higher. The Managed DirectX libraries include one for basic AudioVideo, infact I think it's called Microsoft.DirectX.AudioVideo.dll. Once this referenced and the namespace inported, you can create Video object and target them to Panels, Forms and the like.

Jerod Edward Moemeka
Genesys Corporation
Generalhow to get sound instantaneous level?
xfy
4:46 7 Nov '04  
i can get aConfused volume,but it's a fixed value.i want to get a instantaneous value changing with sound,how do?


hzxfy@21cn.com

xfy
Generalspaces in paths
Anonymous
7:13 1 Sep '04  
is there an easy to understand workaround for using mciSendString with spaces in paths? I searched the web and only found a solution for vb but dont know what to write in c/c++:

If InStr(1, AppPath, " ") Then AppPath = """" & AppPath & """" 'if there is a space in the path add some ""

mciSendString "open " & AppPath & " type sequencer alias mid1", 0, 0, 0 'open midi file

Thanks in advance!


GeneralRe: spaces in paths
Anonymous
17:04 2 Sep '04  
ok, problem already solved. Thank you!
Generalduration of a wav file
elxharoon
23:57 13 Jul '04  
I want to know the duration of a saved wave file. How can I do it ?
GeneralRe: duration of a wav file
Jerod Edward Moemeka
17:21 14 Jul '04  
the 'length' argument of the status command returns the total length of the media, in the current time format. IN your case that would be the wave file.
the command would go:
status your_wave_file length

Jerod Edward Moemeka
Vice President of Technology
Frontline Inc.


Last Updated 12 Feb 2004 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010