1. Win32Lib: PlaySound/setVisible solution

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 )

new topic     » topic index » view message » categorize

2. Re: Win32Lib: PlaySound/setVisible solution

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

new topic     » goto parent     » topic index » view message » categorize

3. Re: Win32Lib: PlaySound/setVisible solution

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

new topic     » goto parent     » topic index » view message » categorize

4. Re: Win32Lib: PlaySound/setVisible solution

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

new topic     » goto parent     » topic index » view message » categorize

5. Re: Win32Lib: PlaySound/setVisible solution

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

new topic     » goto parent     » topic index » view message » categorize

6. Re: Win32Lib: PlaySound/setVisible solution

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

new topic     » goto parent     » topic index » view message » categorize

7. Re: Win32Lib: PlaySound/setVisible solution

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

new topic     » goto parent     » topic index » view message » categorize

8. Re: Win32Lib: PlaySound/setVisible solution

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

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu