Re: [GnomeMeeting-devel-list] Advanced support for bluetooth headsets



Julien PUYDT a �it :
Julien PUYDT a �it :
Well, oh, well. Let me share a wild idea I have in the back of my mind ever since I worked on turning drivers into plugins in ekiga (but never specifically worked on this).

Of course discussing it arouse my interest in it enough to write some basic code about it...

Here it is. If anybody wants to finish it, please proceed!

I had a look to it, and was surprised, as:
1) I didn't find a way to know for which direction a PSoundChannel has
been opened (!) ;
2) PSoundChannel is already a facade to itself! (see the role of
baseChannel in ptlib/sound.h !)

I tried to make my facade better, still.

Comments welcome!

Snark

#include "facade_soundchannel.h"

PFacadeSoundChannel::PFacadeSoundChannel ()
{
  realChannel = NULL;
  isOpen = FALSE;
}

PFacadeSoundChannel::~PFacadeSoundChannel()
{
  Close ();

  {
    PWaitAndSignal m(realChannelMutex);
    delete realChannel;
    realChannel = NULL;
  }
}

PStringArray
PFacadeSoundChannel::GetDeviceNames (PSoundChannel::Directions)
{
  PStringArray devices;

  devices += "---";

  return devices;
}

PString
PFacadeSoundChannel::GetDefaultDevice (PSoundChannel::Directions direction)
{
  PStringArray names;

  names = PFacadeSoundChannel::GetDeviceNames (direction);

  return names[0];
}

BOOL
PFacadeSoundChannel::SetChannel (PSoundChannel *channel)
{
  BOOL result = TRUE;

  PWaitAndSignal m(realChannelMutex);

  if (channel == NULL) {

    (void)realChannel->Close ();
    delete realChannel;
    realChannel = FALSE;
    return TRUE;
  }

  if (isOpen) {

    result = channel->IsOpen ();

    /* FIXME: how does one know in which direction a channel is opened!?
     * if (result)
     *   result = channel->direction == ownDirection;
     */

    if (result)
      result = channel->SetFormat (ownNumChannels,
				   ownSampleRate,
				   ownBitsPerSample);

    if (result)
      result = channel->SetBuffers (ownBufferSize, ownBufferCount);

    if (result)
      result = channel->SetVolume (ownVolume);
  }

  if (result) {

    if (realChannel != NULL) {
      realChannel->Close ();
      delete realChannel;
    }
    realChannel = channel;
  }


  return result;
}

BOOL
PFacadeSoundChannel::Open (const PString &device,
			   Directions direction,
			   unsigned numChannels,
			   unsigned sampleRate,
			   unsigned bitsPerSample)
{
  BOOL result = TRUE;
  PWaitAndSignal m(realChannelMutex);

  Close ();

  if (realChannel != NULL)
    result = realChannel->Open (device, direction, numChannels,
				sampleRate, bitsPerSample);

  if (result) { /* there was no issue: update ourselves */

    ownDirection = direction;
    ownNumChannels = numChannels;
    ownSampleRate = sampleRate;
    ownBitsPerSample = bitsPerSample;
    isOpen = TRUE;
  }

  return result;
}

BOOL
PFacadeSoundChannel::Close ()
{
  BOOL result = TRUE;
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    result = realChannel->Close ();

  if (result)
    isOpen = FALSE;

  return result;
}

BOOL
PFacadeSoundChannel::Write (const void *buf,
			    PINDEX len)
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->Write (buf, len);
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::Read (void *buf,
			   PINDEX len)
{
  PWaitAndSignal m(realChannelMutex);
  BOOL result = TRUE;

  if (realChannel != NULL) {

    result = realChannel->Read (buf, len);
    lastReadCount = realChannel->GetLastReadCount ();
  } else {

    memset ((char *) buf, 0, len);
    lastReadCount = len;
  }

  return result;
}

BOOL
PFacadeSoundChannel::SetFormat (unsigned numChannels,
				unsigned sampleRate,
				unsigned bitsPerSample)
{
  BOOL result = FALSE;
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    result = realChannel->SetFormat (numChannels, sampleRate, bitsPerSample);
  else
    result = TRUE;

  if (result) {

    ownNumChannels = numChannels;
    ownSampleRate = sampleRate;
    ownBitsPerSample = bitsPerSample;
  }

  return result;
}

unsigned
PFacadeSoundChannel::GetChannels () const
{
  return ownNumChannels;
}

unsigned
PFacadeSoundChannel::GetSampleRate () const
{
  return ownSampleRate;
}

unsigned
PFacadeSoundChannel::GetSampleSize () const
{
  return ownBitsPerSample;
}

BOOL
PFacadeSoundChannel::SetBuffers (PINDEX size,
				 PINDEX count)
{
  BOOL result = TRUE;
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    result = realChannel->SetBuffers (size, count);

  if (result) {

    ownBufferSize = size;
    ownBufferCount = count;
  }

  return result;
}

BOOL
PFacadeSoundChannel::GetBuffers (PINDEX &size,
				 PINDEX &count)
{
  size = ownBufferSize;
  count = ownBufferCount;

  return TRUE;
}

BOOL
PFacadeSoundChannel::PlaySound (const PSound &sound,
				BOOL wait)
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->PlaySound (sound, wait);
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::PlayFile (const PFilePath &filename,
			       BOOL wait)
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->PlayFile (filename, wait);
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::HasPlayCompleted ()
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->HasPlayCompleted ();
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::WaitForPlayCompletion ()
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->WaitForPlayCompletion ();
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::RecordSound (PSound &sound)
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->RecordSound (sound);
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::RecordFile (const PFilePath &filename)
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->RecordFile (filename);
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::StartRecording ()
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->StartRecording ();
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::IsRecordBufferFull ()
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->IsRecordBufferFull ();
  else
    return FALSE;
}

BOOL
PFacadeSoundChannel::AreAllRecordBuffersFull ()
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->AreAllRecordBuffersFull ();
  else
    return FALSE;
}

BOOL
PFacadeSoundChannel::WaitForRecordBufferFull ()
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->WaitForRecordBufferFull ();
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::WaitForAllRecordBuffersFull ()
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->WaitForAllRecordBuffersFull ();
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::Abort ()
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->Abort ();
  else
    return TRUE;
}

BOOL
PFacadeSoundChannel::SetVolume (unsigned value)
{
  BOOL result = TRUE;
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    result = realChannel->SetVolume (value);

  if (result)
    ownVolume = value;

  return result;
}

BOOL
PFacadeSoundChannel::GetVolume (unsigned &value)
{
  return ownVolume;
}

BOOL
PFacadeSoundChannel::IsOpen () const
{
  return isOpen;
}

int
PFacadeSoundChannel::GetHandle () const
{
  PWaitAndSignal m(realChannelMutex);

  if (realChannel != NULL)
    return realChannel->GetHandle ();
  else
    return -1;
}
#include <ptlib.h>
#include <ptlib/sound.h>

class PFacadeSoundChannel: public PSoundChannel
{
 public:
  PFacadeSoundChannel ();
  ~PFacadeSoundChannel ();

  static PStringArray GetDeviceNames (PSoundChannel::Directions);
  static PString GetDefaultDevice (PSoundChannel::Directions);

  /*
   *
   * (1) For this to work with a non-NULL channel, we want:
   * - either to be closed and the given channel too
   * - or to be both opened, in the same direction
   * We take care of putting the rest in concordance
   * (2) If the channel is NULL, we release our previous channel
   *
   * NOTICE: you shouldn't touch the given channel at all after it was given!
   * we take care of dumping it
   */
  BOOL SetChannel (PSoundChannel *channel);

  BOOL Open (const PString &device,
	     Directions direction,
	     unsigned numChannels = 1,
	     unsigned sampleRate = 8000,
	     unsigned bitsPerSample = 16);
  BOOL Close ();

  BOOL Write (const void *buf,
	      PINDEX len);
  BOOL Read (void *buf,
	     PINDEX len);

  BOOL SetFormat (unsigned numChannels,
		  unsigned sampleRate,
		  unsigned bitsPerSample);

  unsigned GetChannels () const;

  unsigned GetSampleRate () const;

  unsigned GetSampleSize () const;

  BOOL SetBuffers (PINDEX size,
		   PINDEX count);
  BOOL GetBuffers (PINDEX &size,
		   PINDEX &count);
  BOOL PlaySound (const PSound &sound,
		  BOOL wait);
  BOOL PlayFile (const PFilePath &filename,
		 BOOL wait);
  BOOL HasPlayCompleted ();
  BOOL WaitForPlayCompletion ();
  BOOL RecordSound (PSound &sound);
  BOOL RecordFile (const PFilePath &filename);
  BOOL StartRecording ();
  BOOL IsRecordBufferFull ();
  BOOL AreAllRecordBuffersFull ();
  BOOL WaitForRecordBufferFull ();
  BOOL WaitForAllRecordBuffersFull ();
  BOOL Abort ();
  BOOL SetVolume (unsigned);
  BOOL GetVolume (unsigned &);
  BOOL IsOpen () const;
  int GetHandle () const;


 private:

  BOOL isOpen;

  PMutex realChannelMutex;
  PSoundChannel *realChannel;

  PSoundChannel::Directions ownDirection;
  unsigned ownNumChannels;
  unsigned ownSampleRate;
  unsigned ownBitsPerSample;
  unsigned ownVolume;
  PINDEX ownBufferSize;
  PINDEX ownBufferCount;
};


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]