home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: Multimed
/
Multimed.zip
/
lbmix04.zip
/
PipeMix
/
Source
/
mixerapi.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-03-09
|
6KB
|
224 lines
//-----------------------------------------------------------------------------
// Freeware. This file may be used freely to promote the ioctl90 mixer API.
//-----------------------------------------------------------------------------
// mixerapi.c
/* Modified by Lesha Bogdanow:
Removed fprintfs, added check for CALLBACKREG function presence,
Moved PddName[] to global vars, modified to autodetect only if not set initially
*/
#include <stdlib.h>
#include <stdio.h>
#include <process.h>
#include <signal.h>
#include <memory.h>
#include <string.h>
#include <ctype.h>
#include <io.h>
#define USE_OS2_TOOLKIT_HEADERS
#define INCL_DOSPROCESS // DosSleep
#define INCL_DOSDEVICES // DosDevIOCtl
#define INCL_DOSFILEMGR // DosDevIOCtl
#define INCL_DOSSEMAPHORES // Semaphore values
#define INCL_DOSDATETIME // Timer support
#define INCL_DOSERRORS // DOS error values
#include <os2.h>
#include "pddname.h"
#include "ioctl90.h"
#include "mixerapi.h"
HFILE hDriver = 0;
NPFN CallbackFunc = NULL;
HEV hevCallback = 0;
BOOL fCallbackThreadAlive = FALSE;
char szPddName [14]="\0"; // "\\DEV\\12345678"
HFILE DevOpen (char *ddName)
{
ULONG ulRC;
ULONG OpenFlags;
ULONG OpenMode;
ULONG ulFileSize = 0;
ULONG ulFileAttribute = 0;
ULONG ulActionTaken = 0;
HFILE hPdd = 0;
OpenFlags = OPEN_ACTION_OPEN_IF_EXISTS; // Do not create file
OpenMode = OPEN_ACCESS_READWRITE + // Read/Write file
OPEN_SHARE_DENYNONE + // Non-exclusive access
OPEN_FLAGS_FAIL_ON_ERROR; // No system popups on errors
ulRC = DosOpen (ddName, // in
&hPdd, // out (handle)
&ulActionTaken, // out
ulFileSize, // in
ulFileAttribute, // in
OpenFlags, // in
OpenMode, // in
NULL); // in
if (ulRC != 0)
hPdd = 0;
return (hPdd);
}
ULONG mixerapiIOCTL90 (USHORT usFunc, PVOID pv, ULONG ulSizeofPV)
{
ULONG ulRC;
ULONG ulSize;
ulSize = ulSizeofPV;
ulRC = DosDevIOCtl
(hDriver, // Device Handle
0x90, // Category (user defined >= 0x80)
usFunc, // Function (User defined function >= 0x40)
NULL, // in Address of parm data (not used)
0, // in Max size of parm data structure
NULL, // in out Actual size of parm data structure
pv, // in Address of command data
ulSize, // in Maximum size of command data
&ulSize); // in out Size of command data returned
return (ulRC);
}
// Function runs as independent thread
//
// Thread is used for callbacks from audio device driver.
// Audio device driver posts an event semaphore each time
// something changes. With the notification, multiple mixer
// client applications can track each others settings.
void CallbackThreadFunc (void *arglist)
{
ULONG ulRC;
ULONG ulZero = 0;
// Give semaphore handle to PDD so it can post the sem
ulRC = mixerapiIOCTL90 (CALLBACKREG, &hevCallback, sizeof(hevCallback));
if (ulRC != 0)
{
// Could get here if PDD does not implement callback support
_endthread ();
}
// Loop forever - spending most of our time blocked.
// When the PDD handles a mixer change, it will post
// the semaphore - causing this thread to wake up.
// Primary thread sets this callback address to NULL
// when it wants this thread to terminate
while (CallbackFunc)
{
ulRC = DosWaitEventSem (hevCallback, (ULONG)SEM_INDEFINITE_WAIT);
if (ulRC != 0) break;
// Call the client function (inform of mixer change)
if (CallbackFunc)
CallbackFunc();
}
// Tell PDD that we no longer want to receive callbacks.
ulRC = mixerapiIOCTL90 (CALLBACKREG, &ulZero, sizeof(ulZero));
// Inform primary thread that we are gone
fCallbackThreadAlive = FALSE;
_endthread ();
}
void mixerapiDeInit (void)
{
ULONG ulRC;
ULONG ulPostCount;
// Tell callback thread to terminate
CallbackFunc = NULL;
// While callback thread is still alive
while (fCallbackThreadAlive)
{
// Post semaphore so that callback thread gets a chance to run
// Only need to post the sem if it isn't already posted
ulRC = DosQueryEventSem (hevCallback, &ulPostCount);
if (ulRC != 0) break;
if (ulPostCount == 0)
{
ulRC = DosPostEventSem (hevCallback);
// When post the sem, must also reset it or it will post forever
ulRC = DosResetEventSem (hevCallback, &ulPostCount);
}
// Let other threads run (hevCallback will be cleared by other thread)
DosSleep (1);
}
if (hevCallback)
{
// We are done with the sem
ulRC = DosCloseEventSem (hevCallback);
hevCallback = 0;
}
if (hDriver != 0)
{
DosClose (hDriver);
hDriver = 0;
}
}
ULONG mixerapiInit (NPFN npfnCallback)
{
ULONG ulRC;
unsigned char ApiMap[256];
if (!*szPddName) {
strcpy (szPddName, "\\DEV\\");
ulRC = GetAudioPDDName (&szPddName[5]);
if (ulRC != 0) return (ulRC);
}
hDriver = DevOpen (szPddName);
if (hDriver == 0) ulRC = 1;
else
{
ulRC=mixerapiIOCTL90(GETAPIMAP,ApiMap,256);
if (ulRC) return ulRC;
if (ApiMap[CALLBACKREG])
{
ulRC = 0;
CallbackFunc = npfnCallback;
// Create shared ring-3/ring-0 event semaphore.
// Device driver posts this semaphore when other mixer applications
// make changes to the mixer. The semaphore must be created "shared".
ulRC = DosCreateEventSem (NULL, &hevCallback, DC_SEM_SHARED, FALSE);
if (ulRC != 0) hevCallback = 0;
else
{
fCallbackThreadAlive = TRUE;
if (_beginthread (CallbackThreadFunc, NULL, 32*1024, NULL) == -1)
{
CallbackFunc = NULL;
ulRC = 1;
}
}
}
}
return (ulRC);
}