OS/2, eCS & ArcaOS - Technical > Multimedia
PC Speaker output to sound card?
Greg Barrett:
The software is for the Microlab F.A.M.E. from Hamilton Robotics. We do not have the source code.
Neil Waldhauer:
There ought to be a way to intercept the DosBeep call and re route it to MMOS2. DosBeep is a Control Program API, so it's in DOSCALL, isn't it? Replacing DOSCALL1.DLL would be tricky, but should be possible.
You could also load your own DLL, and binary edit the exe to change the DosBeep to a call to your own DLL.
Martin Iturbide:
Hi Greg.
I'm sorry we don't have a solution for what you are looking for. But if it is possible for your I would like to ask you for more information about this medical device that is using OS/2.
Can you provide the me model, pictures or any information about it? I'm always curious about industrial uses of OS/2.
Regards
Lars:
As Neil has already pointed out, there is a solution (even though a bit clunky, there is no easy way) and it is contained in here (but the changes go against DOSCALLS imports and not DOSCALL1 imports):
http://www.edm2.com/common/snippets/newc2.zip
However, the DEF file contained in this zip file needs an update /to be extended, all DOSCALLS entry points are described here:
http://home.clara.net/orac/os2/doscalls.htm
You need to adapt the sample in the ZIP file, you need to override DOS16BEEP (if your app is 16-bit) or DOS32BEEP (if you app is 32-bit) instead of DOS16OPEN /DOS32OPEN.
You then need to rename the internal References to DOSCALLS in your application to NEWCALLS (instead of renaming inside PMMERGE as the sample code is asking for). You will then need to place NEWCALLS.DLL In your application's exe file directory (preferrably).
Finally you need to know how to play a sound file via MMPM.
Sample code:
--- Quote ---#define INCL_BASE
#include <os2.h>
#define INCL_OS2MM
#include <os2me.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <process.h>
typedef struct _STATEVECTOR
{
USHORT usSize;
HEV hev;
ULONG ulBufLen;
PVOID pBuffer;
} STATEVECTOR, *PSTATEVECTOR;
APIRET SetupData(PSZ pszFileName,PSTATEVECTOR pS)
{
FILESTATUS3 fs={0};
HFILE hfile=NULLHANDLE;
ULONG ulAction=0UL;
APIRET rc=NO_ERROR;
rc = DosQueryPathInfo(pszFileName,FIL_STANDARD,&fs,sizeof(fs));
if (rc == NO_ERROR) {
pS->ulBufLen = fs.cbFile;
rc = DosAllocMem((PPVOID)&pS->pBuffer,pS->ulBufLen,PAG_READ|PAG_WRITE|PAG_COMMIT|OBJ_ANY);
if (rc == NO_ERROR) {
rc = DosOpen( pszFileName,
&hfile,
&ulAction,
0UL,
FILE_NORMAL,
OPEN_ACTION_OPEN_IF_EXISTS|OPEN_ACTION_FAIL_IF_NEW,
OPEN_ACCESS_READONLY|OPEN_SHARE_DENYNONE,
NULL);
rc = DosRead(hfile,pS->pBuffer,pS->ulBufLen,&pS->ulBufLen);
rc = DosClose(hfile);
}
}
if (rc == NO_ERROR)
return 1;
else
return 0;
}
void _LNK_CONV WorkerThread(void *p)
{
#define MCI_ERROR_LENGTH 128
CHAR errorBuffer[MCI_ERROR_LENGTH]={0};
MMIOINFO mmioInfo;
MMFORMATINFO mfi={0}, *pmfi=NULL;
HMMIO hmmio;
LONG lFormats=0;
APIRET rc;
STATEVECTOR state;
PSTATEVECTOR pS=&state;
MCI_OPEN_PARMS mop;
MCI_PLAY_PARMS mpp;
MCI_GENERIC_PARMS mgp;
memcpy(&state,p,sizeof(STATEVECTOR));
rc = DosPostEventSem(pS->hev);
mfi.ulStructLen = sizeof(mfi);
mfi.ulIOProcType = MMIO_IOPROC_DATAFORMAT;
mfi.ulMediaType = MMIO_MEDIATYPE_AUDIO;
rc = mmioQueryFormatCount(&mfi,&lFormats,0UL,0UL);
pmfi = (PMMFORMATINFO)calloc(lFormats,sizeof(*pmfi));
if (!pmfi)
{
_endthread();
}
if (pS->pBuffer) {
rc = mmioGetFormats(&mfi,lFormats,pmfi,&lFormats,0UL,0UL);
/*
We HAVE TO check the FOURCC in this reverse order !
Why ? Because VORBIS/FLAC/MP3 IOProcs are lacking
a data format identification !
If we do it in this reverse order, WAV will be checked
before those, so at least WAVs are correctly identified
as WAVs BEFORE they are misidentified as MP3/VORBIS/FLAC
However it is IMPOSSIBLE to tell apart VORBIS/FLAC/MP3
for exactly the reason stated above !
*/
for (LONG i=lFormats-1;i>=0;i--)
{
/*
Seesh, AVCA IOProc traps on this simple action
skip it
*/
if (pmfi.fccIOProc == mmioFOURCC('A','V','C','A'))
{
continue;
}
memset(&mmioInfo,0,sizeof(mmioInfo));
mmioInfo.fccChildIOProc = FOURCC_MEM;
mmioInfo.pchBuffer = (PCHAR)pS->pBuffer;
mmioInfo.cchBuffer = pS->ulBufLen;
mmioInfo.ulTranslate = MMIO_TRANSLATEHEADER|MMIO_TRANSLATEDATA;
// mmioInfo.fccIOProc = pmfi.fccIOProc;
mmioInfo.fccIOProc = mmioFOURCC('M','P','3',' ');
hmmio = mmioOpen(NULL,&mmioInfo,MMIO_READ|MMIO_DENYNONE);
if (hmmio)
{
break;
}
}
if (hmmio) {
memset(&mop,0,sizeof(mop));
mop.pszElementName = (PSZ)hmmio;
mop.pszDeviceType = (PSZ)MAKEULONG(MCI_DEVTYPE_WAVEFORM_AUDIO, 0);
rc = mciSendCommand(0,MCI_OPEN,MCI_WAIT|MCI_READONLY|MCI_OPEN_MMIO|MCI_OPEN_TYPE_ID,&mop,0);
if (LOUSHORT(rc) != MCIERR_SUCCESS)
{
mciGetErrorString(rc,errorBuffer,MCI_ERROR_LENGTH);
printf("open MMIO failed:%s\n",errorBuffer);
}
memset(&mpp,0,sizeof(mpp));
rc = mciSendCommand(mop.usDeviceID,MCI_PLAY,MCI_WAIT,&mpp,0);
if (LOUSHORT(rc) != MCIERR_SUCCESS)
{
mciGetErrorString(rc,errorBuffer,MCI_ERROR_LENGTH);
printf("open MMIO failed:%s\n",errorBuffer);
}
memset(&mgp,0,sizeof(mgp));
rc = mciSendCommand(mop.usDeviceID,MCI_STOP,MCI_WAIT,&mgp,0);
if (LOUSHORT(rc) != MCIERR_SUCCESS)
{
mciGetErrorString(rc,errorBuffer,MCI_ERROR_LENGTH);
printf("open MMIO failed:%s\n",errorBuffer);
}
memset(&mgp,0,sizeof(mgp));
rc = mciSendCommand(mop.usDeviceID,MCI_CLOSE,MCI_WAIT,&mgp,0);
if (LOUSHORT(rc) != MCIERR_SUCCESS)
{
mciGetErrorString(rc,errorBuffer,MCI_ERROR_LENGTH);
printf("open MMIO failed:%s\n",errorBuffer);
}
rc = mmioClose(hmmio,0);
if (LOUSHORT(rc) != MMIO_SUCCESS)
{
mciGetErrorString(rc,errorBuffer,MCI_ERROR_LENGTH);
printf("open MMIO failed:%s\n",errorBuffer);
}
}
rc = DosFreeMem(pS->pBuffer);
}
free(pmfi);
}
int main(int argc,char *argv[])
{
APIRET rc;
TID tid=0;
STATEVECTOR state={sizeof(STATEVECTOR),0};
PSTATEVECTOR pS=&state;
if (argc != 2)
{
CHAR name[_MAX_FNAME];
_splitpath(argv[0],NULL,NULL,name,NULL);
printf("Usage: % [sound file to play]\n",name);
return 1;
}
if (SetupData(argv[1],pS))
{
rc = DosCreateEventSem(NULL,&(pS->hev),0UL,0UL);
tid = _beginthread(WorkerThread,NULL,32768UL,pS);
/*
we have to make sure we wait until the state data
is copied from this main thread's stack to the
worker thread's stack
*/
rc = DosWaitEventSem(pS->hev,SEM_INDEFINITE_WAIT);
rc = DosCloseEventSem(pS->hev);
/*
DosWaitThread is only necessary in this sample program
in a real application, the worker thread can just
continue to operate while the main thread returns
to the calling routine
*/
rc = DosWaitThread(&tid,DCWW_WAIT);
}
return 0;
}
--- End quote ---
From the code, skip the stuff you are not interested in (for example, setting up a second thread, or querying all sound formats, there is no need to query that if you know you are going to play a WAV file).
Lars:
Because the corona virus is giving me too much time, I hacked together a NEWCALLS.DLL that will generate a "beep" of given freq and duration as a WAV file and play that via MMPM and will therefore serve as a direct replacement of the "DosBeep" API function.
Find attached, including source code. It's free, whoever it may serve a purpose.
Lars
Navigation
[0] Message Index
[#] Next page
[*] Previous page
Go to full version