adding audio or video files to a form

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • vdraceil
    New Member
    • Jul 2007
    • 236

    adding audio or video files to a form

    Hi, can anyone help me to add an audio or video file to a form and play it from there??
  • Robbie
    New Member
    • Mar 2007
    • 180

    #2
    Originally posted by vdraceil
    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:
    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
    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)+"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.

    Comment

    • Robbie
      New Member
      • Mar 2007
      • 180

      #3
      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

      • collin
        New Member
        • Jul 2007
        • 3

        #4
        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

        • Robbie
          New Member
          • Mar 2007
          • 180

          #5
          Originally posted by collin
          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.

          Comment

          • Killer42
            Recognized Expert Expert
            • Oct 2006
            • 8429

            #6
            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.

            Comment

            • Robbie
              New Member
              • Mar 2007
              • 180

              #7
              Originally posted by Killer42
              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...).

              Comment

              Working...