home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // 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);
- }
-