Solved

how to set output device

Posted on 2001-06-15
12
689 Views
Last Modified: 2013-11-20
Dear Experts

We have to set phone line as our output device for the playback of a wave file ? we r unable to get hang on it.our tool is Visual C++
And we also donot know how to get device identifier,,

Thanx

Bye

trium
0
Comment
Question by:trium
12 Comments
 
LVL 32

Expert Comment

by:jhance
Comment Utility
This question is about as ambiguous as I've seen.

Some details about what you are doing would really help...
0
 
LVL 3

Accepted Solution

by:
JackThornton earned 100 total points
Comment Utility
You need to use the TAPI (Microsoft Telephony API). Documentation can be found in MSDN, even on-line.

Note that modems, even "voice modems", do not necessarily implement TAPI or true telephony features fully or correctly.

To get a device identifier, you need to open a line device with lineOpen - this will give you a handle to the line. The device ID's you give to lineOpen will be fairly linear indices (e.g. if you have a device with 4 lines, the indices will be 0-3).

Getting the device ID is only tricky because of an ill-considered use of VARSTRING structure. Code to fetch the ID:

unsigned
Line::GetDeviceID(HLINE hLine, LPCTSTR deviceName)
{
DevIdVarString devID;

    // initialize a VARSTRING structure
    devID.dwTotalSize = sizeof(DevIdVarString);
    devID.dwNeededSize = 0;
    devID.dwUsedSize = 0;
    devID.dwStringFormat = STRINGFORMAT_BINARY;
    devID.dwStringSize = 0;
    devID.dwStringOffset = 0;

    // get the device identifier from TAPI
    if (lineGetID(hLine, 0, 0, LINECALLSELECT_LINE, &devID, deviceName) != 0)
        throw 0;

    // return the discovered value
    _ASSERT(devID.dwStringFormat == STRINGFORMAT_BINARY);
    return *((DWORD *)(((BYTE *)&devID)+devID.dwStringOffset));

where deviceName would, for your purposes, be "wave/out".

Hope this helps.
   
   
0
 

Author Comment

by:trium
Comment Utility

Dear jack

i used the function lineGetID to get the device identifire so that
phone could be used as an output device to play the sound file.


LPCSTR deviceName="wave/out";

VARSTRING devID;

LONG retcode;
   // initialize a VARSTRING structure
   devID.dwTotalSize = sizeof(VARSTRING);
   devID.dwNeededSize = 0;
   devID.dwUsedSize = 0;
   devID.dwStringFormat = STRINGFORMAT_BINARY;
   devID.dwStringSize = 0;
   devID.dwStringOffset = 0;


lineGetID(hLine, 0, hCall, LINECALLSELECT_LINE, &devID, deviceName) ;



ASSERT(devID.dwStringFormat == STRINGFORMAT_BINARY);
   retcode= *((DWORD *)(((BYTE *)&devID)+devID.dwStringOffset));


the value i got at "retcode" is 24 which i think is the device identifire
of the opened line.then i passed this value to "waveOutOpen" function to
open the outputdevice(phone).


  LPHWAVEOUT phwo;          
  UINT uDeviceID=retcode1;            
  LPWAVEFORMATEX pwfx;
  DWORD dwCallback;      
  DWORD dwCallbackInstance;
  DWORD fdwOpen ;
     
 waveOutOpen(
            phwo,          
            uDeviceID,  
            pwfx,      
            dwCallback,          
            dwCallbackInstance,  
            fdwOpen              
            );
and then used "PlaySound" function to play the sound file.




LPCSTR pszSound ="filename.wav;
HMODULE hmod =NULL;
  DWORD fdwSound  =SND_FILENAME;
     

PlaySound(
          pszSound,  
          hmod,    
          fdwSound    
          );

but still the sound file is  played on the speaker not on the phone.
plz tell me what should i do so that phone is set as the output device
to play the sound file.

0
 
LVL 3

Expert Comment

by:JackThornton
Comment Utility
You cannot use the easy "PlaySound" to accomplish this. You need to use the waveform API directly (in this case, the waveOutXXXX calls). You will need to open a waveout device. You will then need to load the contents of the file into a RAM buffer (or, if it is a really large file, you will need to load and play the file in portions, which takes a little more code), build a WAVEHDR structure pointing to your buffer, and submit the WAVEHDR to waveOutWrite.

For more points, I will be happy to post or email you some working sample code for playing audio data using the waveOut functions (in fact, code that was used to output to phone lines using TAPI, although the output device is irrelevant).

- jack
0
 

Author Comment

by:trium
Comment Utility
Now that the points are increased, u must send me proper working code.
Its in your favour if u wanna get all marks,......!

trium
0
 
LVL 3

Expert Comment

by:JackThornton
Comment Utility
Pick up the code at:

http://www.cetasoft.com/JackThornton/code/omsrc.zip

This contains some production code of a more elaborate system than you probably need. The main file of interest is AudioDevice.cpp (the "speaker" section). It will demonstrate how to prepare a wave header for an audio buffer and submit that header (with a pointer to the buffer) to be played by the wave output API. It also demonstrates how to receive notification that the buffer has been played (or at least output to the hardware; if the audio hardware has a significant chunk of on-board RAM buffer or other latency problems then it is possible that you might get the notification before the sound has actually finished playing). You can queue up multiple buffers to be played, which makes it easy to string together different bits and pieces of audio.

Some of the code contains automatic conversion between PCM and muLaw - you can pull this code out.

Be particularly mindful of the formats the output device actually supports - you can call waveOutOpen in a way that will query for support of a particular format without actually opening the device.

You will not be able to use the classes as-is, but there is much code to study and bits and pieces you can cut and paste.

I've also included the Line source files to show how I opened the line device and got my "handle" to the waveout audio device.

Hope this helps.

- jack
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 

Author Comment

by:trium
Comment Utility
dear jack
thanx alot for your code.i've tried that but stucked at a point
which is the first parameter of WAVEHDR structure
LPSTR lpData // pointer to the waveform buffer.
plz guide me how to pass the waveform buffer.
0
 
LVL 3

Expert Comment

by:JackThornton
Comment Utility
The waveform buffer is the raw waveform data, WITHOUT the header or any other information. For example, if you load in a standard .WAV file, the waveform data will be encapsulated inside the "data" chunk. Examine the method AudioBuffer::GetWaveData in AudioBuffer.cpp to see how to pull the data out of a WAV file, if this is what you're stuck at.

Once you have a block of waveform data, simply pass a pointer to that data in lpData. Ignore the fact that the type is LPSTR, this is old Microsoft code back before they became more intelligent about designing API's (they should have used "LPVOID"; "BYTE *" would have been acceptable; using "LPSTR" is lazy and misleading, which is very bad policy for an API meant for others to use). Just use either a standard 'C' style cast or a C++ reinterpret_cast to cast the pointer to the beginning of the waveform data to LPSTR.

- jack
0
 

Author Comment

by:trium
Comment Utility
Dear jack

Thanx 4 ur guidance.i used the function GetWaveData() and tried to set the lpData parameter

here is the code

// after successfully gettin' the devise ID

//open line device;
     HWAVEOUT phwo;
     

  LPWAVEFORMATEX pwfx;
  DWORD dwCallback=0;      
  DWORD dwCallbackInstance;
  DWORD fdwOpen=CALLBACK_NULL ;  
 
//--------------------------------  

 waveOutOpen(
 &phwo,          
 uDeviceID, //got it by lineGetID function  


 pwfx,      
  dwCallback,          
 dwCallbackInstance,  
  fdwOpen              
);
 //---------------------------------------

unsigned x;
void *src ="myfile.wav";
   

    unsigned wholeChunkSize = ((DWORD *)src)[1];
     unsigned fileSize = wholeChunkSize + 8;  
     BYTE *pFormatChunk = (BYTE *)src + 8;
     ++pFormatChunk;

WAVEFORMATEX *pFormat = (WAVEFORMATEX *) (pFormatChunk + 12);
     unsigned formatSize = ((DWORD *)pFormatChunk)[2];

BYTE *pDataChunk = (BYTE *)src + 8;

++pDataChunk;

void *pData = (void *) (pDataChunk + 8);
unsigned dataSize = ((DWORD *)pDataChunk)[1];



HWAVEOUT hwo=phwo;
  WAVEHDR *pwh;
pwh->lpData=(LPSTR)pData;  
pwh->dwBufferLength=dataSize;
pwh->dwBufferLength=0;
pwh->dwFlags=0;
pwh->dwLoops=0;
pwh->dwUser=0;
pwh->lpNext=0;
pwh->reserved=0;

//-------------------------------------
  UINT cbwh;
 waveOutPrepareHeader(
  hwo,  
   pwh,
   cbwh      
);

//------------------------------
 waveOutWrite(
  hwo,  
   pwh,
   cbwh      
);

//--------------------------------------

The code is without error checking.ignore this.
kindly point out my mistakes and how can i make them correct. Don't worry about the points. if i get my problem solved, i'll give u all
of my points 'cuz i need it to be solved as soon as possible.
0
 
LVL 3

Expert Comment

by:JackThornton
Comment Utility
Could you tell me what errors you're having running this code before I take a look at it?

thanx

- jack
0
 

Author Comment

by:trium
Comment Utility
......no error....but i cannot hear my sound file being played on dialed telephone
0
 
LVL 23

Expert Comment

by:Roshan Davis
Comment Utility
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Answered by : JackThornton

Please leave any comments here within the next seven days.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Roshan Davis
EE Cleanup Volunteer
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Importing  SSL Certificate into Firefox using GPO 28 192
sumDigits challenge 9 95
scoreUp challenge 14 47
Problem to open Excel file 15 37
Introduction: Finishing the grid – keyboard support for arrow keys to manoeuvre, entering the numbers.  The PreTranslateMessage function is to be used to intercept and respond to keyboard events. Continuing from the fourth article about sudoku. …
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now