diff --git a/utils/wxMMedia2/lib/sndbase.cpp b/utils/wxMMedia2/lib/sndbase.cpp index d5e6e8f72a..95a51c7179 100644 --- a/utils/wxMMedia2/lib/sndbase.cpp +++ b/utils/wxMMedia2/lib/sndbase.cpp @@ -43,6 +43,7 @@ wxSoundStream::wxSoundStream() { int i; + // Reset all variables to their neutral value. m_sndformat = NULL; m_handler = NULL; m_snderror = wxSOUND_NOERR; @@ -57,17 +58,33 @@ wxSoundStream::~wxSoundStream() delete m_sndformat; } -// SetSoundFormat returns TRUE when the format can be handled. +// -------------------------------------------------------------------------- +// SetSoundFormat(const wxSoundFormatBase& format) is one of the most +// important function of the wxSoundStream class. It prepares the stream to +// receive or send the data in a strict format. Normally, the sound stream +// should be ready to accept any format it is asked to manage but in certain +// cases, it really cannot: in that case it returns FALSE. To have more +// details in the functionnalities of SetSoundFormat see +// wxSoundRouterStream::SetSoundFormat() +// -------------------------------------------------------------------------- bool wxSoundStream::SetSoundFormat(const wxSoundFormatBase& format) { + // delete the previous prepared format if (m_sndformat) delete m_sndformat; + // create a new one by cloning the format passed in parameter m_sndformat = format.Clone(); return TRUE; } -// Register a callback for a specified async event. + +// -------------------------------------------------------------------------- +// Register(int evt, ...) registers the callback for a specified async event. +// Warning ! Only one callback by event is supported. It means that if you +// call twice this function the previous registered callback is absolutely +// ignored. +// -------------------------------------------------------------------------- void wxSoundStream::Register(int evt, wxSoundCallback cbk, char *cdata) { int c; @@ -86,6 +103,13 @@ void wxSoundStream::Register(int evt, wxSoundCallback cbk, char *cdata) m_cdata[c] = cdata; } +// -------------------------------------------------------------------------- +// OnSoundEvent(int evt) is called either when the driver is ready to receive +// a new block to play or when the driver has a new recorded buffer. You +// must be careful here and try not to spend a lot of time: this is a +// real-time call. In the case, an "event handler" was specified previously, +// it called him before everything. +// -------------------------------------------------------------------------- void wxSoundStream::OnSoundEvent(int evt) { int c; diff --git a/utils/wxMMedia2/lib/sndbase.h b/utils/wxMMedia2/lib/sndbase.h index 0f4fa4d8b7..cfd2ea83ae 100644 --- a/utils/wxMMedia2/lib/sndbase.h +++ b/utils/wxMMedia2/lib/sndbase.h @@ -14,12 +14,25 @@ #include +// ------------------------------------------------------------------------ +// DEFINITIONS + +// --------------------- +// Sound streaming mode: +// - wxSOUND_INPUT: simple recording mode +// - wxSOUND_OUTPUT: simple playing mode +// - wxSOUND_DUPLEX: full duplex record/play at the same time +// --------------------- enum { wxSOUND_INPUT = 1, wxSOUND_OUTPUT = 2, wxSOUND_DUPLEX = wxSOUND_INPUT | wxSOUND_OUTPUT, }; +// --------------------- +// wxSoundFormatType: it specifies the format family of the sound data +// which will be passed to the stream. +// --------------------- typedef enum { wxSOUND_NOFORMAT, wxSOUND_PCM, @@ -27,12 +40,33 @@ typedef enum { wxSOUND_G72X } wxSoundFormatType; +// --------------------- +// wxSoundError: +// - wxSOUND_NOERR: No error occured +// - wxSOUND_IOERR: an input/output error occured, it may concern either +// a driver or a file +// - wxSOUND_INVFRMT: the sound format passed to the function is invalid. +// Generally, it means that you passed out of range values +// to the codec stream or you don't pass the right sound +// format object to the right sound codec stream. +// - wxSOUND_INVDEV: Invalid device. Generally, it means that the sound stream +// didn't manage to open the device driver due to an invalid// parameter or to the fact that sound is not supported on +// this computer. +// - wxSOUND_NOEXACT: No exact matching sound codec has been found for +// this sound format. It means that the sound driver didn't +// manage to setup the sound card with the specified +// values. +// - wxSOUND_NOCODEC: No matching codec has been found. Generally, it +// may happen when you call +// wxSoundRouterStream::SetSoundFormat(). +// - wxSOUND_MEMERR: Not enough memory. +// --------------------- typedef enum { wxSOUND_NOERR, wxSOUND_IOERR, wxSOUND_INVFRMT, wxSOUND_INVDEV, - wxSOUND_NOTEXACT, + wxSOUND_NOEXACT, wxSOUND_INVSTRM, wxSOUND_NOCODEC, wxSOUND_MEMERR @@ -40,6 +74,13 @@ typedef enum { class WXDLLEXPORT wxSoundStream; +// --------------------- +// wxSoundCallback(stream, evt, cdata): C callback for sound event. +// - stream: current wxSoundStream +// - evt: the sound event which has occured, it may be wxSOUND_INPUT, +// wxSOUND_OUTPUT or wxSOUND_DUPLEX +// - cdata: User callback data +// --------------------- typedef void (*wxSoundCallback)(wxSoundStream *stream, int evt, char *cdata); @@ -52,7 +93,9 @@ class WXDLLEXPORT wxSoundFormatBase { wxSoundFormatBase(); virtual ~wxSoundFormatBase(); + // It returns a "standard" format type. virtual wxSoundFormatType GetType() const { return wxSOUND_NOFORMAT; } + // It clones the current format. virtual wxSoundFormatBase *Clone() const; virtual wxUint32 GetTimeFromBytes(wxUint32 bytes) const = 0; @@ -86,7 +129,8 @@ class wxSoundStream { // Register a callback for a specified async event. void Register(int evt, wxSoundCallback cbk, char *cdata); - // Starts the async notifier. + // Starts the async notifier. After this call, the stream begins either + // recording or playing or the two at the same time. virtual bool StartProduction(int evt) = 0; // Stops the async notifier. virtual bool StopProduction() = 0; diff --git a/utils/wxMMedia2/lib/sndesd.cpp b/utils/wxMMedia2/lib/sndesd.cpp index b31dfd1250..39713d3dd9 100644 --- a/utils/wxMMedia2/lib/sndesd.cpp +++ b/utils/wxMMedia2/lib/sndesd.cpp @@ -113,7 +113,7 @@ bool wxSoundStreamESD::SetSoundFormat(const wxSoundFormatBase& format) m_snderror = wxSOUND_NOERR; if (*pcm_format != format) { - m_snderror = wxSOUND_NOTEXACT; + m_snderror = wxSOUND_NOEXACT; return FALSE; } return TRUE; diff --git a/utils/wxMMedia2/lib/sndfile.cpp b/utils/wxMMedia2/lib/sndfile.cpp index b1be59501f..55f1c15e75 100644 --- a/utils/wxMMedia2/lib/sndfile.cpp +++ b/utils/wxMMedia2/lib/sndfile.cpp @@ -20,8 +20,10 @@ // -------------------------------------------------------------------------- // Sound codec router +// A very important class: it ensures that everybody is satisfied. +// It is supposed to create as many codec as it is necessary to transform +// a signal in a specific format in an another. // -------------------------------------------------------------------------- - wxSoundRouterStream::wxSoundRouterStream(wxSoundStream& sndio) : wxSoundStreamCodec(sndio) { @@ -34,6 +36,10 @@ wxSoundRouterStream::~wxSoundRouterStream() delete m_router; } +// -------------------------------------------------------------------------- +// Read(void *buffer, wxUint32 len): It reads data synchronously. See sndbase.h +// for possible errors and behaviours ... +// -------------------------------------------------------------------------- wxSoundStream& wxSoundRouterStream::Read(void *buffer, wxUint32 len) { if (m_router) { @@ -48,6 +54,9 @@ wxSoundStream& wxSoundRouterStream::Read(void *buffer, wxUint32 len) return *this; } +// -------------------------------------------------------------------------- +// Write(const void *buffer, wxUint32 len): It writes data synchronously +// -------------------------------------------------------------------------- wxSoundStream& wxSoundRouterStream::Write(const void *buffer, wxUint32 len) { if (m_router) { @@ -62,6 +71,13 @@ wxSoundStream& wxSoundRouterStream::Write(const void *buffer, wxUint32 len) return *this; } +// -------------------------------------------------------------------------- +// SetSoundFormat(const wxSoundFormatBase& format) first tries to setup the +// sound driver using the specified format. If this fails, it uses personnal +// codec converters: for the moment there is a PCM converter (PCM to PCM: +// with optional resampling, ...), an ULAW converter (ULAW to PCM), a G72X +// converter (G72X to PCM). If nothing works, it returns FALSE. +// -------------------------------------------------------------------------- bool wxSoundRouterStream::SetSoundFormat(const wxSoundFormatBase& format) { if (m_router) @@ -92,6 +108,11 @@ bool wxSoundRouterStream::SetSoundFormat(const wxSoundFormatBase& format) return TRUE; } +// -------------------------------------------------------------------------- +// GetBestSize() returns the specific best buffer size a sound driver +// can manage. It means that it will be easier for it to manage the buffer +// and so it will be faster and in some case more accurate for real-time event. +// -------------------------------------------------------------------------- wxUint32 wxSoundRouterStream::GetBestSize() const { if (m_router) @@ -100,6 +121,9 @@ wxUint32 wxSoundRouterStream::GetBestSize() const return m_sndio->GetBestSize(); } +// -------------------------------------------------------------------------- +// StartProduction(int evt). See sndbase.h +// -------------------------------------------------------------------------- bool wxSoundRouterStream::StartProduction(int evt) { if (!m_router) { @@ -119,6 +143,9 @@ bool wxSoundRouterStream::StartProduction(int evt) return FALSE; } +// -------------------------------------------------------------------------- +// StopProduction(). See sndbase.h +// -------------------------------------------------------------------------- bool wxSoundRouterStream::StopProduction() { if (!m_router) { @@ -209,8 +236,13 @@ bool wxSoundFileStream::Stop() m_state = wxSOUND_FILE_STOPPED; return FALSE; } + + if (m_input) + m_input->SeekI(0, wxFromStart); + + if (m_output) + m_output->SeekO(0, wxFromStart); - // TODO reset counter m_state = wxSOUND_FILE_STOPPED; return TRUE; } diff --git a/utils/wxMMedia2/lib/sndoss.cpp b/utils/wxMMedia2/lib/sndoss.cpp index 60fb82a2bd..875d19b167 100644 --- a/utils/wxMMedia2/lib/sndoss.cpp +++ b/utils/wxMMedia2/lib/sndoss.cpp @@ -131,7 +131,7 @@ bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase& format) m_snderror = wxSOUND_NOERR; if (*pcm_format != format) { - m_snderror = wxSOUND_NOTEXACT; + m_snderror = wxSOUND_NOEXACT; return FALSE; } return TRUE; @@ -235,6 +235,10 @@ bool wxSoundStreamOSS::StartProduction(int evt) StopProduction(); old_frmt = m_sndformat->Clone(); + if (!old_frmt) { + m_snderror = wxSOUND_MEMERR; + return FALSE; + } if (evt == wxSOUND_OUTPUT) m_fd = open(m_devname.mb_str(), O_WRONLY); diff --git a/utils/wxMMedia2/lib/sndwav.cpp b/utils/wxMMedia2/lib/sndwav.cpp index 618cbfcab3..d083097222 100644 --- a/utils/wxMMedia2/lib/sndwav.cpp +++ b/utils/wxMMedia2/lib/sndwav.cpp @@ -285,7 +285,7 @@ FAIL_WITH(s->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM); delete frmt; } - data << (fmt_data.GetSize() + 8 + m_sndformat->GetBytesFromTime(time)); + data << (fmt_data.GetSize() + m_sndformat->GetBytesFromTime(time)); { char *out_buf; @@ -304,6 +304,15 @@ FAIL_WITH(s->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM); bool wxSoundWave::FinishRecording() { + if (m_output->SeekO(0, wxFromStart) == wxInvalidOffset) + // We can't but there is no error. + return TRUE; + + if (m_len == 0) + return TRUE; + + + // TODO: Update headers when we stop before the specified time (if possible) return TRUE; } diff --git a/utils/wxMMedia2/lib/sndwin.cpp b/utils/wxMMedia2/lib/sndwin.cpp index 0d67b5ab89..0d070fce80 100644 --- a/utils/wxMMedia2/lib/sndwin.cpp +++ b/utils/wxMMedia2/lib/sndwin.cpp @@ -59,6 +59,11 @@ wxSoundStreamWin::wxSoundStreamWin() m_production_started = FALSE; m_internal = new wxSoundInternal; + if (!m_internal) { + m_snderror = wxSOUND_MEMERR; + m_internal = NULL; + return; + } m_snderror = wxSOUND_NOERR; // Setup defaults @@ -78,11 +83,13 @@ wxSoundStreamWin::wxSoundStreamWin() wxSoundStreamWin::~wxSoundStreamWin() { - if (m_production_started) - StopProduction(); - DestroySndWindow(); + if (m_internal) { + if (m_production_started) + StopProduction(); + DestroySndWindow(); - delete m_internal; + delete m_internal; + } } LRESULT APIENTRY _EXPORT _wxSoundHandlerWndProc(HWND hWnd, UINT message, @@ -651,6 +658,9 @@ bool wxSoundStreamWin::SetSoundFormat(wxSoundFormatBase& base) // ------------------------------------------------------------------------- bool wxSoundStreamWin::StartProduction(int evt) { + if (!m_internal) + return FALSE; + if ((m_internal->m_output_enabled && (evt & wxSOUND_OUTPUT)) || (m_internal->m_input_enabled && (evt & wxSOUND_INPUT))) CloseDevice(); @@ -679,6 +689,9 @@ bool wxSoundStreamWin::StartProduction(int evt) // ------------------------------------------------------------------------- bool wxSoundStreamWin::StopProduction() { + if (!m_production_started) + return FALSE; + m_production_started = FALSE; CloseDevice(); return TRUE;