//*******************************************************************
/*
Solution: NerdkillPocket
Project: NerdkillPocket
File: RWaveOut.cs
Copyright 2003, 2004, Raphael MOLL.
This file is part of NerdkillPocket.
NerdkillPocket is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
NerdkillPocket is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with NerdkillPocket; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
//*******************************************************************
using System;
using System.Reflection;
using System.Runtime.InteropServices;
//*********************************************
namespace Alfray.Nerdkill.Platform.RPocketSound
{
//***************************************************
/// <summary>
/// RWaveOut abstracts the usage of the WaveOut interface
/// from Windows/Windows CE under C# for the Nerdkill Project.
///
/// Details can be found here:
/// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetcomp/html/WaveInOut.asp
///
/// Disclaimer:
/// Note that the MSDN article can be used as a reference (especially for the syntax
/// of DllImport) and the general idea, yet this class is NOT an exact copy of
/// the classes provided by the MSDN P/Invoke Library. There are significant differences
/// due to the fact that this class only implements the bare minimum needed by the
/// Nerdkill project. It should NOT be considered a generic implementation of WaveOut in C#.
///
/// The following APIs are mapped here:
/// - WAVEFORMATEX
/// - WAVEHDR
/// - WAVE_MAPPER
/// - CALLBACK_FUNCTION
/// - waveOutOpen
/// - waveOutGetErrorText
/// - waveOutPrepareHeader
/// - waveOutWrite
/// - waveOutUnprepareHeader
/// - waveOutReset
/// - waveOutClose
/// </summary>
//***************************************************
public abstract class RWaveOut
{
//-------------------------------------------
//----------- Public Constants --------------
//-------------------------------------------
// WAVE_MAPPER can be used in place of a device identifier when opening an audio device in order to automatically find a best fit.
public const uint WAVE_MAPPER = unchecked((uint)(-1));
// CALLBACK_WINDOW is used when opening an audio device to specify that windows messages will be the method for receiving feedback from the audio system.
public const uint CALLBACK_WINDOW = 0x10000;
// Messages sent to the window callback by WaveOut -- RM 20040523
public const int MM_WOM_OPEN = 0x3BB;
public const int MM_WOM_CLOSE = 0x3BC;
public const int MM_WOM_DONE = 0x3BD;
// flags for wFormatTag field of WAVEFORMAT -- extracted from mmsystem.h
public const uint WAVE_FORMAT_PCM = 1;
// The WF_OFFSET constants are defined to provide locations associated with WAVEFORMATEX members in a file.
// WF_OFFSET_DATA specifies the file location at which actual audio data starts.
public const int WF_OFFSET_FORMATTAG = 20;
public const int WF_OFFSET_CHANNELS = 22;
public const int WF_OFFSET_SAMPLESPERSEC = 24;
public const int WF_OFFSET_AVGBYTESPERSEC = 28;
public const int WF_OFFSET_BLOCKALIGN = 32;
public const int WF_OFFSET_BITSPERSAMPLE = 34;
public const int WF_OFFSET_DATA = 44;
// Size of a WAVEHDR structure -- RM 20040524
public static uint SizeofWAVEHDR = (uint)Marshal.SizeOf(typeof(WAVEHDR));
// Possible values for WAVEHDR.dwFlags -- RM 20040525
public const int WHDR_DONE = 0x00000001; /* done bit */
public const int WHDR_PREPARED = 0x00000002; /* set if this header has been prepared */
public const int WHDR_BEGINLOOP = 0x00000004; /* loop start block */
public const int WHDR_ENDLOOP = 0x00000008; /* loop end block */
public const int WHDR_INQUEUE = 0x00000010; /* reserved for driver */
//-------------------------------------------
//----------- Public Classes ----------------
//-------------------------------------------
[StructLayout(LayoutKind.Sequential)]
public class WAVEFORMATEX
{
public ushort wFormatTag;
public ushort nChannels;
public uint nSamplesPerSec;
public uint nAvgBytesPerSec;
public ushort nBlockAlign;
public ushort wBitsPerSample;
// public ushort cbSize; -- not used for PCM data
}
[StructLayout(LayoutKind.Sequential)]
public class WAVEHDR
{
public IntPtr lpData;
public uint dwBufferLength;
public uint dwBytesRecorded;
public uint dwUser;
public uint dwFlags;
public uint dwLoops;
public IntPtr lpNext;
public uint reserved;
}
public enum MMSYSERR : int
{
NOERROR = 0,
ERROR = (MMSYSERR_BASE + 1),
BADDEVICEID = (MMSYSERR_BASE + 2),
NOTENABLED = (MMSYSERR_BASE + 3),
ALLOCATED = (MMSYSERR_BASE + 4),
INVALHANDLE = (MMSYSERR_BASE + 5),
NODRIVER = (MMSYSERR_BASE + 6),
NOMEM = (MMSYSERR_BASE + 7),
NOTSUPPORTED = (MMSYSERR_BASE + 8),
BADERRNUM = (MMSYSERR_BASE + 9),
INVALFLAG = (MMSYSERR_BASE + 10),
INVALPARAM = (MMSYSERR_BASE + 11),
HANDLEBUSY = (MMSYSERR_BASE + 12),
INVALIDALIAS = (MMSYSERR_BASE + 13),
BADDB = (MMSYSERR_BASE + 14),
KEYNOTFOUND = (MMSYSERR_BASE + 15),
READERROR = (MMSYSERR_BASE + 16),
WRITEERROR = (MMSYSERR_BASE + 17),
DELETEERROR = (MMSYSERR_BASE + 18),
VALNOTFOUND = (MMSYSERR_BASE + 19),
NODRIVERCB = (MMSYSERR_BASE + 20),
LASTERROR = (MMSYSERR_BASE + 20),
WAVERR_BADFORMAT = (WAVERR_BASE + 0), /* unsupported wave format */
WAVERR_STILLPLAYING = (WAVERR_BASE + 1), /* still something playing */
WAVERR_UNPREPARED = (WAVERR_BASE + 2), /* header not prepared */
WAVERR_SYNC = (WAVERR_BASE + 3), /* device is synchronous */
WAVERR_LASTERROR = (WAVERR_BASE + 3), /* last error in range */
}
//-------------------------------------------
//----------- Public Methods ----------------
//-------------------------------------------
[DllImport ("coredll.dll")]
public static extern MMSYSERR waveOutOpen(ref IntPtr phwi,
uint uDeviceID, WAVEFORMATEX pwfx, IntPtr dwCallback,
uint dwInstance, uint fdwOpen);
[DllImport ("coredll.dll")]
public static extern MMSYSERR waveOutPrepareHeader(IntPtr hwo,
IntPtr /*WAVEHDR*/ pwh, uint cbwh);
[DllImport ("coredll.dll")]
public static extern MMSYSERR waveOutWrite(IntPtr hwo,
IntPtr /*WAVEHDR*/ pwh, uint cbwh);
[DllImport ("coredll.dll")]
public static extern MMSYSERR waveOutUnprepareHeader(IntPtr
hwo, IntPtr /*WAVEHDR*/ pwh, uint cbwh);
[DllImport ("coredll.dll")]
public static extern MMSYSERR waveOutClose(IntPtr hwo);
[DllImport ("coredll.dll")]
public static extern MMSYSERR waveOutReset(IntPtr hwo);
//[DllImport ("coredll.dll")]
//public static extern MMSYSERR waveOutGetErrorText(uint mmrError,
// out string pszText, uint cchText);
//-------------------------------------------
//----------- Private Methods ---------------
//-------------------------------------------
//-------------------------------------------
//----------- Private Attributes ------------
//-------------------------------------------
private const int WAVERR_BASE = 32;
private const int MMSYSERR_BASE = 0;
} // class class RWaveOut
} // namespace Alfray.Nerdkill.Platform.RPocketSound
//---------------------------------------------------------------
// [C# Template RM 20040516]
// $Log: RWaveOut.cs,v $
// Revision 1.2 2004/05/26 08:48:13 ralf
// Fixes in WaveOut mixer.
//
// Revision 1.1 2004/05/24 14:24:44 ralf
// WinCE's WaveOut sound threaded mixer.
//
//---------------------------------------------------------------