home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ioctlapi.zip
/
appsrc.zip
/
mixerapi.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-11-16
|
7KB
|
258 lines
//-----------------------------------------------------------------------------
// Freeware. This file may be used freely to promote the ioctl90 mixer API.
//-----------------------------------------------------------------------------
// mixerapi.c
#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 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 "data.h"
#include "parse.h"
#include "help.h"
#include "pddname.h"
#include "commands.h"
#include "ioctl90.h"
#include "mixerapi.h"
HFILE hDriver = NULL;
NPFN CallbackFunc = NULL;
HEV hevCallback = NULL;
BOOL fCallbackThreadAlive = FALSE;
HFILE DevOpen (char *ddName)
{
ULONG ulRC;
ULONG OpenFlags;
ULONG OpenMode;
ULONG ulFileSize = 0;
ULONG ulFileAttribute = 0;
ULONG ulActionTaken = 0;
HFILE hPdd = NULL;
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
printf ("DosOpen RC = %x\n", ulRC);
if (ulRC != 0)
hPdd = NULL;
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
if (ulRC != 0)
{
printf ("DosDevIOCtl ulRC = 0x%x\n", ulRC);
}
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
printf ("CallbackThreadFunc - PDD callback register failed\n", ulRC);
_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)
{
printf ("mixerapi CallbackThreadFunc - WaitEvent failed\n");
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)
{
printf ("mixerapiDeInit - DosQueryEventSem failed");
break;
}
if (ulPostCount == 0)
{
ulRC = DosPostEventSem (hevCallback);
if (ulRC != 0)
{
printf ("mixerapiDeInit - DosPostEventSem failed");
}
// 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);
if (ulRC != 0)
{
printf ("mixerapiDeInit - DosCloseEventSem failed");
}
hevCallback = NULL;
}
if (hDriver != NULL)
{
DosClose (hDriver);
hDriver = NULL;
}
}
ULONG mixerapiInit (NPFN npfnCallback)
{
ULONG ulRC;
char szPddName [14]; // "\\DEV\\12345678"
if (Options.Verbose)
printf ("\nmixerapiInit\n");
strcpy (szPddName, "\\DEV\\");
ulRC = GetAudioPDDName (&szPddName[5]);
if (ulRC != 0)
{
printf ("GetAudioPDDName returned failure (%x)\n", ulRC);
return (ulRC);
}
if (Options.Verbose)
printf (" PddName=%s\n", szPddName);
hDriver = DevOpen (szPddName);
if (hDriver == NULL)
{
printf (" DevOpen failed: %s\n", szPddName);
ulRC = 1;
}
else
{
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)
{
printf ("mixerapiInit - CreateSem failed\n");
hevCallback = NULL;
}
else
{
fCallbackThreadAlive = TRUE;
if (_beginthread (CallbackThreadFunc, NULL, 32*1024, NULL) == -1)
{
printf ("mixerapiInit - callback thread create failed\n");
CallbackFunc = NULL;
ulRC = 1;
}
}
}
return (ulRC);
}