By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
425,967 Members | 815 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 425,967 IT Pros & Developers. It's quick & easy.

adding audio or video files to a form

vdraceil
100+
P: 236
Hi, can anyone help me to add an audio or video file to a form and play it from there??
Jul 6 '07 #1
Share this Question
Share on Google+
6 Replies


Robbie
100+
P: 180
Hi, can anyone help me to add an audio or video file to a form and play it from there??
For both video and audio you can use MCI (Windows' Multimedia Control Interface).

However, if you are going to only need audio, I highly recommend using FMOD (you can do so much more - set the volume, frequency, panning, view waveform and spectrum data, etc, even though you probably won't need all that. XD)

FMOD is used by means of a DLL, meaning that you just call functions like normal in VB.

MCI is very different - you simply send a commands as a string and get a return value.

For both, there are no 'events' for when a sound reaches the end of playback, for example, you have to keep bugging them asking for the current position and seeing if that's how long the sound is (it must've reached the end). Also both can cope with many files open at once, although FMOD seems to be able to cope with more, because it's very often used for a sound effects engine in games, therefore it needs to be able to deal with many many sounds.

Anyway... a quick tutorial of how to use MCI! ^-^

Firstly, to be able to send commands to MCI in VB6, you need to put this module in your VB project:
Expand|Select|Wrap|Line Numbers
  1. Declare Function mciSendString Lib "winmm.dll" Alias _
  2.     "mciSendStringA" (ByVal lpstrCommand As String, ByVal _
  3.     lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _
  4.     hwndCallback As Long) As Long
  5.  
  6. 'Also, I (Robbi-985) found this list of error codes (and
  7. 'their explanations, is the point...)
  8.  
  9. 'MCI Errors Defined                        MCI Error Number
  10. '----------------------------------------------------------
  11. '#define MCIERR_BASE                       256
  12. '
  13. '#define MCIERR_INVALID_DEVICE_ID          257
  14. '#define MCIERR_UNRECOGNIZED_KEYWORD       259
  15. '#define MCIERR_UNRECOGNIZED_COMMAND       261
  16. '#define MCIERR_HARDWARE                   262
  17. '#define MCIERR_INVALID_DEVICE_NAME        263
  18. '#define MCIERR_OUT_OF_MEMORY              264
  19. '#define MCIERR_DEVICE_OPEN                265
  20. '#define MCIERR_CANNOT_LOAD_DRIVER         266
  21. '#define MCIERR_MISSING_COMMAND_STRING     267
  22. '#define MCIERR_PARAM_OVERFLOW             268
  23. '#define MCIERR_MISSING_STRING_ARGUMENT    269
  24. '#define MCIERR_BAD_INTEGER                270
  25. '#define MCIERR_PARSER_INTERNAL            271
  26. '#define MCIERR_DRIVER_INTERNAL            272
  27. '#define MCIERR_MISSING_PARAMETER          273
  28. '#define MCIERR_UNSUPPORTED_FUNCTION       274
  29. '#define MCIERR_FILE_NOT_FOUND             275
  30. '#define MCIERR_DEVICE_NOT_READY           276
  31. '#define MCIERR_INTERNAL                   277
  32. '#define MCIERR_DRIVER                     278
  33. '#define MCIERR_CANNOT_USE_ALL             279
  34. '#define MCIERR_MULTIPLE                   280
  35. '#define MCIERR_EXTENSION_NOT_FOUND        281
  36. '#define MCIERR_OUTOFRANGE                 282
  37. '#define MCIERR_FLAGS_NOT_COMPATIBLE       283
  38. '#define MCIERR_FILE_NOT_SAVED             286
  39. '#define MCIERR_DEVICE_TYPE_REQUIRED       287
  40. '#define MCIERR_DEVICE_LOCKED              288
  41. '#define MCIERR_DUPLICATE_ALIAS            289
  42. '#define MCIERR_BAD_CONSTANT               290
  43. '#define MCIERR_MUST_USE_SHAREABLE         291
  44. '#define MCIERR_MISSING_DEVICE_NAME        292
  45. '#define MCIERR_BAD_TIME_FORMAT            293
  46. '#define MCIERR_NO_CLOSING_QUOTE           294
  47. '#define MCIERR_DUPLICATE_FLAGS            295
  48. '#define MCIERR_INVALID_FILE               296
  49. '#define MCIERR_NULL_PARAMETER_BLOCK       297
  50. '#define MCIERR_UNNAMED_RESOURCE           298
  51. '#define MCIERR_NEW_REQUIRES_ALIAS         299
  52. '#define MCIERR_NOTIFY_ON_AUTO_OPEN        300
  53. '#define MCIERR_NO_ELEMENT_ALLOWED         301
  54. '#define MCIERR_NONAPPLICABLE_FUNCTION     302
  55. '#define MCIERR_ILLEGAL_FOR_AUTO_OPEN      303
  56. '#define MCIERR_FILENAME_REQUIRED          304
  57. '#define MCIERR_EXTRA_CHARACTERS           305
  58. '#define MCIERR_DEVICE_NOT_INSTALLED       306
  59. '#define MCIERR_GET_CD                     307
  60. '#define MCIERR_SET_CD                     308
  61. '#define MCIERR_SET_DRIVE                  309
  62. '#define MCIERR_DEVICE_LENGTH              310
  63. '#define MCIERR_DEVICE_ORD_LENGTH          311
  64. '#define MCIERR_NO_INTEGER                 312
  65. '
  66. '#define MCIERR_WAVE_OUTPUTSINUSE          320
  67. '#define MCIERR_WAVE_SETOUTPUTINUSE        321
  68. '#define MCIERR_WAVE_INPUTSINUSE           322
  69. '#define MCIERR_WAVE_SETINPUTINUSE         323
  70. '#define MCIERR_WAVE_OUTPUTUNSPECIFIED     324
  71. '#define MCIERR_WAVE_INPUTUNSPECIFIED      325
  72. '#define MCIERR_WAVE_OUTPUTSUNSUITABLE     326
  73. '#define MCIERR_WAVE_SETOUTPUTUNSUITABLE   327
  74. '#define MCIERR_WAVE_INPUTSUNSUITABLE      328
  75. '#define MCIERR_WAVE_SETINPUTUNSUITABLE    329
  76. '
  77. '#define MCIERR_SEQ_DIV_INCOMPATIBLE       336
  78. '#define MCIERR_SEQ_PORT_INUSE             337
  79. '#define MCIERR_SEQ_PORT_NONEXISTENT       338
  80. '#define MCIERR_SEQ_PORT_MAPNODEVICE       339
  81. '#define MCIERR_SEQ_PORT_MISCERROR         340
  82. '#define MCIERR_SEQ_TIMER                  341
  83. '#define MCIERR_SEQ_PORTUNSPECIFIED        342
  84. '#define MCIERR_SEQ_NOMIDIPRESENT          343
  85. '
  86. '#define MCIERR_NO_WINDOW                  346
  87. '#define MCIERR_CREATEWINDOW               347
  88. '#define MCIERR_FILE_READ                  348
  89. '#define MCIERR_FILE_WRITE                 349
  90. '
  91. '#define MCIERR_CUSTOM_DRIVER_BASE         512
  92.  
Now...
It seems there are basically 2 types of commands you can send - ones which require a return value (a response, in English...), and ones which don't. For both, you get back an error code.

When you send a command which doesn't require a response, use code like this:
TempError = mciSendString("open that file", 0&, 0, 0)

TempError will be given the error code which that MCI command made. If it's 0, there was no error. Otherwise, look at that massive piece of code above to find a number which matches, and that'll tell you what that error code means.

When you send a command which DOES require a response, use code like this:
TempError = mciSendString("how long is that file?", ReturnString, 255, 0)

Again, TempError is the error code (this is always the case), hopefully 0.
We've told MCI to put the answer to the question we asked, into ReturnString.
And we told it not to make the answer more than 255 characters long.

How to use MCI to actually do something (a.k.a. Examples)

You know in VB6, everything's based on objects, and every obejct has a name?
Well in MCI it's kinda the same, except it's called an alias. The alias basically is the sound, to MCI - every time you give it the alias, it refers to that sound.

When you open a new file (video or audio), you need to give it an alias.
To open a file, send the command open followed by the name of the file, in speech-marks.
- You also need to tell it what type of file you're telling it to open.
- Lastly, you need to give it an alias - a name which you can refer to this loaded file as later, when you need to stop it or play it again for example.

The full command could look like this:
open "c:\An Audio File.wav" type waveaudio alias MyFirstSound

- The type will usually be one of 2:
- - waveaudio
- - mpegvideo
Yes, it sounds weird telling it that a sound is in fact an 'mpegvideo', but there is no such type as 'mpegaudio'. mpegvideo seems to look for any codec you have on your system which can play this file (for example, it can also play OGG files if you have the Ogg Vorbis codecs installed!)

- The alias can be anything alphabetical, and it is case sensitive (i.e. MyFirstSound isn't the same thing as myfirstsound). Possibly it can also have numbers in it, but I'm not sure about that, and I've never had to use numbers, so I haven't.

To put speech-marks into a string in VB6 is not quite as straight-forward as we'd like it to be.
e.g.
String = "My name is "Robbi-985""
That makes no sense if you follow the speech-marks.
It can be done though by telling VB to insert the character with the ASCII code 34 (this the code for a speech-mark).
e.g.
String = "My name is"+chr(34)+"Robbi-985"+chr(34)
That's what I mean - it's a mess, but it works.

So, to send the string which I gave as an example above, you'd type in VB:
TempError = mciSendString("open "+chr(34)+"c:\An Audio File.wav"+chr(34)+" type waveaudio alias MyFirstSound)
Nasty. But anyway, that's really the only time you'll need to give it a speech-mark, thankfully.

The next thing that you should know is how to REMOVE an alias (i.e. sound/video) when you don't need it any more! If you don't remove it, then the next time your program runs, it will cause an error when trying to open a sound with that alias again, because that alias will already be being used (left over from before)!

This is probably the simplest command of them all - close:
close MyAudioFile
That's it.
Also, in case your program crashes or is not exitted properly (like using the Stop button on VB6 when not made into an EXE yet), you should tell MCI to make sure that your alias is not already being used before trying to open a sound and use that alias. In other words, tell it to close it before opening it. Again, it sounds weird, but it will prevent an error when you try to use the aliss which is already used, and if it isn't already being used, it will not cause an error, so it's a win-win situation.

To play a loaded sound, send ... surprisingly... the play command:
play lynxaudiofile
...and to stop a playing sound, if it is playing (again, an error won't be caused it it isn't playing - MCI is generally pretty error-resiliant):
stop lynxaudiofile

So far, these have all been commands where you're not asking MCI to tell you something - to give back a return value.
What if you want to skip 5 seconds ahead in a playing sound?
You need MCI to tell you how long the sound is, then add 5 seconds to that, then tell it to skip to there.
So...
First, you must tell it what unit of length to operate in - MCI can tell you how long a sound is in samples or miliseconds, but miliseconds is the one we want here. So we tell it this:
set MyAudioFile time format ms
Again, we're not asking for anything back yet, so we use code like this:
TempError = mciSendString("set MyAudioFile time format ms", 0&, 0, 0)

Next, we ask it, how long is the sound?
Whenever you ask MCI to tell you anything, you will always begin the command with status. For example, to get the length of a sound we use:
TempError = mciSendString("status MyAudioFile position", ReturnString, 255, 0)

So it gives back an error code as usual in TempError, but stores how long the sound is, in milliseconds in ReturnString.
IMPORTANT - MCI always gives back responses as strings!
(Not the error codes - they're not exactly a response, more a result.)
So, if you want to store the position of the sound as a Long variable type, you'll want to do:
Dim MyAudioFileLength as Long
MyAudioFileLength = Val(ReturnString)

Here, we need the position though:
TempError = mciSendString("status MyAudioFile position", ReturnString, 255, 0)
We'll store it in a variable called SoundPosition:
SoundPosition = Val(ReturnString)

So, we wanted it to skip 5 seconds ahead. Since we've been told the length in milliseconds, we'll need to add 5000 onto its current position and tell it to skip to there.
SoundPosition = SoundPosition + 5000

Next step is telling it to skip ('seek') to this new position!
TempError = mciSendString("seek MyAudioFile to " + Str(SoundPosition), 0&, 0, 0)
Note, we're not asking for MCI to give something back here.

Note also that after seeking, the sound playback stops, so you must tell it to carry on playing!
TempReturn = mciSendString("play MyAudioFile", 0&, 0, 0)

My God, I went on a bit. But I hope that is useful info. Even if you are using VB.NET, the command strings of MCI are always the same.
Jul 7 '07 #2

Robbie
100+
P: 180
Oops, forgot to mention video with MCI. Well basically you'll be glad to know it's exactly the same - open, close, play, stop, seek. Even using the type mpegvidoe has worked for every video I've tried.

Also you might be wondering why I highly recommended FMOD and then explained how to use MCI. Simply because MCI is easier and it seems like you don't need those vast features now. Also if you get used to using MCI with audio, it's extremely easy to start using video with MCI too.

You need to send 2 more commands to get the video to display in your program.
Actually, the first one is just another thing added to the open command:
TempError=mciSendString("open "+VideoFile+" type mpegvideo alias MyVideoFile parent " + Str(PicVideo.hWnd) + " Style " + Str(&H40000000), 0&, 0, 0)

Note that when sending big strings like this, it's often easier for you to keep track of things by building up a string of stuff to send, then just sending that string, like this:

Dim SendString as String

SendString = "open " + Chr(34) + DialogStuff.FileName + Chr(34)
SendString =SendString +" type " + FileType
SendString =SendString + " alias asciivideofile"
SendString = SendString + " Parent " + Str(PicVideo.hWnd)
SendString =SendString + " Style " + Str(&H40000000)

TempError = mciSendString(SendString, 0&, 0, 0)

You need to have a PictureBox where you want your video to appear.
Here I called it PicVideo. We've just sent the command above and opened your video file, telling it that the PictureBox PicVideo is its parent. (Sorry, I don't understand what the Style part means.)

Now you need to tell it to put the video into it. This involves telling MCI where the top-left of the video should be in the PictureBox (usually 0,0), and how wide and high the video should be stretched to (usually, how wide and high the PictureBox is):

Dim PicWidth As Integer
Dim PicHeight As Integer
PicHeight = PicVideo.ScaleHeight
PicWidth = PicVideo.ScaleWidth
TempError = mciSendString("put MyVideoFile window at 0 0 " + Str(PicWidth) + " " + Str(PicHeight), 0&, 0, 0)

Make sure the ScaleMode for the PictureBox is set to 3 - Pixel for this! (On the properties for the PictureBox in the designer.)
Otherwise you could have a massively stretched video! >_<
Or you could do this in code just before you do what's above:

PicVideo.ScaleMode = vbPixels

That's it - when you tell it to play the video, you should see it appear in the PicVideo PictureBox!
Jul 7 '07 #3

P: 3
Thank you for that great explanation of the mci.
I have done what you said and great it "works"
I have one problem, I cannot get a status or position from the MCI.
I am playing a mpegvideo file and I need to detect when the very short movie is
complete so that I can doing something else. Could you PLEASE help .

Thanking you in advance

Collin Pillay ( E-mail address removed by Moderator)
Jul 30 '07 #4

Robbie
100+
P: 180
Thank you for that great explanation of the mci.
I have done what you said and great it "works"
I have one problem, I cannot get a status or position from the MCI.
I am playing a mpegvideo file and I need to detect when the very short movie is
complete so that I can doing something else. Could you PLEASE help .

Thanking you in advance

Collin Pillay
Hi, sorry for the long delay in me replying.

I looked back over the little tutorial I typed and noticed a few errors.
To get the length of a file, it's status MySound length

Can you please show me the code which you're using to try to get the status of position? I can't think of any reason it would fail if it's able to open it, apart from me giving bad info in the tutorial.
Aug 19 '07 #5

Expert 5K+
P: 8,434
Just to let you know, Robbie, I've copied this thread to the Editor's Corner. I'd like to turn it into an Article/Tutorial for the VB Articles area.
Aug 30 '07 #6

Robbie
100+
P: 180
Just to let you know, Robbie, I've copied this thread to the Editor's Corner. I'd like to turn it into an Article/Tutorial for the VB Articles area.
Sure, that would be great!
I'd like to sort it out a bit though (as I said, I noticed a few errors), and add more info to it (ways to do things more easily, more features, what to do if things don't work...).
Aug 30 '07 #7

Post your reply

Sign in to post your reply or Sign up for a free account.