wave APIs don't send Window Messages on completion

D

Dave Hall

I'm trying to play a wav file on CE.NET 4.1. I'm able to successfully play
the first buffer full of data, by calling waveOutWrite()but I never get any
call to the overridden WndProc of my messageWindow class to let me know it's
been played so that I can play the next buffer full of data.

In the following code, hWaveOut, waveFormat and messageWindow are class
members, so they won't go out of scope while the audio is playing.

waveOutOpen(out hWaveOut, 0, waveFormat, messageWindow.Hwnd, 0,
CALLBACK_WINDOW) and
waveOutPrepareHeader(hWaveOut, wh.lpWAVEHDR, WAVEHDR.WAVEHDR_SIZE) and
waveOutWrite(hWaveOut, wh.lpWAVEHDR, WAVEHDR.WAVEHDR_SIZE)
all return MMSYSERR_NOERROR

Without going into alot of detail, I think it's important to note
wh.lpWAVEHDR is an IntPtr to unmanaged memory, and so is the lpData member
within the unmanaged WAVEHDR. I'm not sure if this is related to the
problem, but I thought I'd mention it because I couldn't even get the wave
APIs to work at all until I used this approach based on the examples at
OpenNETCF.

Although I can't directly use the OpenNETCF.Multimedia.Audio sourcecode for
this application, I'm trying to use it as an example. The OpenNETCF code
works fine, but there's something I'm missing in my version. I haven't
posted my code here because a lot of the P/Invoke stuff gets wordy, but I'll
be glad to post any of it that might help anyone show me what I'm doing
wrong. I just can't figure out any reason why the WndProc of my
messageWindow shouldn't be invoked after the first buffer of sound is
played.

Any help would be appreciated.

Dave
 
A

Alex Feinman [MVP]

I own the OpenNETCF multimedia library, so I suppose you can send your code
to me. Will be probably a day or two until I can take a look at it though
 
C

Chris Tacke, eMVP

Out of curiosity, why can't you just pull the OpenNETCF code into your
project and use it as is?
 
D

Dave Hall

Chris,
I really appreciate the work you guys are doing at OpenNETCF, and I'd
like to be able to use some of the code as is, but as a software developer,
part of my contract with my customer says that all of the source code for
their application become their exclusive propery, not just the binaries.
Since the works of OpenNETCF are not mine to offer to my customer in that
way, it's my understanding that I shouldn't include them in my application.
If I were only distributing the binaries, then I would gladly include the
applicable OpenNETCF libraries and save myself a lot of work. As it is, I
appreciate the excelent examples you provide, and hope that some day I might
return the favor and contribute to the work at OpenNETCF.

Dave
 
C

Chris Tacke, eMVP

I'm just trying to better understand the market and this is an interesting
scenario. What is their policy toward 3rd-party controls? Do they
explicitly exclude their use? They can't possibly require ownership can
they? Again, I'm trying to fully understand barriers to adoption to see if
we can help users get past them.
 
D

Dave Hall

Thanks for the offer Alex, but I think I can save you the trouble. After
three days of beating my head against various walls, I discovered that the
OpenNETCF Audio library suffers from the same malady as my own code. I
finally discovered that the problem is not in the code itself, but in the
way I was trying to test it. If I play a wave file in response to a button
click on a form, it works fine, using my code or the OpenNETCF code. The
problem all along was that I was testing my code by sticking it in the
beginning of main in an effort to test it without the overhead of all the
startup code in my application which includes some time consuming
handshaking with a second remote CE device to determine what screens are
rendered similar to the way a web server determines what's rendered in a
browser. Since I was just testing Audio features, I figured I could test it
without any UI, but that's where I was wrong. My test code looked like this:

static void Main()
{
Test.WavePlayer wp = new Test.WavePlayer();
wp.Play(@"\Program Files\Test\440hz.wav");
System.Threading.Thread.Sleep(5000);
return;
// Application.Run(mainForm);
}

It wasn't obvious to me what was happening until I discovered that the
following OpenNETCF code behaved exactly the same way as mine.

static void Main()
{
OpenNETCF.Multimedia.Audio.Player player = new
OpenNETCF.Multimedia.Audio.Player();
player.Play(new FileStream(@"\Program Files\Test\440hz.wav",
FileMode.Open, FileAccess.Read));
System.Threading.Thread.Sleep(15000);
return;
// Application.Run(new Form1());
}

The problem in both cases is that there's no message pump running at this
point in the program execution, so only the initial buffer full that's not
dependent on the message pump gets played. There's never any call to the
WndProc because there is no message pump.

When I quit cheating and moved my code so that it played a wave file in
response to a button click, or some other event that really exists within my
application, it all worked fine using either my class of the OpenNETCF Audio
library.

I'm not sure that it matters in this case, since it all appears to be
working now, but in retrospect, it seems like no more work to develop a
library that's not subject to this particular limitation. I'm not sure I see
any advantage to using CALLBACK_WINDOW instead of some of the other options.
What are your thoughts on using waveOutOpen with a CALLBACK_FUNCTION or a
CALLBACK_EVENT as the fdwFlags parameter? It seems that CALLBACK_EVENT would
be pretty easy to implement. Do you foresee any problems with using
CALLBACK_FUNCTION and having the unmanaged wave API code call back into
managed code? I haven't done callbacks like that before. It might be an
interesting variation. Any suggestions on the benefits of one way of
another?

Anyway, thanks again for all your help.
Dave
 
C

Chris Tacke, eMVP

CALLBACK_FUNCTION would be the ideal, but unfortunately the CF doesn't
support it and there's no way to get a function pointer.

--
Chris Tacke, eMVP
Co-Founder and Advisory Board Member
www.OpenNETCF.org
---
---
Principal Partner
OpenNETCF Consulting
www.OpenNETCF.com
 
A

Alex Feinman [MVP]

I see now. Yes, we do need a message pump. As for other callback scenarios,
the function is at the moment out of question since we are trying to avoid
using unmanaged code if possible. And besides to get back from an umanaged
callback to the managed code will require some sort of messaging - usually a
MessageWindow. The event will work most likely. In fact in the TAPI library
there is a similar problem except that using a Window is not an option
there. So the TAPI library is built using CALLBACK_EVENT. I'll take you
suggestion under consideration for the next release as we just have produced
SDF 1.1
Thank you for this information
 
D

Dave Hall

The project I'm working on is really the first venture into software
development for this particular customer. They've been a hardware
manufacturer for several decades, and are just now stepping into the area of
software based solutions. They don't understand the software industry or the
software development process well enough to have any policy on 3rd party
controls, or their own code for that matter. They have more of a general
feeling that they can better provide unique features to help maintain a
competitive advantage, and also that they can safeguard their product from
competitors by keeping as much as possible under their own control as they
transition from hardware-only to software dependent solutions. If I were to
explain to them that a particular feature was only available as a third
party component, they'd probably accept that fact without too much trouble,
but so far, one of the selling features that we've offered them is the fact
that their app is very portable, both in terms of code and the fact that
we've used standard hardware as much as possible. For example, using an LPT
port for an I/O interface to their proprietary hardware instead of a GPIO
register that might be proprietary to a particular vendor's CE device. In a
similar fashion, we've managed to avoid third party components in the whole
design so far ... unless you count the .NET framework itself ... :) In
short, the one big reason for not trying to get their approval for use of
the OpenNETCF library is that it's quicker in the short run to reinvent the
wheel than to rock the boat and suggest that they consider not owning some
of the code.

Thanks for your consideration,
Dave
 
D

Dave Hall

Does CALLBACK_EVENT seem do-able? It would trade the overhead of a message
pump for the overhead of a kernel event. I think the latter is less
expensive as far as run time resources, but I'm not sure. In any case, it
would work in situations where the messageWindow solution won't.

Dave
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top