1. Win32Lib: PlaySound/setVisible solution
- Posted by "Brian K. Broker" <bkb at CNW.COM> Nov 02, 1999
- 608 views
- Last edited Nov 03, 1999
You will need to redefine xPlaySound as a function in Win32lib (if you don't have a registered version of Euphoria, you could just make up your own name and declare it in your program). This example is based off of your first example and it's not perfect (don't click the button multiple times before it's done because you will get strange results as the 'wavelist' queue "overflows". Also, on my system sometimes the first WAV won't play the very first time you click the button. I don't know why that is.) This is just meant as an example of how you might go about solving your problem. Sorry, I have no idea why setVisible behaves as it does and I don't think there's much that can be done in Win32Lib to solve it (but I'd like to be wrong). That said, here it is (you'll have to clean up the long lines and provide samples for 'one.wav', 'two.wav', and 'three.wav'): -- NOTE: you need to redefine xPlaySound in Win32lib.ew -- xPlaySound = linkFunc(winmm, "PlaySoundA", {C_POINTER, C_INT, C_INT}, C_SHORT), include Win32Lib.ew without warning constant SND_NOSTOP = #10, -- flag used in xPlaySound TheWindow = create( Window, "Sound/setVisible Problem", 0, 100, 100, 684, 388,0 ), LText2 = create( LText, "LText2", TheWindow, 132, 96, 444, 76, 0 ), Restart = create( PushButton, "RESTART", TheWindow, 248, 264, 132, 36, 0 ), DoTest = create( PushButton, "CLICK HERE", TheWindow, 248, 192, 132, 40, 0 ), LText5 = create( LText, "LText5", TheWindow, 136, 8, 408, 80, 0 ) integer wavecount -- keeps track of which sound is playing wavecount = 0 sequence wavelist -- list of sounds to play wavelist = {} --------------------------------------- -- Prepare to play a series of .WAV files: procedure playsound(sequence wave) -- convert file names to string pointers --trace(1) for i = 1 to length( wave ) do wavelist = wavelist & allocate_string( wave[i] ) end for --trace(0) -- initialize wave count and set timer wavecount = 1 setTimer( TheWindow, 1, 150 ) end procedure --------------------------------------- procedure TheWindow_onTimer( integer id ) if id = 1 then if wavecount <= length( wavelist ) then if c_func(xPlaySound, {wavelist[wavecount], NULL, or_all({SND_FILENAME, SND_ASYNC, SND_NOSTOP})}) then free( wavelist[wavecount] ) wavecount += 1 end if else wavecount = 0 wavelist = {} killTimer( TheWindow, 1 ) end if end if end procedure onTimer[TheWindow] = routine_id( "TheWindow_onTimer" ) ------------------------------------ procedure TheWindow_onOpen () -- TEST INSTRUCTIONS: setText(LText5,"Before you perform this test, name some .wav file 'test.wav' " & "and put it into the programs directory. Click the button; " & "some text SHOULD show BEFORE test.wav plays; it doesn't.") --TEXT TO SHOW WHEN BUTTON CLICKED ; MAKE IT INVISIBLE FOR NOW: setFont(LText2,"Arial", 15, Bold) setVisible(LText2, False) setText(LText2,"This text should have shown BEFORE anything was spoken!") end procedure onOpen[TheWindow] = routine_id("TheWindow_onOpen") ----------------------------------- --DO THE TEST: procedure DoTest_onClick () setVisible(LText2, True)-- TEXT should become VISIBLE; --trace(1) playsound({"one.wav","two.wav","three.wav"}) -- THEN sound should happen. --trace(0) end procedure onClick[DoTest] = routine_id("DoTest_onClick") ------------------------------------ -- RESET TO DO TEST AGAIN: procedure Restart_onClick () setVisible(LText2, False) end procedure onClick[Restart] = routine_id("Restart_onClick") ---------------------------------------------------------------------- WinMain( TheWindow, Normal )
2. Re: Win32Lib: PlaySound/setVisible solution
- Posted by Dan Moyer <DanMoyer at PRODIGY.NET> Nov 03, 1999
- 597 views
Brian, Thanks for the code! Using it & David's suggestion for making playSound a function, I have unfortunately discovered that using playSound in async mode AND setting the SND_NOSTOP flag to allow a series of wave files to be played amount to the same thing as using playSound in sync mode. I took your demo solution & simplified it, from a "play list" orientation into just a "while" test loop of the SND_NOSTOP return (see below for snippet), so I could just feed PlaySound a series of wave files & the while loop would test to see if the preceding was finished & then when it was it would play the next & so forth till it did all of them. (This would be simpler to integrate into my application.) This worked just fine as far as making a sequence of wave files play in nominally async mode, no hiccups at all that I could force; BUT: now it operates essentially like SYNC mode did, in that the program is unresponsive to other events while that SEQUENCE of sounds is playing, which throws away that wonderful interruptibility I liked so much with ASYNC mode. I think the flag SND_NOSTOP means MORE than just that the playSound function returns false if the audio device is busy playing a sound, it also means DON'T STOP PLAYING UNTIL YOU'RE FINISHED (duh!), & that's exactly what SYNC mode does, I think. That "nostop" name had been bothering me in the back of my mind, now I see why. Bottom line seems to be that there's not much point in me using ASYNC mode, if in order to make multiple files play in sequence I end up with something indistinguishable from SYNC mode. Anyway, it was interesting, & I thank you for you effort. Your comments about your demo were crystal clear & really very helpful. Hope it wasn't a total waste of time for you. Here's snippets of what I made from your demo, using David's simpler prototype suggestion for changing xPlaySound procedure to a function (thanks David, I need examples I can cut'n'paste as much as I need explanations <sigh>). Dan Moyer -- MAKE NEW PLAYSOUND TO FUNCTION AS FUNCTION: global constant zPlaySound = linkFunc( winmm, "PlaySoundA", {C_INT, C_INT, C_INT}, C_INT ) -- taken from David's prototype suggestion -- PLAY A .WAV FILE if none is currently playing, or wait until finished if one is playing -- & then play it: procedure playsound(sequence wave) atom file file = allocate_string(wave) -- just loop here while/if previous wave playing, then play the new one: -- ("false" return means something is currently playing) while c_func(zPlaySound, {file, 0, or_all({SND_FILENAME, SND_ASYNC, SND_NOSTOP}) })= False do end while free(file) end procedure --SAY SOME THINGS: procedure DoTest_onClick () playsound("1.wav") playsound("2.wav") playsound("3.wav") playsound("4.wav") end procedure
3. Re: Win32Lib: PlaySound/setVisible solution
- Posted by "Brian K. Broker" <bkb at CNW.COM> Nov 03, 1999
- 570 views
On Wed, 3 Nov 1999, Dan Moyer wrote: > I took your demo solution & simplified it, from a "play list" orientation > into just a "while" test loop of the SND_NOSTOP return (see below for > snippet), so I could just feed PlaySound a series of wave files & the while > loop would test to see if the preceding was finished & then when it was it > would play the next & so forth till it did all of them. (This would be > simpler to integrate into my application.) This is the approach I first took and found that the 'busy-waiting' produced the same result as SYNC. That's why I took the timer-based approach. You need to give the system time to think about performing the setVisible. My approach only requires an additional onTimer routine so I don't see why this method won't work for you. > Bottom line seems to be that there's not much point in me using ASYNC mode, > if in order to make multiple files play in sequence I end up with something > indistinguishable from SYNC mode. > > Anyway, it was interesting, & I thank you for you effort. Your comments > about your demo were crystal clear & really very helpful. Hope it wasn't a > total waste of time for you. A learning experience is never a waste of time... Good luck with whatever you decide to do. -- Brian
4. Re: Win32Lib: PlaySound/setVisible solution
- Posted by Dan Moyer <DanMoyer at PRODIGY.NET> Nov 03, 1999
- 553 views
- Last edited Nov 04, 1999
Brian, Oh, ok, I'll give your demo a re-look & re-think! BTW, I have tentativly concluded that the problem with setVisible is really WITH setVisible, not with playSound interacting with it, see my demo in post: Win32Lib: setVisible (true) problem ? The timer I used there, instead of giving setVisible time to finish, actually causes/allows/demos the problem. Dan On Wed, 3 Nov 1999 09:57:50 -0800, Brian K. Broker <bkb at CNW.COM> wrote: >On Wed, 3 Nov 1999, Dan Moyer wrote: > >> I took your demo solution & simplified it, from a "play list" orientation >> into just a "while" test loop of the SND_NOSTOP return (see below for >> snippet), so I could just feed PlaySound a series of wave files & the while >> loop would test to see if the preceding was finished & then when it was it >> would play the next & so forth till it did all of them. (This would be >> simpler to integrate into my application.) > >This is the approach I first took and found that the 'busy-waiting' >produced the same result as SYNC. That's why I took the timer-based >approach. You need to give the system time to think about performing the >setVisible. My approach only requires an additional onTimer routine so I >don't see why this method won't work for you. > ><snip> >-- Brian
5. Re: Win32Lib: PlaySound/setVisible solution
- Posted by Bernie Ryan <bwryan at PCOM.NET> Nov 03, 1999
- 556 views
- Last edited Nov 04, 1999
PlaySound is a high level function and is not ment to be flexible enough to accomplish the type of things you want to do. There are a number of ( 30 or 40 ) LOW Level functions in windows that give you more control over WAVE files ( search the microsoft developer site for wave ). There are also mixer functions which allow for the mixing of wave files. All of these functions will require a extensive understanding of multimedia programming. Bernie
6. Re: Win32Lib: PlaySound/setVisible solution
- Posted by Dan Moyer <DanMoyer at PRODIGY.NET> Nov 03, 1999
- 544 views
- Last edited Nov 04, 1999
Brian, Now that I actually ran your code instead of just looking at it, I find it runs REAL GOOD!! So far I haven't seen any of the problems with it you mentioned, though I haven't tried real hard yet. It even seems to be at least semi-interuptable, I think. Will test it more & see about integrating it into my app. I did change C_SHORT to C_LONG in the re- definition of playSound when euphoria said C_SHORT wasn't defined, but I really don't have any idea whether that is ok or not. (In other words, I really don't know what I'm doing.) Dan Moyer
7. Re: Win32Lib: PlaySound/setVisible solution
- Posted by Brian Broker <bkb at CNW.COM> Nov 03, 1999
- 556 views
- Last edited Nov 04, 1999
On Wed, 3 Nov 1999 20:36:06 -0500, Dan Moyer <DanMoyer at PRODIGY.NET> wrote: >I did change C_SHORT to C_LONG in the re- >definition of playSound when euphoria said C_SHORT wasn't defined, but I >really don't have any idea whether that is ok or not. (In other words, I >really don't know what I'm doing.) Well, a C_LONG is the same as a C_INT and that should work fine. Bernie mentioned that a boolean value is a C_SHORT. These constants essentially define how data is stored in a way that C understands. A Short integer is 16-bits while a Long integer is 32-bits. So defining the return value as a Long will work, it's just overkill. (Of course, only one bit is required to determine True or False so using a Short integer is also overkill.) These values should be defined in DLL.E in your INCLUDE directory (dll.e is included by win32lib.ew). What version of Euphoria are you using? Perhaps an older version of DLL.E did not define C_SHORT? Either way, as long as it works... I'm glad to hear that you might find my example useful after all! -- Brian
8. Re: Win32Lib: PlaySound/setVisible solution
- Posted by Dan Moyer <DanMoyer at PRODIGY.NET> Nov 05, 1999
- 549 views
Brian, Not only did I find your example "useful", but it is now successfully incorperated into my math flash card app, works REALLY WONDERFULY, allows the "interruptiblity" I liked so much about playSound async, & I'm about 99% finished with it!! Wow! Now all I got to do is finish the last 1% & try to clean up the commenting so it could make sense & potentially be useful to others, & I'll send it to RDS. I do still need to find out if David has a fix for the "modal windows" problem I found before I can let my niece & nephew use it, though, 'cause that can make it hang up. I'm really grateful to you not only for the code itself, but for your observation that my initial alterations of it were anything but an "improvement", which prompted me to go back & do what I should have done in the first place & run your original code sans my "improvement". My only excuse is that I didn't really understand it very well, & tried to modify it into something that I understood slightly better. Getting your timer-based "play multiple waves" to work in my app wasn't as easy as I had hoped, but that was mostly my programming ignorance hindering me, & the fact that I had timers running in it already, which I had to make work together correctly with yours. But I did it, & I'm much MUCH more pleased with it now than when I was using playSound sync mode. I wouldn't ever have thought of that approach myself. So thanks a LOT!! re C_SHORT: yeah, I do have DLL.E in my include directory (& it does define C_SHORT), & 0.42e Win32Lib is there too, and no earlier version is in the directory with my app, so I don't know why euphoria hiccupped on it, but as long as LONG works ok, it's ok by me. Thanks again! Dan Moyer On Wed, 3 Nov 1999 21:09:22 -0500, Brian Broker <bkb at CNW.COM> wrote: >On Wed, 3 Nov 1999 20:36:06 -0500, Dan Moyer <DanMoyer at PRODIGY.NET> wrote: > >>I did change C_SHORT to C_LONG in the re- >>definition of playSound when euphoria said C_SHORT wasn't defined, but I >>really don't have any idea whether that is ok or not. (In other words, I >>really don't know what I'm doing.) > >Well, a C_LONG is the same as a C_INT and that should work fine. Bernie >mentioned that a boolean value is a C_SHORT. These constants essentially >define how data is stored in a way that C understands. A Short integer is >16-bits while a Long integer is 32-bits. So defining the return value as a >Long will work, it's just overkill. (Of course, only one bit is required to >determine True or False so using a Short integer is also overkill.) > >These values should be defined in DLL.E in your INCLUDE directory (dll.e is >included by win32lib.ew). What version of Euphoria are you using? Perhaps >an older version of DLL.E did not define C_SHORT? > >Either way, as long as it works... I'm glad to hear that you might find my >example useful after all! > >-- Brian