From 8b33ae2d5a6ed14ab4b89391b2a1cb5e9f164e90 Mon Sep 17 00:00:00 2001 From: Guilhem Lavaux Date: Sun, 27 Feb 2000 10:44:49 +0000 Subject: [PATCH] Inserted "stdio catch" in wxExecute. The activation is controlled by wxProcess. Completed some TODO in wxMMedia (wxSoundUlaw, ...) Reworked the PCM converted: it should be simpler to add converters now and it is cleaner. Implemented status information in wxVideoWindows but it doesn't work on my Win98SE (UNSUPPORTED_FUNCTION) Changed *ERR into *ERROR Added a TODO: we must detect the best format in wxSoundWindows git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6311 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/process.h | 17 +- src/common/process.cpp | 36 ++- src/msw/utilsexc.cpp | 152 +++++++++- src/unix/utilsunx.cpp | 143 ++++++++- utils/wxMMedia2/board/mmbman.cpp | 4 +- utils/wxMMedia2/board/mmboard.cpp | 4 +- utils/wxMMedia2/lib/cdbase.cpp | 2 +- utils/wxMMedia2/lib/converter.def | 16 +- utils/wxMMedia2/lib/sndaiff.cpp | 10 +- utils/wxMMedia2/lib/sndbase.cpp | 4 +- utils/wxMMedia2/lib/sndbase.h | 12 +- utils/wxMMedia2/lib/sndcpcm.cpp | 467 ++++++++++++++++++++---------- utils/wxMMedia2/lib/sndcpcm.h | 43 ++- utils/wxMMedia2/lib/sndesd.cpp | 16 +- utils/wxMMedia2/lib/sndfile.cpp | 6 +- utils/wxMMedia2/lib/sndg72x.cpp | 423 +++++++++++++-------------- utils/wxMMedia2/lib/sndoss.cpp | 85 +++--- utils/wxMMedia2/lib/sndulaw.cpp | 149 ++++++---- utils/wxMMedia2/lib/sndulaw.h | 69 ++--- utils/wxMMedia2/lib/sndwav.cpp | 2 +- utils/wxMMedia2/lib/sndwin.cpp | 1 + utils/wxMMedia2/lib/vidwin.cpp | 56 +++- utils/wxMMedia2/lib/vidwin.h | 2 + 23 files changed, 1152 insertions(+), 567 deletions(-) diff --git a/include/wx/process.h b/include/wx/process.h index b612306a66..19ae35c1f6 100644 --- a/include/wx/process.h +++ b/include/wx/process.h @@ -19,6 +19,7 @@ #include "wx/defs.h" #include "wx/object.h" #include "wx/event.h" +#include "wx/stream.h" // Process Event handling class WXDLLEXPORT wxProcessEvent : public wxEvent @@ -51,7 +52,8 @@ class WXDLLEXPORT wxProcess : public wxEvtHandler DECLARE_DYNAMIC_CLASS(wxProcess) public: - wxProcess(wxEvtHandler *parent = (wxEvtHandler *) NULL, int id = -1); + wxProcess(wxEvtHandler *parent = (wxEvtHandler *) NULL, bool needPipe = FALSE, int id = -1); + ~wxProcess(); virtual void OnTerminate(int pid, int status); @@ -59,8 +61,21 @@ public: // before the process it started terminates void Detach(); + // Pipe handling + wxInputStream *GetInputStream() const; + wxOutputStream *GetOutputStream() const; + + // These functions should not be called by the usual user. They are only + // intended to be used by wxExecute. + // Install pipes + void SetPipeStreams(wxInputStream *in_stream, wxOutputStream *out_stream); + bool NeedPipe() const; + protected: int m_id; + bool m_needPipe; + wxInputStream *m_in_stream; + wxOutputStream *m_out_stream; }; typedef void (wxObject::*wxProcessEventFunction)(wxProcessEvent&); diff --git a/src/common/process.cpp b/src/common/process.cpp index 6440993d20..e573fe8e0d 100644 --- a/src/common/process.cpp +++ b/src/common/process.cpp @@ -29,12 +29,23 @@ IMPLEMENT_DYNAMIC_CLASS(wxProcess, wxEvtHandler) IMPLEMENT_DYNAMIC_CLASS(wxProcessEvent, wxEvent) -wxProcess::wxProcess(wxEvtHandler *parent, int id) +wxProcess::wxProcess(wxEvtHandler *parent, bool needPipe, int id) { if (parent) SetNextHandler(parent); - m_id = id; + m_id = id; + m_needPipe = needPipe; + m_in_stream = NULL; + m_out_stream = NULL; +} + +wxProcess::~wxProcess() +{ + if (m_in_stream) + delete m_in_stream; + if (m_out_stream) + delete m_out_stream; } void wxProcess::OnTerminate(int pid, int status) @@ -51,3 +62,24 @@ void wxProcess::Detach() { SetNextHandler(NULL); } + +void wxProcess::SetPipeStreams(wxInputStream *in_stream, wxOutputStream *out_stream) +{ + m_in_stream = in_stream; + m_out_stream = out_stream; +} + +wxInputStream *wxProcess::GetInputStream() const +{ + return m_in_stream; +} + +wxOutputStream *wxProcess::GetOutputStream() const +{ + return m_out_stream; +} + +bool wxProcess::NeedPipe() const +{ + return m_needPipe; +} diff --git a/src/msw/utilsexc.cpp b/src/msw/utilsexc.cpp index 12a78c001a..411eaeaf44 100644 --- a/src/msw/utilsexc.cpp +++ b/src/msw/utilsexc.cpp @@ -37,6 +37,7 @@ #include "wx/log.h" #ifdef __WIN32__ + #include "wx/stream.h" #include "wx/process.h" #endif @@ -120,6 +121,94 @@ public: bool state; // set to FALSE when the process finishes }; + +#ifdef __WIN32__ +// ---------------------------------------------------------------------------- +// wxPipeStreams +// ---------------------------------------------------------------------------- + +class wxPipeInputStream: public wxInputStream { +public: + wxPipeInputStream(HANDLE hInput); + ~wxPipeInputStream(); + +protected: + size_t OnSysRead(void *buffer, size_t len); + +protected: + HANDLE m_hInput; +}; + +class wxPipeOutputStream: public wxOutputStream { +public: + wxPipeOutputStream(HANDLE hOutput); + ~wxPipeOutputStream(); + +protected: + size_t OnSysWrite(const void *buffer, size_t len); + +protected: + HANDLE m_hOutput; +}; + +// ================== +// wxPipeInputStream +// ================== + +wxPipeInputStream::wxPipeInputStream(HANDLE hInput) +{ + m_hInput = hInput; +} + +wxPipeInputStream::~wxPipeInputStream() +{ + ::CloseHandle(m_hInput); +} + +size_t wxPipeInputStream::OnSysRead(void *buffer, size_t len) +{ + DWORD bytesRead; + + m_lasterror = wxSTREAM_NOERROR; + if (! ::ReadFile(m_hInput, buffer, len, &bytesRead, NULL) ) { + if (GetLastError() == ERROR_BROKEN_PIPE) + m_lasterror = wxSTREAM_EOF; + else + m_lasterror = wxSTREAM_READ_ERROR; + } + return bytesRead; +} + +// ================== +// wxPipeOutputStream +// ================== + +wxPipeOutputStream::wxPipeOutputStream(HANDLE hOutput) +{ + m_hOutput = hOutput; +} + +wxPipeOutputStream::~wxPipeOutputStream() +{ + ::CloseHandle(m_hOutput); +} + +size_t wxPipeOutputStream::OnSysWrite(const void *buffer, size_t len) +{ + DWORD bytesRead; + + m_lasterror = wxSTREAM_NOERROR; + if (! ::WriteFile(m_hOutput, buffer, len, &bytesRead, NULL) ) { + if (GetLastError() == ERROR_BROKEN_PIPE) + m_lasterror = wxSTREAM_EOF; + else + m_lasterror = wxSTREAM_READ_ERROR; + } + return bytesRead; +} + +#endif // __WIN32__ + // ============================================================================ // implementation // ============================================================================ @@ -289,7 +378,6 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) // only reached for space not inside quotes break; } - wxString commandArgs = pc; wxWindow *winTop = wxTheApp->GetTopWindow(); @@ -313,6 +401,46 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) return result; #else // 1 + + HANDLE h_readPipe[2]; + HANDLE h_writePipe[2]; + HANDLE h_oldreadPipe; + HANDLE h_oldwritePipe; + BOOL inheritHandles; + + // ------------------------------------ + // Pipe handling + // We are in the case of opening a pipe + inheritHandles = FALSE; + if (handler && handler->NeedPipe()) { + SECURITY_ATTRIBUTES security; + + security.nLength = sizeof(security); + security.lpSecurityDescriptor = NULL; + security.bInheritHandle = TRUE; + + if (! ::CreatePipe(&h_readPipe[0], &h_readPipe[1], &security, 0) ) { + wxLogSysError(_T("Can't create the inter-process read pipe")); + + return 0; + } + + if (! ::CreatePipe(&h_writePipe[0], &h_writePipe[1], &security, 0) ) { + wxLogSysError(_T("Can't create the inter-process read pipe")); + + return 0; + } + + // We need to save the old stdio handles to restore them after the call + // to CreateProcess + h_oldreadPipe = GetStdHandle(STD_INPUT_HANDLE); + h_oldwritePipe = GetStdHandle(STD_OUTPUT_HANDLE); + + SetStdHandle(STD_INPUT_HANDLE, h_readPipe[0]); + SetStdHandle(STD_OUTPUT_HANDLE, h_writePipe[1]); + + inheritHandles = TRUE; + } // create the process STARTUPINFO si; @@ -327,7 +455,7 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) (wxChar *)command.c_str(), // full command line NULL, // security attributes: defaults for both NULL, // the process and its main thread - FALSE, // don't inherit handles + inheritHandles, // inherit handles if we need pipes CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED, // flags NULL, // environment (use the same) @@ -336,11 +464,31 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler) &pi // process info ) == 0 ) { + if (inheritHandles) { + ::CloseHandle(h_writePipe[0]); + ::CloseHandle(h_writePipe[1]); + ::CloseHandle(h_readPipe[0]); + ::CloseHandle(h_readPipe[1]); + } wxLogSysError(_("Execution of command '%s' failed"), command.c_str()); return 0; } + // Restore the old stdio handles + if (inheritHandles) { + SetStdHandle(STD_INPUT_HANDLE, h_oldreadPipe); + SetStdHandle(STD_OUTPUT_HANDLE, h_oldwritePipe); + + ::CloseHandle(h_writePipe[1]); + ::CloseHandle(h_readPipe[0]); + // We can now initialize the wxStreams + wxInputStream *processOutput = new wxPipeInputStream(h_writePipe[0]); + wxOutputStream *processInput = new wxPipeOutputStream(h_readPipe[1]); + + handler->SetPipeStreams(processOutput, processInput); + } + // register the class for the hidden window used for the notifications if ( !gs_classForHiddenWindow ) { diff --git a/src/unix/utilsunx.cpp b/src/unix/utilsunx.cpp index 3b09340bec..fe4abae50e 100644 --- a/src/unix/utilsunx.cpp +++ b/src/unix/utilsunx.cpp @@ -25,6 +25,8 @@ #include "wx/process.h" #include "wx/thread.h" +#include "wx/stream.h" + #if wxUSE_GUI #include "wx/unix/execute.h" #endif @@ -274,6 +276,83 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data) #define WXUNUSED_UNLESS_GUI(p) #endif +// New wxStream classes to clean up the data when the process terminates + +#if wxUSE_GUI +class wxProcessFileInputStream: public wxInputStream { + public: + wxProcessFileInputStream(int fd); + ~wxProcessFileInputStream(); + + protected: + size_t OnSysRead(void *buffer, size_t bufsize); + + protected: + int m_fd; +}; + +class wxProcessFileOutputStream: public wxOutputStream { + public: + wxProcessFileOutputStream(int fd); + ~wxProcessFileOutputStream(); + + protected: + size_t OnSysWrite(const void *buffer, size_t bufsize); + + protected: + int m_fd; +}; + +wxProcessFileInputStream::wxProcessFileInputStream(int fd) +{ + m_fd = fd; +} + +wxProcessFileInputStream::~wxProcessFileInputStream() +{ + close(m_fd); +} + +size_t wxProcessFileInputStream::OnSysRead(void *buffer, size_t bufsize) +{ + int ret; + + ret = read(m_fd, buffer, bufsize); + m_lasterror = wxSTREAM_NOERROR; + if (ret == 0) + m_lasterror = wxSTREAM_EOF; + if (ret == -1) { + m_lasterror = wxSTREAM_READ_ERROR; + ret = 0; + } + return ret; +} + +wxProcessFileOutputStream::wxProcessFileOutputStream(int fd) +{ + m_fd = fd; +} + +wxProcessFileOutputStream::~wxProcessFileOutputStream() +{ + close(m_fd); +} + +size_t wxProcessFileOutputStream::OnSysWrite(const void *buffer, size_t bufsize) +{ + int ret; + + ret = write(m_fd, buffer, bufsize); + m_lasterror = wxSTREAM_NOERROR; + if (ret == -1) { + m_lasterror = wxSTREAM_WRITE_ERROR; + ret = 0; + } + return ret; +} + +#endif + long wxExecute(wxChar **argv, bool sync, wxProcess * WXUNUSED_UNLESS_GUI(process)) @@ -316,6 +395,26 @@ long wxExecute(wxChar **argv, } #endif // wxUSE_GUI +#if wxUSE_GUI + int in_pipe[2] = { -1, -1 }; + int out_pipe[2] = { -1, -1 }; + // Only asynchronous mode is interresting + if (!sync && process && process->NeedPipe()) + { + if (pipe(in_pipe) == -1 || pipe(out_pipe) == -1) + { + /* Free fds */ + close(end_proc_detect[0]); + close(end_proc_detect[1]); + wxLogSysError( _("Pipe creation failed (Console pipes)") ); + + ARGS_CLEANUP; + + return 0; + } + } +#endif // wxUSE_GUI + // fork the process #ifdef HAVE_VFORK pid_t pid = vfork(); @@ -324,6 +423,14 @@ long wxExecute(wxChar **argv, #endif if (pid == -1) { +#if wxUSE_GUI + close(end_proc_detect[0]); + close(end_proc_detect[1]); + close(in_pipe[0]); + close(in_pipe[1]); + close(out_pipe[0]); + close(out_pipe[1]); +#endif wxLogSysError( _("Fork failed") ); ARGS_CLEANUP; @@ -347,7 +454,7 @@ long wxExecute(wxChar **argv, for ( int fd = 0; fd < FD_SETSIZE; fd++ ) { #if wxUSE_GUI - if ( fd == end_proc_detect[1] ) + if ( fd == end_proc_detect[1] || fd == in_pipe[0] || fd == out_pipe[1] ) continue; #endif // wxUSE_GUI @@ -356,6 +463,16 @@ long wxExecute(wxChar **argv, } } + // Fake a console by duplicating pipes +#if wxUSE_GUI + if (in_pipe[0] != -1) { + dup2(in_pipe[0], STDIN_FILENO); + dup2(out_pipe[1], STDOUT_FILENO); + close(in_pipe[0]); + close(out_pipe[1]); + } +#endif // wxUSE_GUI + #if 0 close(STDERR_FILENO); @@ -386,8 +503,8 @@ long wxExecute(wxChar **argv, data->process = NULL; // sync execution: indicate it by negating the pid - data->pid = -pid; - data->tag = wxAddProcessCallback(data, end_proc_detect[0]); + data->pid = -pid; + data->tag = wxAddProcessCallback(data, end_proc_detect[0]); // we're in parent close(end_proc_detect[1]); // close writing side @@ -403,12 +520,26 @@ long wxExecute(wxChar **argv, } else { + // pipe initialization: construction of the wxStreams + if (process && process->NeedPipe()) { + // These two streams are relative to this process. + wxOutputStream *my_output_stream; + wxInputStream *my_input_stream; + + my_output_stream = new wxProcessFileOutputStream(in_pipe[1]); + my_input_stream = new wxProcessFileInputStream(out_pipe[0]); + close(in_pipe[0]); // close reading side + close(out_pipe[1]); // close writing side + + process->SetPipeStreams(my_input_stream, my_output_stream); + } + // async execution, nothing special to do - caller will be // notified about the process termination if process != NULL, data // will be deleted in GTK_EndProcessDetector - data->process = process; - data->pid = pid; - data->tag = wxAddProcessCallback(data, end_proc_detect[0]); + data->process = process; + data->pid = pid; + data->tag = wxAddProcessCallback(data, end_proc_detect[0]); // we're in parent close(end_proc_detect[1]); // close writing side diff --git a/utils/wxMMedia2/board/mmbman.cpp b/utils/wxMMedia2/board/mmbman.cpp index 7f875c2b8f..d147894530 100644 --- a/utils/wxMMedia2/board/mmbman.cpp +++ b/utils/wxMMedia2/board/mmbman.cpp @@ -298,7 +298,9 @@ wxString MMBoardSoundFile::GetStringInformation() case wxSOUND_PCM: { wxSoundFormatPcm *pcm_format = (wxSoundFormatPcm *)format; - info += wxT("PCM\n"); + info += wxString::Format(wxT("PCM %s %s\n"), + pcm_format->Signed() ? wxT("signed") : wxT("unsigned"), + pcm_format->GetOrder() == wxLITTLE_ENDIAN ? wxT("little endian") : wxT("big endian")); info += wxString::Format(wxT("Sampling rate: %d\n") wxT("Bits per sample: %d\n") wxT("Number of channels: %d\n"), diff --git a/utils/wxMMedia2/board/mmboard.cpp b/utils/wxMMedia2/board/mmboard.cpp index 483b7cf6b8..f20d3ea6d9 100644 --- a/utils/wxMMedia2/board/mmboard.cpp +++ b/utils/wxMMedia2/board/mmboard.cpp @@ -202,7 +202,7 @@ wxUint8 MMBoardApp::TestMultimediaCaps() // We now test the ESD support dev = new wxSoundStreamESD(); - if (dev->GetError() == wxSOUND_NOERR) + if (dev->GetError() == wxSOUND_NOERROR) caps |= MM_SOUND_ESD; delete dev; @@ -210,7 +210,7 @@ wxUint8 MMBoardApp::TestMultimediaCaps() // WARNING: There is a conflict between ESD and ALSA dev = new wxSoundStreamOSS(); - if (dev->GetError() == wxSOUND_NOERR) + if (dev->GetError() == wxSOUND_NOERROR) caps |= MM_SOUND_OSS; delete dev; #endif diff --git a/utils/wxMMedia2/lib/cdbase.cpp b/utils/wxMMedia2/lib/cdbase.cpp index 0bbda32bd7..7dc801c6b4 100644 --- a/utils/wxMMedia2/lib/cdbase.cpp +++ b/utils/wxMMedia2/lib/cdbase.cpp @@ -1,5 +1,5 @@ // --------------------------------------------------------------------------- -// Name: sndsnd.cpp +// Name: cdbase.cpp // Purpose: wxMMedia // Author: Guilhem Lavaux // Created: 1997 diff --git a/utils/wxMMedia2/lib/converter.def b/utils/wxMMedia2/lib/converter.def index 31f58bd502..a558b234bc 100644 --- a/utils/wxMMedia2/lib/converter.def +++ b/utils/wxMMedia2/lib/converter.def @@ -1,7 +1,5 @@ -#include - #define DEFINE_CONV(name, input_type, output_type, convert) \ -static void Convert_##name##(const char *buf_in, char *buf_out, wxUint32 len) \ +static void Convert_##name##(const void *buf_in, void *buf_out, wxUint32 len) \ {\ register input_type src; \ register const input_type *t_buf_in = (input_type *)buf_in; \ @@ -14,6 +12,8 @@ static void Convert_##name##(const char *buf_in, char *buf_out, wxUint32 len) \ } \ } +// TODO: define converters for all other formats (32, 24) + DEFINE_CONV(8_8_sign, wxUint8, wxUint8, (src ^ 0x80)) DEFINE_CONV(8_16, wxUint8, wxUint16, (((wxUint16)src) << 8)) @@ -26,8 +26,14 @@ DEFINE_CONV(16_8_sign, wxUint16, wxUint8, (wxUint8)((src >> 8) ^ 0x80)) DEFINE_CONV(16_swap_8, wxUint16, wxUint8, (wxUint8)(src & 0xff)) DEFINE_CONV(16_swap_8_sign, wxUint16, wxUint8, (wxUint8)((src & 0xff) ^ 0x80)) +//DEFINE_CONV(24_8, wxUint32, wxUint8, (wxUint8)(src >> 16)) +//DEFINE_CONV(24_8_sig, wxUint32, wxUint8, (wxUint8)((src >> 16) ^ 0x80)) + +//DEFINE_CONV(32_8, wxUint32, wxUint8, (wxUint8)(src >> 24)) + DEFINE_CONV(16_sign, wxUint16, wxUint16, (src ^ 0x8000)) DEFINE_CONV(16_swap, wxUint16, wxUint16, (((src & 0xff) << 8) | ((src >> 8) & 0xff))) -DEFINE_CONV(16_swap_16_sign, wxUint16, wxUint16, ((((src & 0xff) << 8) | ((src >> 8) & 0xff)) ^ 0x8000)) -DEFINE_CONV(16_sign_16_swap, wxUint16, wxUint16, ((((src & 0xff) << 8) | ((src >> 8) & 0xff)) ^ 0x80)) +// Problem. +DEFINE_CONV(16_swap_16_sign, wxUint16, wxUint16, ((((src & 0xff) << 8) | ((src >> 8) & 0xff)) ^ 0x80)) +// DEFINE_CONV(16_sign_16_swap, wxUint16, wxUint16, ((((src & 0xff) << 8) | ((src >> 8) & 0xff)) ^ 0x8000)) DEFINE_CONV(16_swap_16_sign_swap, wxUint16, wxUint16, (src ^ 0x80)) diff --git a/utils/wxMMedia2/lib/sndaiff.cpp b/utils/wxMMedia2/lib/sndaiff.cpp index 7c6bfb4018..e661d082ff 100644 --- a/utils/wxMMedia2/lib/sndaiff.cpp +++ b/utils/wxMMedia2/lib/sndaiff.cpp @@ -99,6 +99,7 @@ bool wxSoundAiff::PrepareToPlay() m_snderror = wxSOUND_INVSTRM; return FALSE; } + m_snderror = wxSOUND_NOERROR; data.BigEndianOrdered(TRUE); @@ -129,9 +130,11 @@ bool wxSoundAiff::PrepareToPlay() wxUint32 num_samples; double srate; wxSoundFormatPcm sndformat; - + + // Get sound data informations data >> channels >> num_samples >> bps >> srate; - + + // Convert them in a wxSoundFormat object sndformat.SetSampleRate((wxUint32) srate); sndformat.SetBPS(bps); sndformat.SetChannels(channels); @@ -140,6 +143,7 @@ bool wxSoundAiff::PrepareToPlay() if (!SetSoundFormat(sndformat)) return FALSE; + // We pass all data left m_input->SeekI(len-18, wxFromCurrent); break; } @@ -149,6 +153,7 @@ bool wxSoundAiff::PrepareToPlay() // m_input->SeekI(len-4, wxFromCurrent); // Pass the rest m_input->SeekI(ssnd + 4, wxFromCurrent); m_base_offset = m_input->TellI(); + // len-8 bytes of samples FinishPreparation(len - 8); end_headers = TRUE; break; @@ -175,6 +180,7 @@ bool wxSoundAiff::FinishRecording() bool wxSoundAiff::RepositionStream(wxUint32 position) { + // If the stream is not seekable "TellI() returns wxInvalidOffset" we cannot reposition stream if (m_base_offset == wxInvalidOffset) return FALSE; m_input->SeekI(m_base_offset, wxFromStart); diff --git a/utils/wxMMedia2/lib/sndbase.cpp b/utils/wxMMedia2/lib/sndbase.cpp index be6d6d59c7..0a873500a9 100644 --- a/utils/wxMMedia2/lib/sndbase.cpp +++ b/utils/wxMMedia2/lib/sndbase.cpp @@ -46,7 +46,7 @@ wxSoundStream::wxSoundStream() // Reset all variables to their neutral value. m_sndformat = NULL; m_handler = NULL; - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; m_lastcount = 0; for (i=0;i<2;i++) m_callback[i] = NULL; @@ -85,7 +85,7 @@ bool wxSoundStream::SetSoundFormat(const wxSoundFormatBase& format) // call twice this function the previous registered callback is absolutely // ignored. // -------------------------------------------------------------------------- -void wxSoundStream::Register(int evt, wxSoundCallback cbk, char *cdata) +void wxSoundStream::SetCallback(int evt, wxSoundCallback cbk, void *cdata) { int c; diff --git a/utils/wxMMedia2/lib/sndbase.h b/utils/wxMMedia2/lib/sndbase.h index b2436548ef..1a828ae3fc 100644 --- a/utils/wxMMedia2/lib/sndbase.h +++ b/utils/wxMMedia2/lib/sndbase.h @@ -63,14 +63,14 @@ typedef enum { // - wxSOUND_MEMERR: Not enough memory. // --------------------- typedef enum { - wxSOUND_NOERR, - wxSOUND_IOERR, + wxSOUND_NOERROR, + wxSOUND_IOERROR, wxSOUND_INVFRMT, wxSOUND_INVDEV, wxSOUND_NOEXACT, wxSOUND_INVSTRM, wxSOUND_NOCODEC, - wxSOUND_MEMERR + wxSOUND_MEMERROR } wxSoundError; class WXDLLEXPORT wxSoundStream; @@ -83,7 +83,7 @@ class WXDLLEXPORT wxSoundStream; // - cdata: User callback data // --------------------- typedef void (*wxSoundCallback)(wxSoundStream *stream, int evt, - char *cdata); + void *cdata); // // Base class for sound format specification @@ -128,7 +128,7 @@ class wxSoundStream { wxSoundFormatBase& GetSoundFormat() const { return *m_sndformat; } // Register a callback for a specified async event. - void Register(int evt, wxSoundCallback cbk, char *cdata); + void SetCallback(int evt, wxSoundCallback cbk, void *cdata); // Starts the async notifier. After this call, the stream begins either // recording or playing or the two at the same time. @@ -158,7 +158,7 @@ class wxSoundStream { wxSoundStream *m_handler; wxSoundCallback m_callback[2]; - char *m_cdata[2]; + void *m_cdata[2]; protected: // Handles event diff --git a/utils/wxMMedia2/lib/sndcpcm.cpp b/utils/wxMMedia2/lib/sndcpcm.cpp index c81fc890db..0190874bf2 100644 --- a/utils/wxMMedia2/lib/sndcpcm.cpp +++ b/utils/wxMMedia2/lib/sndcpcm.cpp @@ -8,70 +8,124 @@ #ifdef __GNUG__ #pragma implementation "sndcpcm.cpp" #endif - #include + +#ifndef WX_PRECOMP +#include +#include +#endif + #include "sndbase.h" #include "sndpcm.h" #include "sndcpcm.h" wxSoundStreamPcm::wxSoundStreamPcm(wxSoundStream& sndio) - : wxSoundStreamCodec(sndio) + : wxSoundStreamCodec(sndio) { - m_function_in = NULL; - m_function_out = NULL; + m_function_in = NULL; + m_function_out = NULL; + m_prebuffer = NULL; + m_prebuffer_size = 0; + m_best_size = 0; } wxSoundStreamPcm::~wxSoundStreamPcm() { + if (m_prebuffer) + delete[] m_prebuffer; } +wxUint32 wxSoundStreamPcm::GetBestSize() const +{ + return m_best_size; +} #include "converter.def" // ----------------------------------------------------------------------- // Main PCM stream converter table // ----------------------------------------------------------------------- -wxSoundStreamPcm::ConverterType s_converters[] = { - NULL, - Convert_8_8_sign, /* 8 -> 8 sign */ - NULL, - NULL, - NULL, - NULL, - - Convert_8_16, /* 8 -> 16 */ - Convert_8_16_sign, /* 8 -> 16 sign */ - Convert_8_16_swap, /* 8 -> 16 swapped */ - Convert_8_16_sign_swap, /* 8 -> 16 sign swapped */ - NULL, - NULL, - - Convert_16_8, /* 16 -> 8 */ - Convert_16_8_sign, /* 16 -> 8 sign */ - Convert_16_swap_8, /* 16 swapped -> 8 */ - Convert_16_swap_8_sign, /* 16 swapped -> 8 sign */ - NULL, - NULL, - - NULL, /* 16 -> 16 */ - Convert_16_sign, /* 16 -> 16 sign */ - Convert_16_swap, /* 16 swapped -> 16 */ - Convert_16_swap_16_sign, /* 16 swapped -> 16 sign */ - Convert_16_sign_16_swap, /* 16 sign -> 16 swapped */ - Convert_16_swap_16_sign_swap /* 16 swapped -> 16 sign swapped */ +// Definition +// XX -> YY +// XX -> YY sign +// +// XX swapped -> YY +// XX swapped -> YY sign +// +// XX swapped -> YY swapped +// XX swapped -> YY swapped sign +// +// XX stereo -> YY mono +// XX stereo -> YY mono sign +// +// XX swapped stereo -> YY swapped mono +// XX swapped stereo -> YY swapped mono sign +// +// XX swapped stereo -> YY swapped mono +// XX swapped stereo -> YY swapped mono sign + +static wxSoundStreamPcm::ConverterType s_converters[4][3][2] = { + { + { + NULL, + Convert_8_8_sign /* 8 -> 8 sign */ + }, + { + NULL, + NULL + }, + { + NULL, + NULL + } + }, + { + { + Convert_8_16, /* 8 -> 16 */ + Convert_8_16_sign /* 8 -> 16 sign */ + }, + { + Convert_8_16_swap, /* 8 -> 16 swapped */ + Convert_8_16_sign_swap /* 8 -> 16 sign swapped */ + }, + { + NULL, + NULL + } + }, + { + { + Convert_16_8, /* 16 -> 8 */ + Convert_16_8_sign /* 16 -> 8 sign */ + }, + { + Convert_16_swap_8, /* 16 swapped -> 8 */ + Convert_16_swap_8_sign /* 16 swapped -> 8 sign */ + }, + { + NULL, + NULL + }, + }, + + { + { + NULL, /* 16 -> 16 */ + Convert_16_sign /* 16 -> 16 sign */ + }, + { + Convert_16_swap, /* 16 swapped -> 16 */ + Convert_16_swap_16_sign /* 16 swapped -> 16 sign */ + }, + { + NULL, + Convert_16_swap_16_sign_swap /* 16 swapped -> 16 sign swapped */ + } + } }; -#define CONVERT_BPS 0 -#define CONVERT_SIGN 1 -#define CONVERT_SWAP 2 -#define CONVERT_SIGN_SWAP 3 -#define CONVERT_SWAP_SIGN 4 -#define CONVERT_SWAP_SIGN_SWAP 5 - -#define CONVERT_BASE_8_8 0 -#define CONVERT_BASE_8_16 6 -#define CONVERT_BASE_16_8 12 -#define CONVERT_BASE_16_16 18 +// This is the buffer size multiplier. It gives the needed size of the output size. +static float s_converters_multip[] = {1, 2, 0.5, 1}; // // TODO: Read() and Write() aren't really safe. If you give it a buffer which @@ -80,107 +134,163 @@ wxSoundStreamPcm::ConverterType s_converters[] = { wxSoundStream& wxSoundStreamPcm::Read(void *buffer, wxUint32 len) { - wxUint32 real_len; - char *tmp_buf; - - if (!m_function_in) { - m_sndio->Read(buffer, len); - m_lastcount = m_sndio->GetLastAccess(); - m_snderror = m_sndio->GetError(); - return *this; - } - - real_len = (m_16_to_8) ? len / 2 : len; - - tmp_buf = new char[real_len]; + wxUint32 in_bufsize; + + // We must have a multiple of 2 + len &= 0x01; + + if (!m_function_in) { + m_sndio->Read(buffer, len); + m_lastcount = m_sndio->GetLastAccess(); + m_snderror = m_sndio->GetError(); + return *this; + } - m_sndio->Read(tmp_buf, real_len); - m_lastcount = m_sndio->GetLastAccess(); - m_snderror = m_sndio->GetError(); - if (m_snderror != wxSOUND_NOERR) + in_bufsize = GetReadSize(len); + + if (len <= m_best_size) { + m_sndio->Read(m_prebuffer, in_bufsize); + m_snderror = m_sndio->GetError(); + if (m_snderror != wxSOUND_NOERROR) { + m_lastcount = 0; + return *this; + } + + m_function_in(m_prebuffer, buffer, m_sndio->GetLastAccess()); + } else { + char *temp_buffer; + + temp_buffer = new char[in_bufsize]; + m_sndio->Read(temp_buffer, in_bufsize); + + m_snderror = m_sndio->GetError(); + if (m_snderror != wxSOUND_NOERROR) { + m_lastcount = 0; + return *this; + } + + m_function_in(temp_buffer, buffer, m_sndio->GetLastAccess()); + + delete[] temp_buffer; + } + + m_lastcount = (wxUint32)(m_sndio->GetLastAccess() * m_multiplier_in); + return *this; - - m_function_in(tmp_buf, (char *)buffer, m_lastcount); - - delete[] tmp_buf; - - if (m_16_to_8) - m_lastcount *= 2; - - return *this; } wxSoundStream& wxSoundStreamPcm::Write(const void *buffer, wxUint32 len) { - char *tmp_buf; - wxUint32 len2; + wxUint32 out_bufsize; + + if (!m_function_out) { + m_sndio->Write(buffer, len); + m_lastcount = m_sndio->GetLastAccess(); + m_snderror = m_sndio->GetError(); + return *this; + } - if (!m_function_out) - return m_sndio->Write(buffer, len); + out_bufsize = GetWriteSize(len); - len2 = (m_16_to_8) ? len / 2 : len; + if (len <= m_best_size) { + out_bufsize = GetWriteSize(len); - tmp_buf = new char[len2]; - m_function_out((const char *)buffer, tmp_buf, len2); - m_sndio->Write(tmp_buf, len); - delete[] tmp_buf; + m_function_out(buffer, m_prebuffer, len); + m_sndio->Write(m_prebuffer, out_bufsize); + m_snderror = m_sndio->GetError(); + if (m_snderror != wxSOUND_NOERROR) { + m_lastcount = 0; + return *this; + } + } else { + char *temp_buffer; + + temp_buffer = new char[out_bufsize]; + m_function_out(buffer, temp_buffer, len); + + m_sndio->Write(temp_buffer, out_bufsize); + m_snderror = m_sndio->GetError(); + if (m_snderror != wxSOUND_NOERROR) { + m_lastcount = 0; + return *this; + } + + delete[] temp_buffer; + } - m_lastcount = (m_16_to_8) ? - (m_sndio->GetLastAccess() * 2) : m_sndio->GetLastAccess(); + m_lastcount = (wxUint32)(m_sndio->GetLastAccess() / m_multiplier_out); - return *this; + return *this; } bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase& format) { - wxSoundFormatBase *new_format; - wxSoundFormatPcm *pcm_format, *pcm_format2; - ConverterType *current_table_out, *current_table_in; - int index; - bool change_sign; - - if (m_sndio->SetSoundFormat(format)) { - m_function_out = NULL; - m_function_in = NULL; - return TRUE; - } - if (format.GetType() != wxSOUND_PCM) { - m_snderror = wxSOUND_INVFRMT; - return FALSE; - } - if (m_sndformat) - delete m_sndformat; - - new_format = m_sndio->GetSoundFormat().Clone(); - pcm_format = (wxSoundFormatPcm *)&format; - pcm_format2 = (wxSoundFormatPcm *)new_format; - - // ---------------------------------------------------- - // Select table to use: - // * 8 bits -> 8 bits - // * 16 bits -> 8 bits - // * 8 bits -> 16 bits - // * 16 bits -> 16 bits - - m_16_to_8 = FALSE; - if (pcm_format->GetBPS() != pcm_format2->GetBPS()) { - m_16_to_8 = TRUE; - if (pcm_format2->GetBPS() == 8) { - current_table_out = &s_converters[CONVERT_BASE_16_8]; - current_table_in = &s_converters[CONVERT_BASE_8_16]; - } else { - current_table_out = &s_converters[CONVERT_BASE_8_16]; - current_table_in = &s_converters[CONVERT_BASE_16_8]; + wxSoundFormatBase *new_format; + wxSoundFormatPcm *pcm_format, *pcm_format2; + + if (m_sndio->SetSoundFormat(format)) { + m_function_out = NULL; + m_function_in = NULL; + return TRUE; } - } else if (pcm_format->GetBPS() == 16) { - current_table_out = &s_converters[CONVERT_BASE_16_16]; - current_table_in = &s_converters[CONVERT_BASE_16_16]; - } else { - current_table_out = &s_converters[CONVERT_BASE_8_8]; - current_table_in = &s_converters[CONVERT_BASE_8_8]; - } - - change_sign = (pcm_format2->Signed() != pcm_format->Signed()); + if (format.GetType() != wxSOUND_PCM) { + m_snderror = wxSOUND_INVFRMT; + return FALSE; + } + if (m_sndformat) + delete m_sndformat; + + new_format = m_sndio->GetSoundFormat().Clone(); + pcm_format = (wxSoundFormatPcm *)&format; + pcm_format2 = (wxSoundFormatPcm *)new_format; + +#if 0 + // ---------------------------------------------------- + // Test whether we need to resample + if (pcm_format->GetSampleRate() != pcm_format2->GetSampleRate()) { + wxUint32 src_rate, dst_rate; + + src_rate = pcm_format->GetSampleRate(); + dst_rate = pcm_format2->GetSampleRate(); + m_needResampling = TRUE; + if (src_rate < dst_rate) + m_expandSamples = TRUE; + else + m_expandSamples = FALSE; + m_pitch = (src_rate << FLOATBITS) / dst_rate; + } +#endif + // ---------------------------------------------------- + // Select table to use: + // * 8 bits -> 8 bits + // * 16 bits -> 8 bits + // * 8 bits -> 16 bits + // * 16 bits -> 16 bits + + int table_no, table_no2; + int i_sign, i_swap; + + switch (pcm_format->GetBPS()) { + case 8: + table_no = 0; + break; + case 16: + table_no = 1; + break; + } + switch (pcm_format2->GetBPS()) { + case 8: + table_no2 = 0; + break; + case 16: + table_no2 = 1; + break; + } + + if (pcm_format2->Signed() != pcm_format->Signed()) + i_sign = 1; + else + i_sign = 0; #define MY_ORDER wxBYTE_ORDER #if wxBYTE_ORDER == wxLITTLE_ENDIAN @@ -189,36 +299,91 @@ bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase& format) #define OTHER_ORDER wxLITTLE_ENDIAN #endif - // -------------------------------------------------------- - // Find the good converter ! + // -------------------------------------------------------- + // Find the good converter ! + if (pcm_format->GetOrder() == OTHER_ORDER) { + if (pcm_format->GetOrder() == pcm_format2->GetOrder()) + i_swap = 2; + else + i_swap = 1; + } else { + if (pcm_format->GetOrder() == pcm_format2->GetOrder()) + i_swap = 0; + else + i_swap = 1; + } - if (pcm_format->GetOrder() == OTHER_ORDER && - pcm_format2->GetOrder() == OTHER_ORDER && change_sign) - index = CONVERT_SWAP_SIGN_SWAP; + m_function_out = s_converters[table_no*2+table_no2][i_swap][i_sign]; + m_function_in = s_converters[table_no2*2+table_no][i_swap][i_sign]; + m_multiplier_out = s_converters_multip[table_no*2+table_no2]; + m_multiplier_in = s_converters_multip[table_no2*2+table_no2]; - else if (pcm_format->GetOrder() == OTHER_ORDER && - pcm_format2->GetOrder() == MY_ORDER && change_sign) - index = CONVERT_SWAP_SIGN; + if (m_prebuffer) + delete[] m_prebuffer; - else if (pcm_format->GetOrder() == MY_ORDER && - pcm_format->GetOrder() == OTHER_ORDER && change_sign) - index = CONVERT_SIGN_SWAP; + // We try to minimize the need of dynamic memory allocation by preallocating a buffer. But + // to be sure it will be efficient we minimize the best size. + if (m_multiplier_in < m_multiplier_out) { + m_prebuffer_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_out); + m_best_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_in); + } else { + m_prebuffer_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_in); + m_best_size = (wxUint32)(m_sndio->GetBestSize() * m_multiplier_out); + } + + m_prebuffer = new char[m_prebuffer_size]; + + bool SetSoundFormatReturn; + + SetSoundFormatReturn = m_sndio->SetSoundFormat(*new_format); + wxASSERT( SetSoundFormatReturn ); + + m_sndformat = new_format; + return TRUE; +} - else if (change_sign) - index = CONVERT_SIGN; +wxUint32 wxSoundStreamPcm::GetWriteSize(wxUint32 len) const +{ + // For the moment, it is simple but next time it will become more complicated + // (Resampling) + return (wxUint32)(len * m_multiplier_out); +} - else if (!change_sign && - pcm_format->GetOrder() != pcm_format2->GetOrder()) - index = CONVERT_SWAP; +wxUint32 wxSoundStreamPcm::GetReadSize(wxUint32 len) const +{ + return (wxUint32)(len / m_multiplier_in); +} + +// Resampling engine. NOT FINISHED and NOT INCLUDED but this is a first DRAFT. - else - index = CONVERT_BPS; +#if 0 - m_function_out = current_table_out[index]; - m_function_in = current_table_in[index]; +#define FLOATBITS 16 +#define INTBITS 16 +#define FLOATMASK 0xffff +#define INTMASK 0xffff0000 - m_sndio->SetSoundFormat(*new_format); - m_sndformat = new_format; - return TRUE; +void ResamplingShrink_##DEPTH##(const void *source, void *destination, wxUint32 len) +{ + wxUint##DEPTH## *source_data, *dest_data; + wxUint32 pos; + + source_data = (wxUint##DEPTH## *)source; + dest_data = (wxUint##DEPTH## *)destination; + + pos = m_saved_pos; + while (len > 0) { + // Increment the position in the input buffer + pos += m_pitch; + if (pos & INTMASK) { + pos &= FLOATMASK; + + *dest_data ++ = *source_data; + } + len--; + source_data++; + } + m_saved_pos = pos; } +#endif diff --git a/utils/wxMMedia2/lib/sndcpcm.h b/utils/wxMMedia2/lib/sndcpcm.h index 6880d8b7d0..9064e5813c 100644 --- a/utils/wxMMedia2/lib/sndcpcm.h +++ b/utils/wxMMedia2/lib/sndcpcm.h @@ -20,21 +20,34 @@ // class wxSoundStreamPcm: public wxSoundStreamCodec { - public: - typedef void (*ConverterType)(const char *buf_in, char *buf_out, wxUint32 len); - - wxSoundStreamPcm(wxSoundStream& sndio); - ~wxSoundStreamPcm(); - - wxSoundStream& Read(void *buffer, wxUint32 len); - wxSoundStream& Write(const void *buffer, wxUint32 len); - - bool SetSoundFormat(const wxSoundFormatBase& format); - - protected: - ConverterType m_function_out, m_function_in; - - bool m_16_to_8; +public: + typedef void (*ConverterType)(const void *buf_in, void *buf_out, + wxUint32 len); + + wxSoundStreamPcm(wxSoundStream& sndio); + ~wxSoundStreamPcm(); + + wxSoundStream& Read(void *buffer, wxUint32 len); + wxSoundStream& Write(const void *buffer, wxUint32 len); + + bool SetSoundFormat(const wxSoundFormatBase& format); + + wxUint32 GetBestSize() const; + +protected: + wxUint32 GetReadSize(wxUint32 len) const; + wxUint32 GetWriteSize(wxUint32 len) const; + +protected: + ConverterType m_function_out, m_function_in; + + // Static temporary buffer + char *m_prebuffer; + wxUint32 m_prebuffer_size; + // Estimated best size to fit into the static buffer + wxUint32 m_best_size; + // Multiplier for IO buffer size + float m_multiplier_in, m_multiplier_out; }; #endif diff --git a/utils/wxMMedia2/lib/sndesd.cpp b/utils/wxMMedia2/lib/sndesd.cpp index 700bb1baa6..59c737c04b 100644 --- a/utils/wxMMedia2/lib/sndesd.cpp +++ b/utils/wxMMedia2/lib/sndesd.cpp @@ -59,7 +59,7 @@ wxSoundStreamESD::wxSoundStreamESD(const wxString& hostname) SetSoundFormat(pcm_default); // Initialize some variable - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; m_esd_stop = TRUE; m_q_filled = TRUE; m_fd_output= -1; @@ -84,9 +84,9 @@ wxSoundStream& wxSoundStreamESD::Read(void *buffer, wxUint32 len) m_lastcount = (wxUint32)ret = read(m_fd_input, buffer, len); if (ret < 0) - m_snderror = wxSOUND_IOERR; + m_snderror = wxSOUND_IOERROR; else - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; return *this; } @@ -101,9 +101,9 @@ wxSoundStream& wxSoundStreamESD::Write(const void *buffer, wxUint32 len) m_lastcount = (wxUint32)ret = write(m_fd_output, buffer, len); if (ret < 0) - m_snderror = wxSOUND_IOERR; + m_snderror = wxSOUND_IOERROR; else - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; m_q_filled = TRUE; @@ -133,7 +133,7 @@ bool wxSoundStreamESD::SetSoundFormat(const wxSoundFormatBase& format) m_sndformat = format.Clone(); if (!m_sndformat) { - m_snderror = wxSOUND_MEMERR; + m_snderror = wxSOUND_MEMERROR; return FALSE; } pcm_format = (wxSoundFormatPcm *)m_sndformat; @@ -141,7 +141,7 @@ bool wxSoundStreamESD::SetSoundFormat(const wxSoundFormatBase& format) // Detect the best format DetectBest(pcm_format); - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; if (*pcm_format != format) { m_snderror = wxSOUND_NOEXACT; return FALSE; @@ -256,7 +256,7 @@ void wxSoundStreamESD::DetectBest(wxSoundFormatPcm *pcm) { wxSoundFormatPcm best_pcm; - // We change neither the number of channels nor the sample rate + // We change neither the number of channels nor the sample rate because ESD is clever. best_pcm.SetSampleRate(pcm->GetSampleRate()); best_pcm.SetChannels(pcm->GetChannels()); diff --git a/utils/wxMMedia2/lib/sndfile.cpp b/utils/wxMMedia2/lib/sndfile.cpp index c92ea71d9e..010529d142 100644 --- a/utils/wxMMedia2/lib/sndfile.cpp +++ b/utils/wxMMedia2/lib/sndfile.cpp @@ -325,7 +325,7 @@ wxString wxSoundFileStream::GetCodecName() const wxUint32 wxSoundFileStream::GetLength() { - if (m_input && !m_prepared && GetError() == wxSOUND_NOERR) + if (m_input && !m_prepared && GetError() == wxSOUND_NOERROR) return (PrepareToPlay()) ? m_length : 0; return m_length; @@ -333,7 +333,7 @@ wxUint32 wxSoundFileStream::GetLength() wxUint32 wxSoundFileStream::GetPosition() { - if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR) + if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERROR) PrepareToPlay(); return m_length-m_bytes_left; @@ -341,7 +341,7 @@ wxUint32 wxSoundFileStream::GetPosition() wxUint32 wxSoundFileStream::SetPosition(wxUint32 new_position) { - if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR) + if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERROR) PrepareToPlay(); if (!m_prepared) diff --git a/utils/wxMMedia2/lib/sndg72x.cpp b/utils/wxMMedia2/lib/sndg72x.cpp index 11cd9d1d97..d2c94ec83a 100644 --- a/utils/wxMMedia2/lib/sndg72x.cpp +++ b/utils/wxMMedia2/lib/sndg72x.cpp @@ -21,7 +21,7 @@ // -------------------------------------------------------------------------- wxSoundFormatG72X::wxSoundFormatG72X() - : m_srate(22050) + : m_srate(22050) { } @@ -31,77 +31,77 @@ wxSoundFormatG72X::~wxSoundFormatG72X() void wxSoundFormatG72X::SetSampleRate(wxUint32 srate) { - m_srate = srate; + m_srate = srate; } wxUint32 wxSoundFormatG72X::GetSampleRate() const { - return m_srate; + return m_srate; } void wxSoundFormatG72X::SetG72XType(wxSoundG72XType type) { - m_g72x_type = type; + m_g72x_type = type; } wxSoundFormatBase *wxSoundFormatG72X::Clone() const { - wxSoundFormatG72X *g72x = new wxSoundFormatG72X(); + wxSoundFormatG72X *g72x = new wxSoundFormatG72X(); - g72x->m_srate = m_srate; - g72x->m_g72x_type = m_g72x_type; - return g72x; + g72x->m_srate = m_srate; + g72x->m_g72x_type = m_g72x_type; + return g72x; } wxUint32 wxSoundFormatG72X::GetTimeFromBytes(wxUint32 bytes) const { - int n_bits; - - switch (m_g72x_type) { - case wxSOUND_G721: - n_bits = 4; - break; - case wxSOUND_G723_24: - n_bits = 3; - break; - case wxSOUND_G723_40: - n_bits = 5; - break; - default: - n_bits = 0; - break; - } - return (wxUint32)((bytes / m_srate) * ((float)n_bits / 8)); + int n_bits; + + switch (m_g72x_type) { + case wxSOUND_G721: + n_bits = 4; + break; + case wxSOUND_G723_24: + n_bits = 3; + break; + case wxSOUND_G723_40: + n_bits = 5; + break; + default: + n_bits = 0; + break; + } + return (wxUint32)((bytes / m_srate) * n_bits) / 8; } wxUint32 wxSoundFormatG72X::GetBytesFromTime(wxUint32 time) const { - int n_bits; - - switch (m_g72x_type) { - case wxSOUND_G721: - n_bits = 4; - break; - case wxSOUND_G723_24: - n_bits = 3; - break; - case wxSOUND_G723_40: - n_bits = 5; - break; - default: - n_bits = 0; - } - return (wxUint32)(time * (m_srate * ((float)n_bits / 8))); + int n_bits; + + switch (m_g72x_type) { + case wxSOUND_G721: + n_bits = 4; + break; + case wxSOUND_G723_24: + n_bits = 3; + break; + case wxSOUND_G723_40: + n_bits = 5; + break; + default: + n_bits = 0; + } + return (wxUint32)((time * m_srate * n_bits) / 8); } bool wxSoundFormatG72X::operator !=(const wxSoundFormatBase& frmt2) const { - wxSoundFormatG72X *g72x = (wxSoundFormatG72X *)&frmt2; - - if (frmt2.GetType() != wxSOUND_G72X) - return TRUE; - - return (g72x->m_srate != m_srate || g72x->m_g72x_type != m_g72x_type); + wxSoundFormatG72X *g72x = (wxSoundFormatG72X *)&frmt2; + + if (frmt2.GetType() != wxSOUND_G72X) + return TRUE; + + return (g72x->m_srate != m_srate || g72x->m_g72x_type != m_g72x_type); } // -------------------------------------------------------------------------- @@ -109,195 +109,196 @@ bool wxSoundFormatG72X::operator !=(const wxSoundFormatBase& frmt2) const // -------------------------------------------------------------------------- wxSoundStreamG72X::wxSoundStreamG72X(wxSoundStream& sndio) - : wxSoundStreamCodec(sndio) + : wxSoundStreamCodec(sndio) { - // PCM converter - m_router = new wxSoundRouterStream(sndio); - m_state = new g72state; - g72x_init_state(m_state); + // PCM converter + m_router = new wxSoundRouterStream(sndio); + m_state = new g72state; + g72x_init_state(m_state); } wxSoundStreamG72X::~wxSoundStreamG72X() { - delete m_router; + delete m_router; } wxSoundStream& wxSoundStreamG72X::Read(void *buffer, wxUint32 len) { - wxUint16 *old_linear; - register wxUint16 *linear_buffer; - register wxUint32 real_len; - register wxUint32 countdown = len; - - real_len = (len * 8 / m_n_bits); - - old_linear = linear_buffer = new wxUint16[real_len]; - - m_router->Read(linear_buffer, real_len); - - real_len = (wxUint32)(m_router->GetLastAccess() * ((float)m_n_bits / 8)); - if (!real_len) - return *m_router; - - m_io_buffer = (wxUint8 *)buffer; - m_current_b_pos = 0; - - while (countdown != 0) { - PutBits(m_coder(*linear_buffer++, AUDIO_ENCODING_LINEAR, m_state)); - countdown--; - } - m_lastcount = real_len; - m_snderror = m_router->GetError(); - - delete[] old_linear; - - return *this; + wxUint16 *old_linear; + register wxUint16 *linear_buffer; + register wxUint32 real_len; + register wxUint32 countdown = len; + + real_len = (len * 8 / m_n_bits); + + old_linear = linear_buffer = new wxUint16[real_len]; + + m_router->Read(linear_buffer, real_len); + + real_len = (wxUint32)(m_router->GetLastAccess() * ((float)m_n_bits / 8)); + if (!real_len) + return *m_router; + + m_io_buffer = (wxUint8 *)buffer; + m_current_b_pos = 0; + + while (countdown != 0) { + PutBits(m_coder(*linear_buffer++, AUDIO_ENCODING_LINEAR, m_state)); + countdown--; + } + m_lastcount = real_len; + m_snderror = m_router->GetError(); + + delete[] old_linear; + + return *this; } wxSoundStream& wxSoundStreamG72X::Write(const void *buffer, wxUint32 len) { - wxUint16 *old_linear; - register wxUint16 *linear_buffer; - register wxUint32 countdown = len; - register wxUint32 real_len; - - // Compute the real length (PCM format) to sendt to the sound card - real_len = (len * m_n_bits / 8); - - // Allocate a temporary buffer - old_linear = linear_buffer = new wxUint16[real_len]; - - // Bad, we override the const - m_io_buffer = (wxUint8 *)buffer; - m_current_b_pos = 0; - - // Decode the datas - while (countdown != 0) { - *linear_buffer++ = m_decoder(GetBits(), AUDIO_ENCODING_LINEAR, m_state); - countdown--; - } - m_lastcount = len; - - // Send them to the sound card - m_router->Write(old_linear, real_len); - - // Destroy the temporary buffer - delete[] old_linear; - - return *m_router; + wxUint16 *old_linear; + register wxUint16 *linear_buffer; + register wxUint32 countdown = len; + register wxUint32 real_len; + + // Compute the real length (PCM format) to sendt to the sound card + real_len = (len * m_n_bits / 8); + + // Allocate a temporary buffer + old_linear = linear_buffer = new wxUint16[real_len]; + + // Bad, we override the const + m_io_buffer = (wxUint8 *)buffer; + m_current_b_pos = 0; + + // Decode the datas + while (countdown != 0) { + *linear_buffer++ = m_decoder(GetBits(), AUDIO_ENCODING_LINEAR, m_state); + countdown--; + } + m_lastcount = len; + + // Send them to the sound card + m_router->Write(old_linear, real_len); + + // Destroy the temporary buffer + delete[] old_linear; + + return *m_router; } bool wxSoundStreamG72X::SetSoundFormat(const wxSoundFormatBase& format) { - if (format.GetType() != wxSOUND_G72X) { - m_snderror = wxSOUND_INVFRMT; - return FALSE; - } - - wxSoundFormatPcm pcm; - wxSoundFormatG72X *g72x; - - wxSoundStreamCodec::SetSoundFormat(format); - - g72x = (wxSoundFormatG72X *)m_sndformat; - - // Set PCM as the output format of the codec - pcm.SetSampleRate(g72x->GetSampleRate()); - pcm.SetBPS(16); - pcm.SetChannels(1); - pcm.Signed(TRUE); - pcm.SetOrder(wxBYTE_ORDER); - - // Look for the correct codec to use and set its bit width - switch (g72x->GetG72XType()) { - case wxSOUND_G721: - m_n_bits = 4; - m_coder = g721_encoder; - m_decoder = g721_decoder; - break; - case wxSOUND_G723_24: - m_n_bits = 3; - m_coder = g723_24_encoder; - m_decoder = g723_24_decoder; - break; - case wxSOUND_G723_40: - m_n_bits = 5; - m_coder = g723_40_encoder; - m_decoder = g723_40_decoder; - break; - } - - // Let the router finish the work - m_router->SetSoundFormat(pcm); - - return TRUE; + if (format.GetType() != wxSOUND_G72X) { + m_snderror = wxSOUND_INVFRMT; + return FALSE; + } + + wxSoundFormatPcm pcm; + wxSoundFormatG72X *g72x; + + wxSoundStreamCodec::SetSoundFormat(format); + + g72x = (wxSoundFormatG72X *)m_sndformat; + + // Set PCM as the output format of the codec + pcm.SetSampleRate(g72x->GetSampleRate()); + pcm.SetBPS(16); + pcm.SetChannels(1); // Only mono supported + pcm.Signed(TRUE); + pcm.SetOrder(wxBYTE_ORDER); + + // Look for the correct codec to use and set its bit width + switch (g72x->GetG72XType()) { + case wxSOUND_G721: + m_n_bits = 4; + m_coder = g721_encoder; + m_decoder = g721_decoder; + break; + case wxSOUND_G723_24: + m_n_bits = 3; + m_coder = g723_24_encoder; + m_decoder = g723_24_decoder; + break; + case wxSOUND_G723_40: + m_n_bits = 5; + m_coder = g723_40_encoder; + m_decoder = g723_40_decoder; + break; + } + + // Let the router finish the work + m_router->SetSoundFormat(pcm); + + return TRUE; } #define BYTE_SIZE 8 wxUint8 wxSoundStreamG72X::GetBits() { - register wxUint8 bits; - - if (m_current_b_pos < m_n_bits) { - register wxUint8 b_left; - - // TRANSLATE the mask - m_current_mask >>= m_current_b_pos; - - // GET the last bits: 0001..1 - bits = (m_current_byte & m_current_mask) << (m_n_bits - m_current_b_pos); - - // GEN: 1. n times .1000 - b_left = BYTE_SIZE-m_n_bits; - m_current_mask = ((1 << m_n_bits) - 1) << b_left; - - // GET the next byte - m_current_byte = *m_io_buffer++; - - register wxUint8 tmp_mask; - - // COMPUTE a new temporary mask to get the last bits - b_left = m_n_bits - b_left; - tmp_mask = (1 << b_left) - 1; - // TRANSLATE the old mask to get ready for the next time - m_current_mask >>= b_left; - - // COMPUTE the new bit position - b_left = BYTE_SIZE - b_left; - m_current_b_pos = b_left; - tmp_mask <<= b_left; - - // GET the last bits - bits |= (m_current_byte & tmp_mask) >> b_left; - } else { - m_current_mask >>= m_n_bits; - m_current_b_pos -= m_n_bits; - bits = (m_current_byte & m_current_mask) >> m_current_b_pos; - } - return bits; + register wxUint8 bits; + + // We have two bytes to compute + if (m_current_b_pos < m_n_bits) { + register wxUint8 b_left; + + // TRANSLATE the mask + m_current_mask >>= m_current_b_pos; + + // GET the last bits: 0001..1 + bits = (m_current_byte & m_current_mask) << (m_n_bits - m_current_b_pos); + + // GEN: 1. n times .1000 + b_left = BYTE_SIZE-m_n_bits; + m_current_mask = ((1 << m_n_bits) - 1) << b_left; + + // GET the next byte + m_current_byte = *m_io_buffer++; + + register wxUint8 tmp_mask; + + // COMPUTE a new temporary mask to get the last bits + b_left = m_n_bits - b_left; + tmp_mask = (1 << b_left) - 1; + // TRANSLATE the old mask to get ready for the next time + m_current_mask >>= b_left; + + // COMPUTE the new bit position + b_left = BYTE_SIZE - b_left; + m_current_b_pos = b_left; + tmp_mask <<= b_left; + + // GET the last bits + bits |= (m_current_byte & tmp_mask) >> b_left; + } else { + m_current_mask >>= m_n_bits; + m_current_b_pos -= m_n_bits; + bits = (m_current_byte & m_current_mask) >> m_current_b_pos; + } + return bits; } void wxSoundStreamG72X::PutBits(wxUint8 bits) { - if (m_current_b_pos < m_n_bits) { - register wxUint8 tmp_mask; - register wxUint8 diff; - - diff = m_n_bits - m_current_b_pos; - // Pack bits and put the byte in the buffer - m_current_byte |= bits >> diff; - *m_io_buffer++ = m_current_byte; - - // Gen a mask - tmp_mask = ~((1 << diff) - 1); - - m_current_b_pos = BYTE_SIZE - (m_n_bits - m_current_b_pos); - - m_current_byte = (bits & (tmp_mask)) << m_current_b_pos; - } else { - m_current_b_pos -= m_n_bits; - bits <<= m_current_b_pos; - m_current_byte |= bits; - } + if (m_current_b_pos < m_n_bits) { + register wxUint8 tmp_mask; + register wxUint8 diff; + + diff = m_n_bits - m_current_b_pos; + // Pack bits and put the byte in the buffer + m_current_byte |= bits >> diff; + *m_io_buffer++ = m_current_byte; + + // Gen a mask + tmp_mask = ~((1 << diff) - 1); + + m_current_b_pos = BYTE_SIZE - (m_n_bits - m_current_b_pos); + + m_current_byte = (bits & (tmp_mask)) << m_current_b_pos; + } else { + m_current_b_pos -= m_n_bits; + bits <<= m_current_b_pos; + m_current_byte |= bits; + } } diff --git a/utils/wxMMedia2/lib/sndoss.cpp b/utils/wxMMedia2/lib/sndoss.cpp index 77e8ec47b9..33eb64f7f7 100644 --- a/utils/wxMMedia2/lib/sndoss.cpp +++ b/utils/wxMMedia2/lib/sndoss.cpp @@ -41,7 +41,7 @@ wxSoundStreamOSS::wxSoundStreamOSS(const wxString& dev_name) ioctl(m_fd, SNDCTL_DSP_GETBLKSIZE, &m_bufsize); - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; close(m_fd); @@ -68,9 +68,9 @@ wxSoundStream& wxSoundStreamOSS::Read(void *buffer, wxUint32 len) m_q_filled = TRUE; if (ret < 0) - m_snderror = wxSOUND_IOERR; + m_snderror = wxSOUND_IOERROR; else - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; return *this; } @@ -83,9 +83,9 @@ wxSoundStream& wxSoundStreamOSS::Write(const void *buffer, wxUint32 len) m_q_filled = TRUE; if (ret < 0) - m_snderror = wxSOUND_IOERR; + m_snderror = wxSOUND_IOERROR; else - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; return *this; } @@ -110,7 +110,7 @@ bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase& format) m_sndformat = format.Clone(); if (!m_sndformat) { - m_snderror = wxSOUND_MEMERR; + m_snderror = wxSOUND_MEMERROR; return FALSE; } pcm_format = (wxSoundFormatPcm *)m_sndformat; @@ -129,7 +129,7 @@ bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase& format) ioctl(m_fd, SNDCTL_DSP_CHANNELS, &tmp); pcm_format->SetChannels(tmp); - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; if (*pcm_format != format) { m_snderror = wxSOUND_NOEXACT; return FALSE; @@ -229,44 +229,43 @@ void wxSoundStreamOSS::WakeUpEvt(int evt) bool wxSoundStreamOSS::StartProduction(int evt) { - wxSoundFormatBase *old_frmt; - - if (!m_oss_stop) - 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); - else if (evt == wxSOUND_INPUT) - m_fd = open(m_devname.mb_str(), O_RDONLY); - - if (m_fd == -1) { - m_snderror = wxSOUND_INVDEV; - return FALSE; - } - - SetSoundFormat(*old_frmt); - delete old_frmt; - + wxSoundFormatBase *old_frmt; + + if (!m_oss_stop) + StopProduction(); + + old_frmt = m_sndformat->Clone(); + if (!old_frmt) { + m_snderror = wxSOUND_MEMERROR; + return FALSE; + } + + if (evt == wxSOUND_OUTPUT) + m_fd = open(m_devname.mb_str(), O_WRONLY); + else if (evt == wxSOUND_INPUT) + m_fd = open(m_devname.mb_str(), O_RDONLY); + + if (m_fd == -1) { + m_snderror = wxSOUND_INVDEV; + return FALSE; + } + + SetSoundFormat(*old_frmt); + delete old_frmt; + + int trig; + + if (evt == wxSOUND_OUTPUT) { #ifdef __WXGTK__ - int trig; - - if (evt == wxSOUND_OUTPUT) { - m_tag = gdk_input_add(m_fd, GDK_INPUT_WRITE, _wxSound_OSS_CBack, (gpointer)this); - trig = PCM_ENABLE_OUTPUT; - } else { - m_tag = gdk_input_add(m_fd, GDK_INPUT_READ, _wxSound_OSS_CBack, (gpointer)this); - trig = PCM_ENABLE_INPUT; - } -#else - while (!m_oss_stop) - OnSoundEvent(evt); + m_tag = gdk_input_add(m_fd, GDK_INPUT_WRITE, _wxSound_OSS_CBack, (gpointer)this); +#endif + trig = PCM_ENABLE_OUTPUT; + } else { +#ifdef __WXGTK__ + m_tag = gdk_input_add(m_fd, GDK_INPUT_READ, _wxSound_OSS_CBack, (gpointer)this); #endif + trig = PCM_ENABLE_INPUT; + } ioctl(m_fd, SNDCTL_DSP_SETTRIGGER, &trig); diff --git a/utils/wxMMedia2/lib/sndulaw.cpp b/utils/wxMMedia2/lib/sndulaw.cpp index 371f68b646..c5bc1011f7 100644 --- a/utils/wxMMedia2/lib/sndulaw.cpp +++ b/utils/wxMMedia2/lib/sndulaw.cpp @@ -25,7 +25,7 @@ // -------------------------------------------------------------------------- wxSoundFormatUlaw::wxSoundFormatUlaw() - : m_srate(22050) + : m_srate(22050), m_channels(1) { } @@ -35,40 +35,51 @@ wxSoundFormatUlaw::~wxSoundFormatUlaw() void wxSoundFormatUlaw::SetSampleRate(wxUint32 srate) { - m_srate = srate; + m_srate = srate; } wxUint32 wxSoundFormatUlaw::GetSampleRate() const { - return m_srate; + return m_srate; } -wxSoundFormatBase *wxSoundFormatUlaw::Clone() const +wxUint8 wxSoundFormatUlaw::GetChannels() const { - wxSoundFormatUlaw *ulaw = new wxSoundFormatUlaw(); + return m_channels; +} - ulaw->m_srate = m_srate; - return ulaw; +void wxSoundFormatUlaw::SetChannels(wxUint8 nchannels) +{ + m_channels = nchannels; +} + +wxSoundFormatBase *wxSoundFormatUlaw::Clone() const +{ + wxSoundFormatUlaw *ulaw = new wxSoundFormatUlaw(); + + ulaw->m_srate = m_srate; + ulaw->m_channels = m_channels; + return ulaw; } wxUint32 wxSoundFormatUlaw::GetTimeFromBytes(wxUint32 bytes) const { - return (bytes / m_srate); + return (bytes / m_srate); } wxUint32 wxSoundFormatUlaw::GetBytesFromTime(wxUint32 time) const { - return time * m_srate; + return time * m_srate; } bool wxSoundFormatUlaw::operator !=(const wxSoundFormatBase& frmt2) const { - wxSoundFormatUlaw *ulaw = (wxSoundFormatUlaw *)&frmt2; - - if (frmt2.GetType() != wxSOUND_ULAW) - return TRUE; - - return (ulaw->m_srate != m_srate); + wxSoundFormatUlaw *ulaw = (wxSoundFormatUlaw *)&frmt2; + + if (frmt2.GetType() != wxSOUND_ULAW) + return TRUE; + + return (ulaw->m_srate != m_srate); } // -------------------------------------------------------------------------- @@ -88,58 +99,82 @@ wxSoundStreamUlaw::~wxSoundStreamUlaw() wxSoundStream& wxSoundStreamUlaw::Read(void *buffer, wxUint32 len) { - // TODO - return *this; + wxUint16 *old_linear; + register wxUint16 *linear_buffer; + register const wxUint8 *ulaw_buffer; + register wxUint32 countdown; + + old_linear = linear_buffer = new wxUint16[len*2]; + ulaw_buffer = (const wxUint8 *)buffer; + + m_router->Read(linear_buffer, len * 2); + + m_lastcount = countdown = m_router->GetLastAccess() / 2; + m_snderror = m_router->GetError(); + if (m_snderror != wxSOUND_NOERROR) + return *this; + + while (countdown > 0) { + *linear_buffer++ = ulaw2linear(*ulaw_buffer++); + countdown--; + } + + delete[] old_linear; + + return *m_router; } wxSoundStream& wxSoundStreamUlaw::Write(const void *buffer, wxUint32 len) { - wxUint16 *old_linear; - register wxUint16 *linear_buffer; - register const wxUint8 *ulaw_buffer; - register wxUint32 countdown = len; - - old_linear = linear_buffer = new wxUint16[len*2]; - ulaw_buffer = (const wxUint8 *)buffer; - - while (countdown != 0) { - *linear_buffer++ = ulaw2linear(*ulaw_buffer++); - countdown--; - } - - m_router->Write(old_linear, len * 2); - - delete[] old_linear; - - return *m_router; + wxUint16 *old_linear; + register wxUint16 *linear_buffer; + register const wxUint8 *ulaw_buffer; + register wxUint32 countdown = len; + + old_linear = linear_buffer = new wxUint16[len*2]; + ulaw_buffer = (const wxUint8 *)buffer; + + while (countdown > 0) { + *linear_buffer++ = ulaw2linear(*ulaw_buffer++); + countdown--; + } + + m_router->Write(old_linear, len * 2); + + delete[] old_linear; + + return *m_router; } wxUint32 wxSoundStreamUlaw::GetBestSize() const { - return m_sndio->GetBestSize() / 2; + return m_sndio->GetBestSize() / 2; } bool wxSoundStreamUlaw::SetSoundFormat(const wxSoundFormatBase& format) { - if (format.GetType() != wxSOUND_ULAW) { - m_snderror = wxSOUND_INVFRMT; - return FALSE; - } - - wxSoundFormatPcm pcm; - wxSoundFormatUlaw *ulaw; - - wxSoundStreamCodec::SetSoundFormat(format); - - ulaw = (wxSoundFormatUlaw *)m_sndformat; - - pcm.SetSampleRate(ulaw->GetSampleRate()); - pcm.SetBPS(16); - pcm.SetChannels(1); - pcm.Signed(TRUE); - pcm.SetOrder(wxBYTE_ORDER); - - m_router->SetSoundFormat(pcm); - - return TRUE; + if (format.GetType() != wxSOUND_ULAW) { + m_snderror = wxSOUND_INVFRMT; + return FALSE; + } + + // As the codec only support 16 bits, Mono we must use a wxSoundRouter to filter the data and + // to translate them to a format supported by the sound card. + + wxSoundFormatPcm pcm; + wxSoundFormatUlaw *ulaw; + + wxSoundStreamCodec::SetSoundFormat(format); + + ulaw = (wxSoundFormatUlaw *)m_sndformat; + + pcm.SetSampleRate(ulaw->GetSampleRate()); + pcm.SetBPS(16); + pcm.SetChannels(ulaw->GetChannels()); + pcm.Signed(TRUE); + pcm.SetOrder(wxBYTE_ORDER); + + m_router->SetSoundFormat(pcm); + + return TRUE; } diff --git a/utils/wxMMedia2/lib/sndulaw.h b/utils/wxMMedia2/lib/sndulaw.h index 4ddba8f577..7b862e019a 100644 --- a/utils/wxMMedia2/lib/sndulaw.h +++ b/utils/wxMMedia2/lib/sndulaw.h @@ -12,6 +12,8 @@ #pragma interface "sndulaw.h" #endif +#include "wx/defs.h" + #include "sndcodec.h" #include "sndbase.h" @@ -19,26 +21,27 @@ // ULAW format // class WXDLLEXPORT wxSoundFormatUlaw: public wxSoundFormatBase { - public: - wxSoundFormatUlaw(); - ~wxSoundFormatUlaw(); - - void SetSampleRate(wxUint32 srate); - wxUint32 GetSampleRate() const; - - void SetChannels(wxUint8 channels); - wxUint8 GetChannels() const; - - wxSoundFormatType GetType() const { return wxSOUND_ULAW; } - wxSoundFormatBase *Clone() const; - - wxUint32 GetTimeFromBytes(wxUint32 bytes) const; - wxUint32 GetBytesFromTime(wxUint32 time) const; - - bool operator !=(const wxSoundFormatBase& frmt2) const; - - protected: - wxUint32 m_srate; +public: + wxSoundFormatUlaw(); + ~wxSoundFormatUlaw(); + + void SetSampleRate(wxUint32 srate); + wxUint32 GetSampleRate() const; + + void SetChannels(wxUint8 channels); + wxUint8 GetChannels() const; + + wxSoundFormatType GetType() const { return wxSOUND_ULAW; } + wxSoundFormatBase *Clone() const; + + wxUint32 GetTimeFromBytes(wxUint32 bytes) const; + wxUint32 GetBytesFromTime(wxUint32 time) const; + + bool operator !=(const wxSoundFormatBase& frmt2) const; + +protected: + wxUint32 m_srate; + wxUint8 m_channels; }; // @@ -47,19 +50,19 @@ class WXDLLEXPORT wxSoundFormatUlaw: public wxSoundFormatBase { class WXDLLEXPORT wxSoundRouterStream; class WXDLLEXPORT wxSoundStreamUlaw: public wxSoundStreamCodec { - public: - wxSoundStreamUlaw(wxSoundStream& sndio); - ~wxSoundStreamUlaw(); - - wxSoundStream& Read(void *buffer, wxUint32 len); - wxSoundStream& Write(const void *buffer, wxUint32 len); - - bool SetSoundFormat(const wxSoundFormatBase& format); - - wxUint32 GetBestSize() const; - - protected: - wxSoundRouterStream *m_router; +public: + wxSoundStreamUlaw(wxSoundStream& sndio); + ~wxSoundStreamUlaw(); + + wxSoundStream& Read(void *buffer, wxUint32 len); + wxSoundStream& Write(const void *buffer, wxUint32 len); + + bool SetSoundFormat(const wxSoundFormatBase& format); + + wxUint32 GetBestSize() const; + +protected: + wxSoundRouterStream *m_router; }; #endif diff --git a/utils/wxMMedia2/lib/sndwav.cpp b/utils/wxMMedia2/lib/sndwav.cpp index 487ddfb3fc..38b96186e0 100644 --- a/utils/wxMMedia2/lib/sndwav.cpp +++ b/utils/wxMMedia2/lib/sndwav.cpp @@ -60,7 +60,7 @@ wxString wxSoundWave::GetCodecName() const bool wxSoundWave::CanRead() { wxUint32 len, signature1, signature2; - m_snderror = wxSOUND_NOERR; + m_snderror = wxSOUND_NOERROR; // Test the main signatures: // "RIFF" diff --git a/utils/wxMMedia2/lib/sndwin.cpp b/utils/wxMMedia2/lib/sndwin.cpp index f09231ee0d..a307c81ca2 100644 --- a/utils/wxMMedia2/lib/sndwin.cpp +++ b/utils/wxMMedia2/lib/sndwin.cpp @@ -651,6 +651,7 @@ void wxSoundStreamWin::NotifyDoneBuffer(wxUint32 dev_handle, int flag) // ------------------------------------------------------------------------- bool wxSoundStreamWin::SetSoundFormat(wxSoundFormatBase& base) { + // TODO: detect best format return wxSoundStream::SetSoundFormat(base); } diff --git a/utils/wxMMedia2/lib/vidwin.cpp b/utils/wxMMedia2/lib/vidwin.cpp index b6f5ee9914..131b12503c 100644 --- a/utils/wxMMedia2/lib/vidwin.cpp +++ b/utils/wxMMedia2/lib/vidwin.cpp @@ -1,4 +1,4 @@ -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- // Name: vidwin.h // Purpose: wxMMedia // Author: Guilhem Lavaux @@ -6,7 +6,7 @@ // Updated: // Copyright: (C) 1998, 1999, 2000 Guilhem Lavaux // License: wxWindows license -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- #ifdef __GNUG__ #pragma implementation "vidwin.h" @@ -45,6 +45,7 @@ wxVideoWindows::wxVideoWindows(wxInputStream& str) m_filename = wxGetTempFileName("wxvid"); m_paused = FALSE; m_stopped = TRUE; + m_frameRate = 1.0; wxFileOutputStream temp_file(m_filename); temp_file << str; @@ -60,6 +61,7 @@ wxVideoWindows::wxVideoWindows(const wxString& filename) m_filename = filename; m_paused = FALSE; m_stopped = TRUE; + m_frameRate = 1.0; OpenFile(); } @@ -73,17 +75,41 @@ wxVideoWindows::~wxVideoWindows(void) void wxVideoWindows::OpenFile() { - MCI_DGV_OPEN_PARMS open_struct; + MCI_DGV_OPEN_PARMS openStruct; + MCI_DGV_SET_PARMS setStruct; + MCI_STATUS_PARMS statusStruct; DWORD ret; - open_struct.lpstrDeviceType = "avivideo"; - open_struct.lpstrElementName = (LPSTR)(m_filename.mb_str()); - open_struct.hWndParent = 0; + openStruct.lpstrDeviceType = "avivideo"; + openStruct.lpstrElementName = (LPSTR)(m_filename.mb_str()); + openStruct.hWndParent = 0; ret = mciSendCommand(0, MCI_OPEN, MCI_OPEN_ELEMENT|MCI_DGV_OPEN_PARENT|MCI_OPEN_TYPE|MCI_DGV_OPEN_32BIT, - (DWORD)(LPVOID)&open_struct); - m_internal->m_dev_id = open_struct.wDeviceID; + (DWORD)(LPVOID)&openStruct); + m_internal->m_dev_id = openStruct.wDeviceID; + + + setStruct.dwCallback = 0; + setStruct.dwTimeFormat = MCI_FORMAT_FRAMES; + + ret = mciSendCommand(m_internal->m_dev_id, MCI_SET, MCI_SET_TIME_FORMAT, + (DWORD)(LPVOID)&setStruct); + + + statusStruct.dwCallback = 0; + statusStruct.dwItem = MCI_DGV_STATUS_FRAME_RATE; + ret = mciSendCommand(m_internal->m_dev_id, MCI_STATUS, + MCI_STATUS_ITEM, + (DWORD)(LPVOID)&statusStruct); + + m_frameRate = ((double)statusStruct.dwReturn) / 1000; + + statusStruct.dwItem = MCI_DGV_STATUS_BITSPERSAMPLE; + ret = mciSendCommand(m_internal->m_dev_id, MCI_STATUS, MCI_STATUS_ITEM, + (DWORD)(LPVOID)&statusStruct); + m_bps = statusStruct.dwReturn; + } bool wxVideoWindows::Pause() @@ -91,7 +117,7 @@ bool wxVideoWindows::Pause() if (m_paused || m_stopped) return TRUE; m_paused = TRUE; - return (mciSendCommand(m_internal->m_dev_id, MCI_PAUSE, 0, 0) == 0); + return (mciSendCommand(m_internal->m_dev_id, MCI_PAUSE, MCI_WAIT, 0) == 0); } bool wxVideoWindows::Resume() @@ -114,7 +140,6 @@ bool wxVideoWindows::IsStopped() const bool wxVideoWindows::GetSize(wxSize& size) const { - // Two random numbers. size.SetWidth(200); size.SetHeight(200); return TRUE; @@ -169,16 +194,17 @@ bool wxVideoWindows::Stop() if (m_stopped) return FALSE; m_stopped = TRUE; - if (::mciSendCommand(m_internal->m_dev_id, MCI_STOP, 0, NULL) != 0) + if (::mciSendCommand(m_internal->m_dev_id, MCI_STOP, MCI_WAIT, NULL) != 0) return FALSE; seekStruct.dwCallback = 0; seekStruct.dwTo = 0; - return (::mciSendCommand(m_internal->m_dev_id, MCI_SEEK, 0, (DWORD)(LPVOID)&seekStruct) == 0); + return (::mciSendCommand(m_internal->m_dev_id, MCI_SEEK, MCI_SEEK_TO_START|MCI_WAIT, (DWORD)(LPVOID)&seekStruct) == 0); } - // TODO TODO +// I hate windows :-(. The doc says MCI_STATUS should return all info I want but when I call it +// it returns to me with an UNSUPPORTED_FUNCTION error. I will have to do all by myself. Grrrr ! wxString wxVideoWindows::GetMovieCodec() const { @@ -202,12 +228,12 @@ wxUint8 wxVideoWindows::GetChannels() const wxUint8 wxVideoWindows::GetBPS() const { - return 8; + return m_bps; } double wxVideoWindows::GetFrameRate() const { - return 1.0; + return m_frameRate; } wxUint32 wxVideoWindows::GetNbFrames() const diff --git a/utils/wxMMedia2/lib/vidwin.h b/utils/wxMMedia2/lib/vidwin.h index fd8a64b2b6..eba6bd2470 100644 --- a/utils/wxMMedia2/lib/vidwin.h +++ b/utils/wxMMedia2/lib/vidwin.h @@ -59,6 +59,8 @@ protected: struct VIDW_Internal *m_internal; bool m_paused, m_stopped, m_remove_file; wxString m_filename; + double m_frameRate; + wxUint8 m_bps; void OpenFile(); public: -- 2.45.2