Media Player

 

By Marius Hudea ( marius_hudea@personal.ro)

 

The purpose of this application is to teach you how to use the Windows MCI Interface in order to play audio & video files without using any Active-X controls.

 

   First of all I would like to mention some people that helped me a lot, directly or indirectly.

   I am mentioning his name here because they deserve it and because I don’t want people to think I have stolen their code and that I am using their work to receive credit for it.

 

  1. Abdullah Al-Ahdal (a_ahdal@yahoo.com)

  It all started from him and he should receive a lot of the credits. He was the one that made me start this project. His work,  available on Planet Source Code, was great but contained a lot of imperfections and I wanted to improve it. What I did turned into a completly different media player.

 

  1. The KPD Team  (KPDTeam@allapi.net)

  They  have designed the wonderfull application API-Guide. I must admit that it is hard for me to remember all those API functions and constants so API-Guide is a big help. It earned a place in my taskbar. It’s so sad that they can no longer continue improving their application.

 

  1. Planet Source Code (http://www.planet-source-code.com)

  A special Thank You!  goes to all the people that continue working on free projects and to the ones that help others improve their programming skills.

 

 

LIKE ANYTHING ELSE THAT'S FREE, THIS PROJECT IS PROVIDED AS IS AND COMES WITH NO WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED. IN NO EVENT WILL THE AUTHOR BE LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE.

 

  I have worked a lot on this project and I believe it is safe to use. However, this project is provided as-is, without any guarantees that it will work or that will not generate any errors.

  It works great on my computer, my friends also tested this project and they found it safe to use but I had to say that because

I don’t want anybody to blame me if something goes wrong.  

  You may use this source code in any projects you work on as long as they are free or if you are using code from my project for educational-related programs. If you are going to use this in a commercial application I will not stop you or sue you but I would like you to write my name somewhere in the help files or in the About Box of  your application. I would also like to receive a (registered) copy of  your application.

 

 

Introduction

 

First of all, what is MCI ?

 

As the Microsoft MSDN says:

 

 „The Media Control Interface (MCI) provides standard commands for playing multimedia devices and recording multimedia resource files. These commands are a generic interface to nearly every kind of multimedia device.”

 

   So, by using the MCI, we could play virtually any media file, audio or video, if we have a propper multimedia device.

 

   Ok, but what is a multimedia device ? As far as I know, you could imagine that a multimedia device is a software driver that receives commands and performs things for you. A multimedia device is is a library that uses software codecs installed on your computer to translate into something that can be played on your soundcard or on your video card.

   For example, in this project I am using a multimedia device called „MPEGVideo” to play the well-known *.mp3 files. This multimedia device can handle any MPEG files, audio or video and also other file formats. The multimedia device will load a codec on your computer, usually „Fraunhofer ILS MPEG Layer-3 Codec” ( if the selected file was a *.mp3 ), and will use it to play the file on your sound card.

   This multimedia device can also decode *.avi files.In this project I am using this device to play *.avi files because, on my computer it is faster.

    You can get a list of the available multimedia devices on your computer by viewing the System.ini file, located in your Windows folder. You can see both at the same time by running the SysEdit  or the msconfig program.

    Bellow is the list of multimedia devices that normally are installed automatically when you install Windows.

 

Multimedia Device

Description

cdaudio

Plays Audio-CD’s

waveaudio

Plays *.wav files and compatibles

sequencer

Plays *.mid & *.rmi files ( midi )

MPEGVideo

Plays most video & audio files

avivideo

Plays *.avi files ( see note )

 

  You could use the avivideo multimedia device to play *.avi files but I don’t recommend it. As far as I know, this multimedia

device uses only the GDI system in order to accelerate the playback. This is why you might notice frame losses or slow rendering of the video file.

  It seems that the MPEGVideo uses a lot of functions that accelerate the playback of video files, overlays beeing just one of them.

 

 

     The Multimedia Controle Interface can be accessed using two API functions contained in the winmm.dll library.      

 

 

 

  Well, only the first function is really important but the seconds is usefull if we want to show a text explaining what happened if an error has occured.

  The mciSendString function is used to send commands to the MCI  and will always will return a value (Long) that will be 0 (zero) is everything is Ok or an error code. The error code can’t explain us the error, that is why we will use the mciGetErrorString function that will give us a text explaining what happened

 

Here’s what the mciSendString parameters mean:

 

·        lpstrCommand

A command string.

 

·        lpstrReturnString

A buffer (String) that receives return information. If no return information is needed, this parameter can be NULL.

 

·        uReturnLength

Size, in characters, of the return buffer specified by the lpstrReturnString parameter.

 

·        hwndCallback

Handle of a callback window if the “notify” flag was specified in the command string. This will not be used by our project and will always be NULL.

 

Here’s what the mciGetErrorString parameters mean:

 

·        dwError

The error code. ( The value returned by the mciSendString function )

 

·        lpstrBuffer

A buffer (String) that receives return information ( the error message)

 

·        uLength

Size, in characters, of the return buffer specified by the lpstrBuffer parameter.

 

 

     If everything goes well, the mciSendString function should return 0 (zero)

 

 

      I have created functions or procedures that simplify the interaction with MCI.

      Each function that interacts with MCI will return a value (Boolean). It will be True or False if an error has ocurred.

 

      I am also using 4 ( four ) variables in my project that hold the status of the current audio or video stream:

 

·        Public IsLoaded As Boolean

·        Public IsPlaying As Boolean

·        Public IsPaused As Boolean

·        Public IsFullscreen As Boolean    

 

IsLoaded – A media file ( called Stream ) is loaded ( with the OpenStream function ). If we want to open another file, the   previous media file loaded must be closed. IsLoaded is True is a file is open.

IsPlaying – A media file is playing at the current time. This is usefull because most commands are working only when a file is playing.

IsPaused – A media file is playing and is paused. When a media file is paused we should not refresh the file position on progress bars and we should stop any subtitles.

IsFullScreen – The media file is a video file and it is in Full Screen Mode.

 

      Note. The functions or the sub’s in the modMCI module will not change these variables, you will have to change them in the application if needed, considering the return code the functions will return.

 

 

Opening a media file…

 

Public Function OpenStream(VideoHandle As Long, FileTitle As String) As Boolean

 

This function will open a media file and returns True if everithing is Ok.

 

Parameters:

 

 

What is a VideoHandle?

   Every window has it’s own handle. Think of it as the nail that holds a painting on the wall. It’s an unique identifier.

What is interesting is that even buttons, menu’s, scrollbars are actually windows so you could actually play a video in a button.

 

The MCI requires a valid window handle. In my project the VideoHandle is the handle of the frmView window or the handle of the frmFullscreen window ( when in Full Screen ) mode.

 

The command string that the function will send to the MCI is the following:

 

"open " & StreamName & " type " & StreamDevice & " Alias " & StreamAlias & " parent " & VideoWindowHandle & " Style child"

 

Or, in plain English ( you can’t send this string to the MCI ):

 

„Open the filename that has the multimedia device StreamDevice , call the media from now on StreamAlias and make the parent window the window that has the handle VideoHandle.The video window will have the style style”

 

Note: The maximum length of the string commands accepted by the mciSendString  is 255 characters.

 

Open – tells MCI to open the file

StreamName – The filename. This could be very long, that’s why it must be reduced it somehow. And it’s not allowed to contain spaces. I’ll use a function in a standard library that comes with Windows to convert the filename to it’s MS-DOS representation. For example :

 

C:\Caffe Concert\ Dave Stewart & Candy Dulfer - Lili was Here.mp3 ®  C:\Caffec~1\Davest~1.mp3

 

The function is the following:

 

Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long

 

LpszLongPath – The original Filename

LpszShortPath –  A buffer (String) where the new short filename will be stored.

CchBuffer – The length, in characters, of the buffer.

 

It returns the length of the new string that holds the short filename.

 

StreamDevice – The multimedia device that will be used to play the media file.

In my project I am using another function in the same module to select the proper multimedia device

 

StreamAlias – This is a name , a nick, an unique identifier that will be used to tell MCI what to do with the opened media file.

 

Note: If you are going to use a constant string ( ex. MyMP3 ) you’ll have problems if another instance of your application is opened because the alias is already in use. The problem is that you will not be able to open a second file using the same alias.

  This is why you should generate an unique StreamAlias each time you open a new media file by using the Rnd() function that comes with Visual Basic or any other method.

  In my project I am using  the number of milliseconds that have elaspsed since Windows was started. There is  a possibility for two instances of your application to open a file at the same time but the possibility it is very small ( smaller than using Rnd() )

 

  The function that will return the number of milliseconds elapsed since Windows started is :

 

Private Declare Function GetTickCount Lib "kernel32" () As Long

 

  It simply retuns the number of milliseconds.

  Note: There is a famous Windows bug here, but it is not caused by the project or by accessing the function. When Windows reaches the maximum value accepted by the Long type ( about  25 days, if your computer stays on for that long ), it will crash.

  However, there is a patch for this bug on Microsoft’s web site.

 

VideoWindowHandle – It’s the VideoHandle parameter that you have passed to the function. It tells MCI that his parent window is the window that has the handle VideoWindowHandle .

 

Style – Represents the style of the window. It can be a string constant or a Long variable like in the command string shown previously.

 

Possible styles :

 

style child

Opens a window with a child window style.

style overlapped

Opens a window with an overlapped window style.

style popup

Opens a window with a pop-up window style.

style style_type

Indicates a window style.

 

  Well, that’s how you open a media file. All you have to remember is to close the media file when your application closes, otherwise the media will remain running in the background and you won’t be able to stop it (unless you know the StreamAlias).

 

   I believe this function was the hardest. I have tried to make this whole project very easy to understand. I hate inserting

comments in source code so, please try to understand me.

   There are also some things that you might think I forgot to do or that I did them on the run but I have tried to keep this whole

project as simple as possible.

 

 

 

Testing Configuration

 

This project was tested on several computers with different configurations.

 

My computer:

 

Home-made AMD K6-2 3D Now! 500 MHz ,160MB SDRAM , nVIDIA Vanta 8 MB SDRAM, Win98 SE

 

My friend’s PC:

 

Home-made AMD K6-2 3D Now! 350 MHz, 64 MB SDRAM, nVIDIA Vanta 8MB SDRAM, Win2000 Pro

 

My sister’s old PC:

 

Siemens-Nixdorf Intel-P90 MHz , 64 MB SDRAM, Tseng Labs 2 MB VRAM, Win95 Pan European Edition

 

   It works great on my computer, runs all movies, even DivX 5 Wide Screen without glitches and without freezing the

Screen. My friend has problems with wide-screen DivX 5 movies because it has only 64 MB SDRAM. My sister can

not see movies on her old ( antique) computer but she enjoys listening to MP3 music with my program. (and the music

runs great on that computer).

 

Tested on:

 

A Beautiful Mind ( 2 CD’s DVD Rip 23.976 fps  - DivX 5)

Eyes Wide Shut  ( 1 CD Video Tape Rip 23.976fps AngelPotion MPEG-4 Codec )

Monsters Inc.  ( 1CD DVD Rip 23.976fps DivX)

 

A lot  of  Trance, Dream-Trance  & Oldies music

 

My personal favourites : ATB , Dj Taucher,Paul Oakenfold, Trance All Stars.

                                     Mike Oldfield  

 

 

Known Bugs

 

  I know there are some small bugs in this project. Please mail me if you fiind some serios bugs because I’ll try to fix them as soon as possible. I have chosen not to fix some small bugs ( like the one explained bellow) because the solution would only complicate things a lot.

 

Bugs :

 

·        I have found that on my computer, if i install the AC3 Audio Direct Show codec, the *.mp3 playback is seriously altered. Files that have a variable bitrate or files that are not coded at standard bitrate ( 128kbs, 192kbps, 320kbs) will be heard with pops and glitches. The MCI autodetects the best codec and will select this one.

·        On files with variable bitrate the total time is not properly detected but the progress bar is running well. This is again MCI’s fault because ( I believe ) it only scans the first frames of the files and doesn’t test all the frames in order to properly detect their bitrate.

·        Time is not properly detected on video files without sound. I won’t bother fixing this. I don’t think it is the purpose of this project.

 

   Currently only 3 lines of subtitling are accepted. I should not consider this one a bug because I haven’t found yet any subtitles with more than 3 lines of text. The way I show this text on the screen is not a very smart one but, as I already said, this was not the purpose of the project.

   Only microDVD and SubRIP subtitles are decoded by the subtitles module at this moment.

 

 

Final notes :

 

  I have studied English for over 10 years and I want to improve it so, if you fiind any grammatical or language errors, please mail me and tell me where I have made an error.

  Please don’t vote for me on Planet Source Code unless I really deserve it. I did not do this for votes.

  However, voting is the only way I will know how good I am at programming. If you do vote, be honest.

  If you fiind any errors or if you need extra information regarding this project, mail me.

  If you can, please send me a postcard ( is it post-card? ) with a picture of your town or your country.

  

 

  Oh, you have made it. You have reached the end of the document. Thank you for your time. Here’s my mail and my snail-mail in case you want to contact me. Please don’t send me advertising stuff . J

 

      Marius Hudea

      C.I.Bratianu 5 Nr.5 Ap.27 Et.4 Sc.B

      Medias, Cod 3125, Sibiu

      ROMANIA