Hi, can anyone help me to add an audio or video file to a form and play it from there??
adding audio or video files to a form
Collapse
X
-
For both video and audio you can use MCI (Windows' Multimedia Control Interface).Originally posted by vdraceilHi, can anyone help me to add an audio or video file to a form and play it from there??
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:
Now...Code:Declare Function mciSendString Lib "winmm.dll" Alias _ "mciSendStringA" (ByVal lpstrCommand As String, ByVal _ lpstrReturnString As Any, ByVal uReturnLength As Long, ByVal _ hwndCallback As Long) As Long 'Also, I (Robbi-985) found this list of error codes (and 'their explanations, is the point...) 'MCI Errors Defined MCI Error Number '---------------------------------------------------------- '#define MCIERR_BASE 256 ' '#define MCIERR_INVALID_DEVICE_ID 257 '#define MCIERR_UNRECOGNIZED_KEYWORD 259 '#define MCIERR_UNRECOGNIZED_COMMAND 261 '#define MCIERR_HARDWARE 262 '#define MCIERR_INVALID_DEVICE_NAME 263 '#define MCIERR_OUT_OF_MEMORY 264 '#define MCIERR_DEVICE_OPEN 265 '#define MCIERR_CANNOT_LOAD_DRIVER 266 '#define MCIERR_MISSING_COMMAND_STRING 267 '#define MCIERR_PARAM_OVERFLOW 268 '#define MCIERR_MISSING_STRING_ARGUMENT 269 '#define MCIERR_BAD_INTEGER 270 '#define MCIERR_PARSER_INTERNAL 271 '#define MCIERR_DRIVER_INTERNAL 272 '#define MCIERR_MISSING_PARAMETER 273 '#define MCIERR_UNSUPPORTED_FUNCTION 274 '#define MCIERR_FILE_NOT_FOUND 275 '#define MCIERR_DEVICE_NOT_READY 276 '#define MCIERR_INTERNAL 277 '#define MCIERR_DRIVER 278 '#define MCIERR_CANNOT_USE_ALL 279 '#define MCIERR_MULTIPLE 280 '#define MCIERR_EXTENSION_NOT_FOUND 281 '#define MCIERR_OUTOFRANGE 282 '#define MCIERR_FLAGS_NOT_COMPATIBLE 283 '#define MCIERR_FILE_NOT_SAVED 286 '#define MCIERR_DEVICE_TYPE_REQUIRED 287 '#define MCIERR_DEVICE_LOCKED 288 '#define MCIERR_DUPLICATE_ALIAS 289 '#define MCIERR_BAD_CONSTANT 290 '#define MCIERR_MUST_USE_SHAREABLE 291 '#define MCIERR_MISSING_DEVICE_NAME 292 '#define MCIERR_BAD_TIME_FORMAT 293 '#define MCIERR_NO_CLOSING_QUOTE 294 '#define MCIERR_DUPLICATE_FLAGS 295 '#define MCIERR_INVALID_FILE 296 '#define MCIERR_NULL_PARAMETER_BLOCK 297 '#define MCIERR_UNNAMED_RESOURCE 298 '#define MCIERR_NEW_REQUIRES_ALIAS 299 '#define MCIERR_NOTIFY_ON_AUTO_OPEN 300 '#define MCIERR_NO_ELEMENT_ALLOWED 301 '#define MCIERR_NONAPPLICABLE_FUNCTION 302 '#define MCIERR_ILLEGAL_FOR_AUTO_OPEN 303 '#define MCIERR_FILENAME_REQUIRED 304 '#define MCIERR_EXTRA_CHARACTERS 305 '#define MCIERR_DEVICE_NOT_INSTALLED 306 '#define MCIERR_GET_CD 307 '#define MCIERR_SET_CD 308 '#define MCIERR_SET_DRIVE 309 '#define MCIERR_DEVICE_LENGTH 310 '#define MCIERR_DEVICE_ORD_LENGTH 311 '#define MCIERR_NO_INTEGER 312 ' '#define MCIERR_WAVE_OUTPUTSINUSE 320 '#define MCIERR_WAVE_SETOUTPUTINUSE 321 '#define MCIERR_WAVE_INPUTSINUSE 322 '#define MCIERR_WAVE_SETINPUTINUSE 323 '#define MCIERR_WAVE_OUTPUTUNSPECIFIED 324 '#define MCIERR_WAVE_INPUTUNSPECIFIED 325 '#define MCIERR_WAVE_OUTPUTSUNSUITABLE 326 '#define MCIERR_WAVE_SETOUTPUTUNSUITABLE 327 '#define MCIERR_WAVE_INPUTSUNSUITABLE 328 '#define MCIERR_WAVE_SETINPUTUNSUITABLE 329 ' '#define MCIERR_SEQ_DIV_INCOMPATIBLE 336 '#define MCIERR_SEQ_PORT_INUSE 337 '#define MCIERR_SEQ_PORT_NONEXISTENT 338 '#define MCIERR_SEQ_PORT_MAPNODEVICE 339 '#define MCIERR_SEQ_PORT_MISCERROR 340 '#define MCIERR_SEQ_TIMER 341 '#define MCIERR_SEQ_PORTUNSPECIFIED 342 '#define MCIERR_SEQ_NOMIDIPRESENT 343 ' '#define MCIERR_NO_WINDOW 346 '#define MCIERR_CREATEWINDOW 347 '#define MCIERR_FILE_READ 348 '#define MCIERR_FILE_WRITE 349 ' '#define MCIERR_CUSTOM_DRIVER_BASE 512
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)+"Ro bbi-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:\A n Audio File.wav"+chr(3 4)+" 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 MyAudioFileLeng th as Long
MyAudioFileLeng th = Val(ReturnStrin g)
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(ReturnStrin g)
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(SoundPositi on), 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. -
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=mciSe ndString("open "+VideoFile +" type mpegvideo alias MyVideoFile parent " + Str(PicVideo.hW nd) + " 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.Fil eName + Chr(34)
SendString =SendString +" type " + FileType
SendString =SendString + " alias asciivideofile"
SendString = SendString + " Parent " + Str(PicVideo.hW nd)
SendString =SendString + " Style " + Str(&H40000000)
TempError = mciSendString(S endString, 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.ScaleH eight
PicWidth = PicVideo.ScaleW idth
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.ScaleM ode = vbPixels
That's it - when you tell it to play the video, you should see it appear in the PicVideo PictureBox!Comment
-
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)Comment
-
Hi, sorry for the long delay in me replying.Originally posted by collinThank 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
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.Comment
-
Sure, that would be great!Originally posted by Killer42Just 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.
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...).Comment
Comment