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
This commit is contained in:
Guilhem Lavaux
2000-02-27 10:44:49 +00:00
parent bdeca1d18c
commit 8b33ae2d5a
23 changed files with 1148 additions and 563 deletions

View File

@@ -19,6 +19,7 @@
#include "wx/defs.h" #include "wx/defs.h"
#include "wx/object.h" #include "wx/object.h"
#include "wx/event.h" #include "wx/event.h"
#include "wx/stream.h"
// Process Event handling // Process Event handling
class WXDLLEXPORT wxProcessEvent : public wxEvent class WXDLLEXPORT wxProcessEvent : public wxEvent
@@ -51,7 +52,8 @@ class WXDLLEXPORT wxProcess : public wxEvtHandler
DECLARE_DYNAMIC_CLASS(wxProcess) DECLARE_DYNAMIC_CLASS(wxProcess)
public: 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); virtual void OnTerminate(int pid, int status);
@@ -59,8 +61,21 @@ public:
// before the process it started terminates // before the process it started terminates
void Detach(); 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: protected:
int m_id; int m_id;
bool m_needPipe;
wxInputStream *m_in_stream;
wxOutputStream *m_out_stream;
}; };
typedef void (wxObject::*wxProcessEventFunction)(wxProcessEvent&); typedef void (wxObject::*wxProcessEventFunction)(wxProcessEvent&);

View File

@@ -29,12 +29,23 @@
IMPLEMENT_DYNAMIC_CLASS(wxProcess, wxEvtHandler) IMPLEMENT_DYNAMIC_CLASS(wxProcess, wxEvtHandler)
IMPLEMENT_DYNAMIC_CLASS(wxProcessEvent, wxEvent) IMPLEMENT_DYNAMIC_CLASS(wxProcessEvent, wxEvent)
wxProcess::wxProcess(wxEvtHandler *parent, int id) wxProcess::wxProcess(wxEvtHandler *parent, bool needPipe, int id)
{ {
if (parent) if (parent)
SetNextHandler(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) void wxProcess::OnTerminate(int pid, int status)
@@ -51,3 +62,24 @@ void wxProcess::Detach()
{ {
SetNextHandler(NULL); 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;
}

View File

@@ -37,6 +37,7 @@
#include "wx/log.h" #include "wx/log.h"
#ifdef __WIN32__ #ifdef __WIN32__
#include "wx/stream.h"
#include "wx/process.h" #include "wx/process.h"
#endif #endif
@@ -120,6 +121,94 @@ public:
bool state; // set to FALSE when the process finishes 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 // implementation
// ============================================================================ // ============================================================================
@@ -289,7 +378,6 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
// only reached for space not inside quotes // only reached for space not inside quotes
break; break;
} }
wxString commandArgs = pc; wxString commandArgs = pc;
wxWindow *winTop = wxTheApp->GetTopWindow(); wxWindow *winTop = wxTheApp->GetTopWindow();
@@ -313,6 +401,46 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
return result; return result;
#else // 1 #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 // create the process
STARTUPINFO si; STARTUPINFO si;
@@ -327,7 +455,7 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
(wxChar *)command.c_str(), // full command line (wxChar *)command.c_str(), // full command line
NULL, // security attributes: defaults for both NULL, // security attributes: defaults for both
NULL, // the process and its main thread NULL, // the process and its main thread
FALSE, // don't inherit handles inheritHandles, // inherit handles if we need pipes
CREATE_DEFAULT_ERROR_MODE | CREATE_DEFAULT_ERROR_MODE |
CREATE_SUSPENDED, // flags CREATE_SUSPENDED, // flags
NULL, // environment (use the same) NULL, // environment (use the same)
@@ -336,11 +464,31 @@ long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
&pi // process info &pi // process info
) == 0 ) ) == 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()); wxLogSysError(_("Execution of command '%s' failed"), command.c_str());
return 0; 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 // register the class for the hidden window used for the notifications
if ( !gs_classForHiddenWindow ) if ( !gs_classForHiddenWindow )
{ {

View File

@@ -25,6 +25,8 @@
#include "wx/process.h" #include "wx/process.h"
#include "wx/thread.h" #include "wx/thread.h"
#include "wx/stream.h"
#if wxUSE_GUI #if wxUSE_GUI
#include "wx/unix/execute.h" #include "wx/unix/execute.h"
#endif #endif
@@ -274,6 +276,83 @@ void wxHandleProcessTermination(wxEndProcessData *proc_data)
#define WXUNUSED_UNLESS_GUI(p) #define WXUNUSED_UNLESS_GUI(p)
#endif #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, long wxExecute(wxChar **argv,
bool sync, bool sync,
wxProcess * WXUNUSED_UNLESS_GUI(process)) wxProcess * WXUNUSED_UNLESS_GUI(process))
@@ -316,6 +395,26 @@ long wxExecute(wxChar **argv,
} }
#endif // wxUSE_GUI #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 // fork the process
#ifdef HAVE_VFORK #ifdef HAVE_VFORK
pid_t pid = vfork(); pid_t pid = vfork();
@@ -324,6 +423,14 @@ long wxExecute(wxChar **argv,
#endif #endif
if (pid == -1) 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") ); wxLogSysError( _("Fork failed") );
ARGS_CLEANUP; ARGS_CLEANUP;
@@ -347,7 +454,7 @@ long wxExecute(wxChar **argv,
for ( int fd = 0; fd < FD_SETSIZE; fd++ ) for ( int fd = 0; fd < FD_SETSIZE; fd++ )
{ {
#if wxUSE_GUI #if wxUSE_GUI
if ( fd == end_proc_detect[1] ) if ( fd == end_proc_detect[1] || fd == in_pipe[0] || fd == out_pipe[1] )
continue; continue;
#endif // wxUSE_GUI #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 #if 0
close(STDERR_FILENO); close(STDERR_FILENO);
@@ -386,8 +503,8 @@ long wxExecute(wxChar **argv,
data->process = NULL; data->process = NULL;
// sync execution: indicate it by negating the pid // sync execution: indicate it by negating the pid
data->pid = -pid; data->pid = -pid;
data->tag = wxAddProcessCallback(data, end_proc_detect[0]); data->tag = wxAddProcessCallback(data, end_proc_detect[0]);
// we're in parent // we're in parent
close(end_proc_detect[1]); // close writing side close(end_proc_detect[1]); // close writing side
@@ -403,12 +520,26 @@ long wxExecute(wxChar **argv,
} }
else 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 // async execution, nothing special to do - caller will be
// notified about the process termination if process != NULL, data // notified about the process termination if process != NULL, data
// will be deleted in GTK_EndProcessDetector // will be deleted in GTK_EndProcessDetector
data->process = process; data->process = process;
data->pid = pid; data->pid = pid;
data->tag = wxAddProcessCallback(data, end_proc_detect[0]); data->tag = wxAddProcessCallback(data, end_proc_detect[0]);
// we're in parent // we're in parent
close(end_proc_detect[1]); // close writing side close(end_proc_detect[1]); // close writing side

View File

@@ -298,7 +298,9 @@ wxString MMBoardSoundFile::GetStringInformation()
case wxSOUND_PCM: { case wxSOUND_PCM: {
wxSoundFormatPcm *pcm_format = (wxSoundFormatPcm *)format; 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") info += wxString::Format(wxT("Sampling rate: %d\n")
wxT("Bits per sample: %d\n") wxT("Bits per sample: %d\n")
wxT("Number of channels: %d\n"), wxT("Number of channels: %d\n"),

View File

@@ -202,7 +202,7 @@ wxUint8 MMBoardApp::TestMultimediaCaps()
// We now test the ESD support // We now test the ESD support
dev = new wxSoundStreamESD(); dev = new wxSoundStreamESD();
if (dev->GetError() == wxSOUND_NOERR) if (dev->GetError() == wxSOUND_NOERROR)
caps |= MM_SOUND_ESD; caps |= MM_SOUND_ESD;
delete dev; delete dev;
@@ -210,7 +210,7 @@ wxUint8 MMBoardApp::TestMultimediaCaps()
// WARNING: There is a conflict between ESD and ALSA // WARNING: There is a conflict between ESD and ALSA
dev = new wxSoundStreamOSS(); dev = new wxSoundStreamOSS();
if (dev->GetError() == wxSOUND_NOERR) if (dev->GetError() == wxSOUND_NOERROR)
caps |= MM_SOUND_OSS; caps |= MM_SOUND_OSS;
delete dev; delete dev;
#endif #endif

View File

@@ -1,5 +1,5 @@
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Name: sndsnd.cpp // Name: cdbase.cpp
// Purpose: wxMMedia // Purpose: wxMMedia
// Author: Guilhem Lavaux // Author: Guilhem Lavaux
// Created: 1997 // Created: 1997

View File

@@ -1,7 +1,5 @@
#include <stdio.h>
#define DEFINE_CONV(name, input_type, output_type, convert) \ #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 input_type src; \
register const input_type *t_buf_in = (input_type *)buf_in; \ 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_8_sign, wxUint8, wxUint8, (src ^ 0x80))
DEFINE_CONV(8_16, wxUint8, wxUint16, (((wxUint16)src) << 8)) 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, wxUint16, wxUint8, (wxUint8)(src & 0xff))
DEFINE_CONV(16_swap_8_sign, wxUint16, wxUint8, (wxUint8)((src & 0xff) ^ 0x80)) 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_sign, wxUint16, wxUint16, (src ^ 0x8000))
DEFINE_CONV(16_swap, wxUint16, wxUint16, (((src & 0xff) << 8) | ((src >> 8) & 0xff))) 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)) // Problem.
DEFINE_CONV(16_sign_16_swap, wxUint16, wxUint16, ((((src & 0xff) << 8) | ((src >> 8) & 0xff)) ^ 0x80)) 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)) DEFINE_CONV(16_swap_16_sign_swap, wxUint16, wxUint16, (src ^ 0x80))

View File

@@ -99,6 +99,7 @@ bool wxSoundAiff::PrepareToPlay()
m_snderror = wxSOUND_INVSTRM; m_snderror = wxSOUND_INVSTRM;
return FALSE; return FALSE;
} }
m_snderror = wxSOUND_NOERROR;
data.BigEndianOrdered(TRUE); data.BigEndianOrdered(TRUE);
@@ -129,9 +130,11 @@ bool wxSoundAiff::PrepareToPlay()
wxUint32 num_samples; wxUint32 num_samples;
double srate; double srate;
wxSoundFormatPcm sndformat; wxSoundFormatPcm sndformat;
// Get sound data informations
data >> channels >> num_samples >> bps >> srate; data >> channels >> num_samples >> bps >> srate;
// Convert them in a wxSoundFormat object
sndformat.SetSampleRate((wxUint32) srate); sndformat.SetSampleRate((wxUint32) srate);
sndformat.SetBPS(bps); sndformat.SetBPS(bps);
sndformat.SetChannels(channels); sndformat.SetChannels(channels);
@@ -140,6 +143,7 @@ bool wxSoundAiff::PrepareToPlay()
if (!SetSoundFormat(sndformat)) if (!SetSoundFormat(sndformat))
return FALSE; return FALSE;
// We pass all data left
m_input->SeekI(len-18, wxFromCurrent); m_input->SeekI(len-18, wxFromCurrent);
break; break;
} }
@@ -149,6 +153,7 @@ bool wxSoundAiff::PrepareToPlay()
// m_input->SeekI(len-4, wxFromCurrent); // Pass the rest // m_input->SeekI(len-4, wxFromCurrent); // Pass the rest
m_input->SeekI(ssnd + 4, wxFromCurrent); m_input->SeekI(ssnd + 4, wxFromCurrent);
m_base_offset = m_input->TellI(); m_base_offset = m_input->TellI();
// len-8 bytes of samples
FinishPreparation(len - 8); FinishPreparation(len - 8);
end_headers = TRUE; end_headers = TRUE;
break; break;
@@ -175,6 +180,7 @@ bool wxSoundAiff::FinishRecording()
bool wxSoundAiff::RepositionStream(wxUint32 position) bool wxSoundAiff::RepositionStream(wxUint32 position)
{ {
// If the stream is not seekable "TellI() returns wxInvalidOffset" we cannot reposition stream
if (m_base_offset == wxInvalidOffset) if (m_base_offset == wxInvalidOffset)
return FALSE; return FALSE;
m_input->SeekI(m_base_offset, wxFromStart); m_input->SeekI(m_base_offset, wxFromStart);

View File

@@ -46,7 +46,7 @@ wxSoundStream::wxSoundStream()
// Reset all variables to their neutral value. // Reset all variables to their neutral value.
m_sndformat = NULL; m_sndformat = NULL;
m_handler = NULL; m_handler = NULL;
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
m_lastcount = 0; m_lastcount = 0;
for (i=0;i<2;i++) for (i=0;i<2;i++)
m_callback[i] = NULL; m_callback[i] = NULL;
@@ -85,7 +85,7 @@ bool wxSoundStream::SetSoundFormat(const wxSoundFormatBase& format)
// call twice this function the previous registered callback is absolutely // call twice this function the previous registered callback is absolutely
// ignored. // ignored.
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
void wxSoundStream::Register(int evt, wxSoundCallback cbk, char *cdata) void wxSoundStream::SetCallback(int evt, wxSoundCallback cbk, void *cdata)
{ {
int c; int c;

View File

@@ -63,14 +63,14 @@ typedef enum {
// - wxSOUND_MEMERR: Not enough memory. // - wxSOUND_MEMERR: Not enough memory.
// --------------------- // ---------------------
typedef enum { typedef enum {
wxSOUND_NOERR, wxSOUND_NOERROR,
wxSOUND_IOERR, wxSOUND_IOERROR,
wxSOUND_INVFRMT, wxSOUND_INVFRMT,
wxSOUND_INVDEV, wxSOUND_INVDEV,
wxSOUND_NOEXACT, wxSOUND_NOEXACT,
wxSOUND_INVSTRM, wxSOUND_INVSTRM,
wxSOUND_NOCODEC, wxSOUND_NOCODEC,
wxSOUND_MEMERR wxSOUND_MEMERROR
} wxSoundError; } wxSoundError;
class WXDLLEXPORT wxSoundStream; class WXDLLEXPORT wxSoundStream;
@@ -83,7 +83,7 @@ class WXDLLEXPORT wxSoundStream;
// - cdata: User callback data // - cdata: User callback data
// --------------------- // ---------------------
typedef void (*wxSoundCallback)(wxSoundStream *stream, int evt, typedef void (*wxSoundCallback)(wxSoundStream *stream, int evt,
char *cdata); void *cdata);
// //
// Base class for sound format specification // Base class for sound format specification
@@ -128,7 +128,7 @@ class wxSoundStream {
wxSoundFormatBase& GetSoundFormat() const { return *m_sndformat; } wxSoundFormatBase& GetSoundFormat() const { return *m_sndformat; }
// Register a callback for a specified async event. // 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 // Starts the async notifier. After this call, the stream begins either
// recording or playing or the two at the same time. // recording or playing or the two at the same time.
@@ -158,7 +158,7 @@ class wxSoundStream {
wxSoundStream *m_handler; wxSoundStream *m_handler;
wxSoundCallback m_callback[2]; wxSoundCallback m_callback[2];
char *m_cdata[2]; void *m_cdata[2];
protected: protected:
// Handles event // Handles event

View File

@@ -8,70 +8,124 @@
#ifdef __GNUG__ #ifdef __GNUG__
#pragma implementation "sndcpcm.cpp" #pragma implementation "sndcpcm.cpp"
#endif #endif
#include <wx/wxprec.h> #include <wx/wxprec.h>
#ifndef WX_PRECOMP
#include <wx/debug.h>
#include <wx/log.h>
#endif
#include "sndbase.h" #include "sndbase.h"
#include "sndpcm.h" #include "sndpcm.h"
#include "sndcpcm.h" #include "sndcpcm.h"
wxSoundStreamPcm::wxSoundStreamPcm(wxSoundStream& sndio) wxSoundStreamPcm::wxSoundStreamPcm(wxSoundStream& sndio)
: wxSoundStreamCodec(sndio) : wxSoundStreamCodec(sndio)
{ {
m_function_in = NULL; m_function_in = NULL;
m_function_out = NULL; m_function_out = NULL;
m_prebuffer = NULL;
m_prebuffer_size = 0;
m_best_size = 0;
} }
wxSoundStreamPcm::~wxSoundStreamPcm() wxSoundStreamPcm::~wxSoundStreamPcm()
{ {
if (m_prebuffer)
delete[] m_prebuffer;
} }
wxUint32 wxSoundStreamPcm::GetBestSize() const
{
return m_best_size;
}
#include "converter.def" #include "converter.def"
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
// Main PCM stream converter table // Main PCM stream converter table
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
wxSoundStreamPcm::ConverterType s_converters[] = { // Definition
NULL, // XX -> YY
Convert_8_8_sign, /* 8 -> 8 sign */ // XX -> YY sign
NULL, //
NULL, // XX swapped -> YY
NULL, // XX swapped -> YY sign
NULL, //
// 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
Convert_8_16, /* 8 -> 16 */ static wxSoundStreamPcm::ConverterType s_converters[4][3][2] = {
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_8_8_sign /* 8 -> 8 sign */
NULL, },
{
Convert_16_8, /* 16 -> 8 */ NULL,
Convert_16_8_sign, /* 16 -> 8 sign */ NULL
Convert_16_swap_8, /* 16 swapped -> 8 */ },
Convert_16_swap_8_sign, /* 16 swapped -> 8 sign */ {
NULL, NULL,
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_8_16, /* 8 -> 16 */
Convert_16_sign_16_swap, /* 16 sign -> 16 swapped */ Convert_8_16_sign /* 8 -> 16 sign */
Convert_16_swap_16_sign_swap /* 16 swapped -> 16 sign swapped */ },
{
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 // This is the buffer size multiplier. It gives the needed size of the output size.
#define CONVERT_SIGN 1 static float s_converters_multip[] = {1, 2, 0.5, 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
// //
// TODO: Read() and Write() aren't really safe. If you give it a buffer which // 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) wxSoundStream& wxSoundStreamPcm::Read(void *buffer, wxUint32 len)
{ {
wxUint32 real_len; wxUint32 in_bufsize;
char *tmp_buf;
if (!m_function_in) { // We must have a multiple of 2
m_sndio->Read(buffer, len); len &= 0x01;
m_lastcount = m_sndio->GetLastAccess();
m_snderror = m_sndio->GetError(); if (!m_function_in) {
m_sndio->Read(buffer, len);
m_lastcount = m_sndio->GetLastAccess();
m_snderror = m_sndio->GetError();
return *this;
}
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; return *this;
}
real_len = (m_16_to_8) ? len / 2 : len;
tmp_buf = new char[real_len];
m_sndio->Read(tmp_buf, real_len);
m_lastcount = m_sndio->GetLastAccess();
m_snderror = m_sndio->GetError();
if (m_snderror != wxSOUND_NOERR)
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) wxSoundStream& wxSoundStreamPcm::Write(const void *buffer, wxUint32 len)
{ {
char *tmp_buf; wxUint32 out_bufsize;
wxUint32 len2;
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) out_bufsize = GetWriteSize(len);
return m_sndio->Write(buffer, 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(buffer, m_prebuffer, len);
m_function_out((const char *)buffer, tmp_buf, len2); m_sndio->Write(m_prebuffer, out_bufsize);
m_sndio->Write(tmp_buf, len); m_snderror = m_sndio->GetError();
delete[] tmp_buf; 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_lastcount = (wxUint32)(m_sndio->GetLastAccess() / m_multiplier_out);
(m_sndio->GetLastAccess() * 2) : m_sndio->GetLastAccess();
return *this; return *this;
} }
bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase& format) bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase& format)
{ {
wxSoundFormatBase *new_format; wxSoundFormatBase *new_format;
wxSoundFormatPcm *pcm_format, *pcm_format2; wxSoundFormatPcm *pcm_format, *pcm_format2;
ConverterType *current_table_out, *current_table_in;
int index; if (m_sndio->SetSoundFormat(format)) {
bool change_sign; m_function_out = NULL;
m_function_in = NULL;
if (m_sndio->SetSoundFormat(format)) { return TRUE;
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];
} }
} else if (pcm_format->GetBPS() == 16) { if (format.GetType() != wxSOUND_PCM) {
current_table_out = &s_converters[CONVERT_BASE_16_16]; m_snderror = wxSOUND_INVFRMT;
current_table_in = &s_converters[CONVERT_BASE_16_16]; return FALSE;
} else { }
current_table_out = &s_converters[CONVERT_BASE_8_8]; if (m_sndformat)
current_table_in = &s_converters[CONVERT_BASE_8_8]; delete m_sndformat;
}
new_format = m_sndio->GetSoundFormat().Clone();
pcm_format = (wxSoundFormatPcm *)&format;
pcm_format2 = (wxSoundFormatPcm *)new_format;
change_sign = (pcm_format2->Signed() != pcm_format->Signed()); #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 #define MY_ORDER wxBYTE_ORDER
#if wxBYTE_ORDER == wxLITTLE_ENDIAN #if wxBYTE_ORDER == wxLITTLE_ENDIAN
@@ -189,36 +299,91 @@ bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase& format)
#define OTHER_ORDER wxLITTLE_ENDIAN #define OTHER_ORDER wxLITTLE_ENDIAN
#endif #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 && m_function_out = s_converters[table_no*2+table_no2][i_swap][i_sign];
pcm_format2->GetOrder() == OTHER_ORDER && change_sign) m_function_in = s_converters[table_no2*2+table_no][i_swap][i_sign];
index = CONVERT_SWAP_SIGN_SWAP; 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 && if (m_prebuffer)
pcm_format2->GetOrder() == MY_ORDER && change_sign) delete[] m_prebuffer;
index = CONVERT_SWAP_SIGN;
else if (pcm_format->GetOrder() == MY_ORDER && // We try to minimize the need of dynamic memory allocation by preallocating a buffer. But
pcm_format->GetOrder() == OTHER_ORDER && change_sign) // to be sure it will be efficient we minimize the best size.
index = CONVERT_SIGN_SWAP; 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;
else if (change_sign) SetSoundFormatReturn = m_sndio->SetSoundFormat(*new_format);
index = CONVERT_SIGN; wxASSERT( SetSoundFormatReturn );
else if (!change_sign && m_sndformat = new_format;
pcm_format->GetOrder() != pcm_format2->GetOrder()) return TRUE;
index = CONVERT_SWAP;
else
index = CONVERT_BPS;
m_function_out = current_table_out[index];
m_function_in = current_table_in[index];
m_sndio->SetSoundFormat(*new_format);
m_sndformat = new_format;
return TRUE;
} }
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);
}
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.
#if 0
#define FLOATBITS 16
#define INTBITS 16
#define FLOATMASK 0xffff
#define INTMASK 0xffff0000
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

View File

@@ -20,21 +20,34 @@
// //
class wxSoundStreamPcm: public wxSoundStreamCodec { class wxSoundStreamPcm: public wxSoundStreamCodec {
public: public:
typedef void (*ConverterType)(const char *buf_in, char *buf_out, wxUint32 len); 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;
wxSoundStreamPcm(wxSoundStream& sndio); protected:
~wxSoundStreamPcm(); ConverterType m_function_out, m_function_in;
wxSoundStream& Read(void *buffer, wxUint32 len); // Static temporary buffer
wxSoundStream& Write(const void *buffer, wxUint32 len); char *m_prebuffer;
wxUint32 m_prebuffer_size;
bool SetSoundFormat(const wxSoundFormatBase& format); // Estimated best size to fit into the static buffer
wxUint32 m_best_size;
protected: // Multiplier for IO buffer size
ConverterType m_function_out, m_function_in; float m_multiplier_in, m_multiplier_out;
bool m_16_to_8;
}; };
#endif #endif

View File

@@ -59,7 +59,7 @@ wxSoundStreamESD::wxSoundStreamESD(const wxString& hostname)
SetSoundFormat(pcm_default); SetSoundFormat(pcm_default);
// Initialize some variable // Initialize some variable
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
m_esd_stop = TRUE; m_esd_stop = TRUE;
m_q_filled = TRUE; m_q_filled = TRUE;
m_fd_output= -1; 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); m_lastcount = (wxUint32)ret = read(m_fd_input, buffer, len);
if (ret < 0) if (ret < 0)
m_snderror = wxSOUND_IOERR; m_snderror = wxSOUND_IOERROR;
else else
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
return *this; return *this;
} }
@@ -101,9 +101,9 @@ wxSoundStream& wxSoundStreamESD::Write(const void *buffer, wxUint32 len)
m_lastcount = (wxUint32)ret = write(m_fd_output, buffer, len); m_lastcount = (wxUint32)ret = write(m_fd_output, buffer, len);
if (ret < 0) if (ret < 0)
m_snderror = wxSOUND_IOERR; m_snderror = wxSOUND_IOERROR;
else else
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
m_q_filled = TRUE; m_q_filled = TRUE;
@@ -133,7 +133,7 @@ bool wxSoundStreamESD::SetSoundFormat(const wxSoundFormatBase& format)
m_sndformat = format.Clone(); m_sndformat = format.Clone();
if (!m_sndformat) { if (!m_sndformat) {
m_snderror = wxSOUND_MEMERR; m_snderror = wxSOUND_MEMERROR;
return FALSE; return FALSE;
} }
pcm_format = (wxSoundFormatPcm *)m_sndformat; pcm_format = (wxSoundFormatPcm *)m_sndformat;
@@ -141,7 +141,7 @@ bool wxSoundStreamESD::SetSoundFormat(const wxSoundFormatBase& format)
// Detect the best format // Detect the best format
DetectBest(pcm_format); DetectBest(pcm_format);
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
if (*pcm_format != format) { if (*pcm_format != format) {
m_snderror = wxSOUND_NOEXACT; m_snderror = wxSOUND_NOEXACT;
return FALSE; return FALSE;
@@ -256,7 +256,7 @@ void wxSoundStreamESD::DetectBest(wxSoundFormatPcm *pcm)
{ {
wxSoundFormatPcm best_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.SetSampleRate(pcm->GetSampleRate());
best_pcm.SetChannels(pcm->GetChannels()); best_pcm.SetChannels(pcm->GetChannels());

View File

@@ -325,7 +325,7 @@ wxString wxSoundFileStream::GetCodecName() const
wxUint32 wxSoundFileStream::GetLength() 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 (PrepareToPlay()) ? m_length : 0;
return m_length; return m_length;
@@ -333,7 +333,7 @@ wxUint32 wxSoundFileStream::GetLength()
wxUint32 wxSoundFileStream::GetPosition() wxUint32 wxSoundFileStream::GetPosition()
{ {
if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERR) if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERROR)
PrepareToPlay(); PrepareToPlay();
return m_length-m_bytes_left; return m_length-m_bytes_left;
@@ -341,7 +341,7 @@ wxUint32 wxSoundFileStream::GetPosition()
wxUint32 wxSoundFileStream::SetPosition(wxUint32 new_position) 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(); PrepareToPlay();
if (!m_prepared) if (!m_prepared)

View File

@@ -21,7 +21,7 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
wxSoundFormatG72X::wxSoundFormatG72X() wxSoundFormatG72X::wxSoundFormatG72X()
: m_srate(22050) : m_srate(22050)
{ {
} }
@@ -31,77 +31,77 @@ wxSoundFormatG72X::~wxSoundFormatG72X()
void wxSoundFormatG72X::SetSampleRate(wxUint32 srate) void wxSoundFormatG72X::SetSampleRate(wxUint32 srate)
{ {
m_srate = srate; m_srate = srate;
} }
wxUint32 wxSoundFormatG72X::GetSampleRate() const wxUint32 wxSoundFormatG72X::GetSampleRate() const
{ {
return m_srate; return m_srate;
} }
void wxSoundFormatG72X::SetG72XType(wxSoundG72XType type) void wxSoundFormatG72X::SetG72XType(wxSoundG72XType type)
{ {
m_g72x_type = type; m_g72x_type = type;
} }
wxSoundFormatBase *wxSoundFormatG72X::Clone() const wxSoundFormatBase *wxSoundFormatG72X::Clone() const
{ {
wxSoundFormatG72X *g72x = new wxSoundFormatG72X(); wxSoundFormatG72X *g72x = new wxSoundFormatG72X();
g72x->m_srate = m_srate; g72x->m_srate = m_srate;
g72x->m_g72x_type = m_g72x_type; g72x->m_g72x_type = m_g72x_type;
return g72x; return g72x;
} }
wxUint32 wxSoundFormatG72X::GetTimeFromBytes(wxUint32 bytes) const wxUint32 wxSoundFormatG72X::GetTimeFromBytes(wxUint32 bytes) const
{ {
int n_bits; int n_bits;
switch (m_g72x_type) { switch (m_g72x_type) {
case wxSOUND_G721: case wxSOUND_G721:
n_bits = 4; n_bits = 4;
break; break;
case wxSOUND_G723_24: case wxSOUND_G723_24:
n_bits = 3; n_bits = 3;
break; break;
case wxSOUND_G723_40: case wxSOUND_G723_40:
n_bits = 5; n_bits = 5;
break; break;
default: default:
n_bits = 0; n_bits = 0;
break; break;
} }
return (wxUint32)((bytes / m_srate) * ((float)n_bits / 8)); return (wxUint32)((bytes / m_srate) * n_bits) / 8;
} }
wxUint32 wxSoundFormatG72X::GetBytesFromTime(wxUint32 time) const wxUint32 wxSoundFormatG72X::GetBytesFromTime(wxUint32 time) const
{ {
int n_bits; int n_bits;
switch (m_g72x_type) { switch (m_g72x_type) {
case wxSOUND_G721: case wxSOUND_G721:
n_bits = 4; n_bits = 4;
break; break;
case wxSOUND_G723_24: case wxSOUND_G723_24:
n_bits = 3; n_bits = 3;
break; break;
case wxSOUND_G723_40: case wxSOUND_G723_40:
n_bits = 5; n_bits = 5;
break; break;
default: default:
n_bits = 0; n_bits = 0;
} }
return (wxUint32)(time * (m_srate * ((float)n_bits / 8))); return (wxUint32)((time * m_srate * n_bits) / 8);
} }
bool wxSoundFormatG72X::operator !=(const wxSoundFormatBase& frmt2) const bool wxSoundFormatG72X::operator !=(const wxSoundFormatBase& frmt2) const
{ {
wxSoundFormatG72X *g72x = (wxSoundFormatG72X *)&frmt2; wxSoundFormatG72X *g72x = (wxSoundFormatG72X *)&frmt2;
if (frmt2.GetType() != wxSOUND_G72X) if (frmt2.GetType() != wxSOUND_G72X)
return TRUE; return TRUE;
return (g72x->m_srate != m_srate || g72x->m_g72x_type != m_g72x_type); 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) wxSoundStreamG72X::wxSoundStreamG72X(wxSoundStream& sndio)
: wxSoundStreamCodec(sndio) : wxSoundStreamCodec(sndio)
{ {
// PCM converter // PCM converter
m_router = new wxSoundRouterStream(sndio); m_router = new wxSoundRouterStream(sndio);
m_state = new g72state; m_state = new g72state;
g72x_init_state(m_state); g72x_init_state(m_state);
} }
wxSoundStreamG72X::~wxSoundStreamG72X() wxSoundStreamG72X::~wxSoundStreamG72X()
{ {
delete m_router; delete m_router;
} }
wxSoundStream& wxSoundStreamG72X::Read(void *buffer, wxUint32 len) wxSoundStream& wxSoundStreamG72X::Read(void *buffer, wxUint32 len)
{ {
wxUint16 *old_linear; wxUint16 *old_linear;
register wxUint16 *linear_buffer; register wxUint16 *linear_buffer;
register wxUint32 real_len; register wxUint32 real_len;
register wxUint32 countdown = len; register wxUint32 countdown = len;
real_len = (len * 8 / m_n_bits); real_len = (len * 8 / m_n_bits);
old_linear = linear_buffer = new wxUint16[real_len]; old_linear = linear_buffer = new wxUint16[real_len];
m_router->Read(linear_buffer, real_len); m_router->Read(linear_buffer, real_len);
real_len = (wxUint32)(m_router->GetLastAccess() * ((float)m_n_bits / 8)); real_len = (wxUint32)(m_router->GetLastAccess() * ((float)m_n_bits / 8));
if (!real_len) if (!real_len)
return *m_router; return *m_router;
m_io_buffer = (wxUint8 *)buffer; m_io_buffer = (wxUint8 *)buffer;
m_current_b_pos = 0; m_current_b_pos = 0;
while (countdown != 0) { while (countdown != 0) {
PutBits(m_coder(*linear_buffer++, AUDIO_ENCODING_LINEAR, m_state)); PutBits(m_coder(*linear_buffer++, AUDIO_ENCODING_LINEAR, m_state));
countdown--; countdown--;
} }
m_lastcount = real_len; m_lastcount = real_len;
m_snderror = m_router->GetError(); m_snderror = m_router->GetError();
delete[] old_linear; delete[] old_linear;
return *this; return *this;
} }
wxSoundStream& wxSoundStreamG72X::Write(const void *buffer, wxUint32 len) wxSoundStream& wxSoundStreamG72X::Write(const void *buffer, wxUint32 len)
{ {
wxUint16 *old_linear; wxUint16 *old_linear;
register wxUint16 *linear_buffer; register wxUint16 *linear_buffer;
register wxUint32 countdown = len; register wxUint32 countdown = len;
register wxUint32 real_len; register wxUint32 real_len;
// Compute the real length (PCM format) to sendt to the sound card // Compute the real length (PCM format) to sendt to the sound card
real_len = (len * m_n_bits / 8); real_len = (len * m_n_bits / 8);
// Allocate a temporary buffer // Allocate a temporary buffer
old_linear = linear_buffer = new wxUint16[real_len]; old_linear = linear_buffer = new wxUint16[real_len];
// Bad, we override the const // Bad, we override the const
m_io_buffer = (wxUint8 *)buffer; m_io_buffer = (wxUint8 *)buffer;
m_current_b_pos = 0; m_current_b_pos = 0;
// Decode the datas // Decode the datas
while (countdown != 0) { while (countdown != 0) {
*linear_buffer++ = m_decoder(GetBits(), AUDIO_ENCODING_LINEAR, m_state); *linear_buffer++ = m_decoder(GetBits(), AUDIO_ENCODING_LINEAR, m_state);
countdown--; countdown--;
} }
m_lastcount = len; m_lastcount = len;
// Send them to the sound card // Send them to the sound card
m_router->Write(old_linear, real_len); m_router->Write(old_linear, real_len);
// Destroy the temporary buffer // Destroy the temporary buffer
delete[] old_linear; delete[] old_linear;
return *m_router; return *m_router;
} }
bool wxSoundStreamG72X::SetSoundFormat(const wxSoundFormatBase& format) bool wxSoundStreamG72X::SetSoundFormat(const wxSoundFormatBase& format)
{ {
if (format.GetType() != wxSOUND_G72X) { if (format.GetType() != wxSOUND_G72X) {
m_snderror = wxSOUND_INVFRMT; m_snderror = wxSOUND_INVFRMT;
return FALSE; 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);
wxSoundFormatPcm pcm; // Look for the correct codec to use and set its bit width
wxSoundFormatG72X *g72x; 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;
}
wxSoundStreamCodec::SetSoundFormat(format); // Let the router finish the work
m_router->SetSoundFormat(pcm);
g72x = (wxSoundFormatG72X *)m_sndformat;
return TRUE;
// 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;
} }
#define BYTE_SIZE 8 #define BYTE_SIZE 8
wxUint8 wxSoundStreamG72X::GetBits() wxUint8 wxSoundStreamG72X::GetBits()
{ {
register wxUint8 bits; register wxUint8 bits;
if (m_current_b_pos < m_n_bits) { // We have two bytes to compute
register wxUint8 b_left; if (m_current_b_pos < m_n_bits) {
register wxUint8 b_left;
// TRANSLATE the mask
m_current_mask >>= m_current_b_pos; // 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); // 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; // GEN: 1. n times .1000
m_current_mask = ((1 << m_n_bits) - 1) << b_left; 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++; // GET the next byte
m_current_byte = *m_io_buffer++;
register wxUint8 tmp_mask;
register wxUint8 tmp_mask;
// COMPUTE a new temporary mask to get the last bits
b_left = m_n_bits - b_left; // COMPUTE a new temporary mask to get the last bits
tmp_mask = (1 << b_left) - 1; b_left = m_n_bits - b_left;
// TRANSLATE the old mask to get ready for the next time tmp_mask = (1 << b_left) - 1;
m_current_mask >>= b_left; // 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; // COMPUTE the new bit position
m_current_b_pos = b_left; b_left = BYTE_SIZE - b_left;
tmp_mask <<= b_left; m_current_b_pos = b_left;
tmp_mask <<= b_left;
// GET the last bits
bits |= (m_current_byte & tmp_mask) >> b_left; // GET the last bits
} else { bits |= (m_current_byte & tmp_mask) >> b_left;
m_current_mask >>= m_n_bits; } else {
m_current_b_pos -= m_n_bits; m_current_mask >>= m_n_bits;
bits = (m_current_byte & m_current_mask) >> m_current_b_pos; m_current_b_pos -= m_n_bits;
} bits = (m_current_byte & m_current_mask) >> m_current_b_pos;
return bits; }
return bits;
} }
void wxSoundStreamG72X::PutBits(wxUint8 bits) void wxSoundStreamG72X::PutBits(wxUint8 bits)
{ {
if (m_current_b_pos < m_n_bits) { if (m_current_b_pos < m_n_bits) {
register wxUint8 tmp_mask; register wxUint8 tmp_mask;
register wxUint8 diff; register wxUint8 diff;
diff = m_n_bits - m_current_b_pos; diff = m_n_bits - m_current_b_pos;
// Pack bits and put the byte in the buffer // Pack bits and put the byte in the buffer
m_current_byte |= bits >> diff; m_current_byte |= bits >> diff;
*m_io_buffer++ = m_current_byte; *m_io_buffer++ = m_current_byte;
// Gen a mask // Gen a mask
tmp_mask = ~((1 << diff) - 1); tmp_mask = ~((1 << diff) - 1);
m_current_b_pos = BYTE_SIZE - (m_n_bits - m_current_b_pos); m_current_b_pos = BYTE_SIZE - (m_n_bits - m_current_b_pos);
m_current_byte = (bits & (tmp_mask)) << m_current_b_pos; m_current_byte = (bits & (tmp_mask)) << m_current_b_pos;
} else { } else {
m_current_b_pos -= m_n_bits; m_current_b_pos -= m_n_bits;
bits <<= m_current_b_pos; bits <<= m_current_b_pos;
m_current_byte |= bits; m_current_byte |= bits;
} }
} }

View File

@@ -41,7 +41,7 @@ wxSoundStreamOSS::wxSoundStreamOSS(const wxString& dev_name)
ioctl(m_fd, SNDCTL_DSP_GETBLKSIZE, &m_bufsize); ioctl(m_fd, SNDCTL_DSP_GETBLKSIZE, &m_bufsize);
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
close(m_fd); close(m_fd);
@@ -68,9 +68,9 @@ wxSoundStream& wxSoundStreamOSS::Read(void *buffer, wxUint32 len)
m_q_filled = TRUE; m_q_filled = TRUE;
if (ret < 0) if (ret < 0)
m_snderror = wxSOUND_IOERR; m_snderror = wxSOUND_IOERROR;
else else
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
return *this; return *this;
} }
@@ -83,9 +83,9 @@ wxSoundStream& wxSoundStreamOSS::Write(const void *buffer, wxUint32 len)
m_q_filled = TRUE; m_q_filled = TRUE;
if (ret < 0) if (ret < 0)
m_snderror = wxSOUND_IOERR; m_snderror = wxSOUND_IOERROR;
else else
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
return *this; return *this;
} }
@@ -110,7 +110,7 @@ bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase& format)
m_sndformat = format.Clone(); m_sndformat = format.Clone();
if (!m_sndformat) { if (!m_sndformat) {
m_snderror = wxSOUND_MEMERR; m_snderror = wxSOUND_MEMERROR;
return FALSE; return FALSE;
} }
pcm_format = (wxSoundFormatPcm *)m_sndformat; pcm_format = (wxSoundFormatPcm *)m_sndformat;
@@ -129,7 +129,7 @@ bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase& format)
ioctl(m_fd, SNDCTL_DSP_CHANNELS, &tmp); ioctl(m_fd, SNDCTL_DSP_CHANNELS, &tmp);
pcm_format->SetChannels(tmp); pcm_format->SetChannels(tmp);
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
if (*pcm_format != format) { if (*pcm_format != format) {
m_snderror = wxSOUND_NOEXACT; m_snderror = wxSOUND_NOEXACT;
return FALSE; return FALSE;
@@ -229,44 +229,43 @@ void wxSoundStreamOSS::WakeUpEvt(int evt)
bool wxSoundStreamOSS::StartProduction(int evt) bool wxSoundStreamOSS::StartProduction(int evt)
{ {
wxSoundFormatBase *old_frmt; wxSoundFormatBase *old_frmt;
if (!m_oss_stop) if (!m_oss_stop)
StopProduction(); StopProduction();
old_frmt = m_sndformat->Clone(); old_frmt = m_sndformat->Clone();
if (!old_frmt) { if (!old_frmt) {
m_snderror = wxSOUND_MEMERR; m_snderror = wxSOUND_MEMERROR;
return FALSE; return FALSE;
} }
if (evt == wxSOUND_OUTPUT) if (evt == wxSOUND_OUTPUT)
m_fd = open(m_devname.mb_str(), O_WRONLY); m_fd = open(m_devname.mb_str(), O_WRONLY);
else if (evt == wxSOUND_INPUT) else if (evt == wxSOUND_INPUT)
m_fd = open(m_devname.mb_str(), O_RDONLY); m_fd = open(m_devname.mb_str(), O_RDONLY);
if (m_fd == -1) { if (m_fd == -1) {
m_snderror = wxSOUND_INVDEV; m_snderror = wxSOUND_INVDEV;
return FALSE; return FALSE;
} }
SetSoundFormat(*old_frmt); SetSoundFormat(*old_frmt);
delete old_frmt; delete old_frmt;
int trig;
if (evt == wxSOUND_OUTPUT) {
#ifdef __WXGTK__ #ifdef __WXGTK__
int trig; m_tag = gdk_input_add(m_fd, GDK_INPUT_WRITE, _wxSound_OSS_CBack, (gpointer)this);
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);
#endif #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); ioctl(m_fd, SNDCTL_DSP_SETTRIGGER, &trig);

View File

@@ -25,7 +25,7 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
wxSoundFormatUlaw::wxSoundFormatUlaw() wxSoundFormatUlaw::wxSoundFormatUlaw()
: m_srate(22050) : m_srate(22050), m_channels(1)
{ {
} }
@@ -35,40 +35,51 @@ wxSoundFormatUlaw::~wxSoundFormatUlaw()
void wxSoundFormatUlaw::SetSampleRate(wxUint32 srate) void wxSoundFormatUlaw::SetSampleRate(wxUint32 srate)
{ {
m_srate = srate; m_srate = srate;
} }
wxUint32 wxSoundFormatUlaw::GetSampleRate() const wxUint32 wxSoundFormatUlaw::GetSampleRate() const
{ {
return m_srate; return m_srate;
}
wxUint8 wxSoundFormatUlaw::GetChannels() const
{
return m_channels;
}
void wxSoundFormatUlaw::SetChannels(wxUint8 nchannels)
{
m_channels = nchannels;
} }
wxSoundFormatBase *wxSoundFormatUlaw::Clone() const wxSoundFormatBase *wxSoundFormatUlaw::Clone() const
{ {
wxSoundFormatUlaw *ulaw = new wxSoundFormatUlaw(); wxSoundFormatUlaw *ulaw = new wxSoundFormatUlaw();
ulaw->m_srate = m_srate; ulaw->m_srate = m_srate;
return ulaw; ulaw->m_channels = m_channels;
return ulaw;
} }
wxUint32 wxSoundFormatUlaw::GetTimeFromBytes(wxUint32 bytes) const wxUint32 wxSoundFormatUlaw::GetTimeFromBytes(wxUint32 bytes) const
{ {
return (bytes / m_srate); return (bytes / m_srate);
} }
wxUint32 wxSoundFormatUlaw::GetBytesFromTime(wxUint32 time) const wxUint32 wxSoundFormatUlaw::GetBytesFromTime(wxUint32 time) const
{ {
return time * m_srate; return time * m_srate;
} }
bool wxSoundFormatUlaw::operator !=(const wxSoundFormatBase& frmt2) const bool wxSoundFormatUlaw::operator !=(const wxSoundFormatBase& frmt2) const
{ {
wxSoundFormatUlaw *ulaw = (wxSoundFormatUlaw *)&frmt2; wxSoundFormatUlaw *ulaw = (wxSoundFormatUlaw *)&frmt2;
if (frmt2.GetType() != wxSOUND_ULAW) if (frmt2.GetType() != wxSOUND_ULAW)
return TRUE; return TRUE;
return (ulaw->m_srate != m_srate); return (ulaw->m_srate != m_srate);
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -88,58 +99,82 @@ wxSoundStreamUlaw::~wxSoundStreamUlaw()
wxSoundStream& wxSoundStreamUlaw::Read(void *buffer, wxUint32 len) wxSoundStream& wxSoundStreamUlaw::Read(void *buffer, wxUint32 len)
{ {
// TODO wxUint16 *old_linear;
return *this; 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) wxSoundStream& wxSoundStreamUlaw::Write(const void *buffer, wxUint32 len)
{ {
wxUint16 *old_linear; wxUint16 *old_linear;
register wxUint16 *linear_buffer; register wxUint16 *linear_buffer;
register const wxUint8 *ulaw_buffer; register const wxUint8 *ulaw_buffer;
register wxUint32 countdown = len; register wxUint32 countdown = len;
old_linear = linear_buffer = new wxUint16[len*2]; old_linear = linear_buffer = new wxUint16[len*2];
ulaw_buffer = (const wxUint8 *)buffer; ulaw_buffer = (const wxUint8 *)buffer;
while (countdown != 0) { while (countdown > 0) {
*linear_buffer++ = ulaw2linear(*ulaw_buffer++); *linear_buffer++ = ulaw2linear(*ulaw_buffer++);
countdown--; countdown--;
} }
m_router->Write(old_linear, len * 2); m_router->Write(old_linear, len * 2);
delete[] old_linear; delete[] old_linear;
return *m_router; return *m_router;
} }
wxUint32 wxSoundStreamUlaw::GetBestSize() const wxUint32 wxSoundStreamUlaw::GetBestSize() const
{ {
return m_sndio->GetBestSize() / 2; return m_sndio->GetBestSize() / 2;
} }
bool wxSoundStreamUlaw::SetSoundFormat(const wxSoundFormatBase& format) bool wxSoundStreamUlaw::SetSoundFormat(const wxSoundFormatBase& format)
{ {
if (format.GetType() != wxSOUND_ULAW) { if (format.GetType() != wxSOUND_ULAW) {
m_snderror = wxSOUND_INVFRMT; m_snderror = wxSOUND_INVFRMT;
return FALSE; return FALSE;
} }
wxSoundFormatPcm pcm; // As the codec only support 16 bits, Mono we must use a wxSoundRouter to filter the data and
wxSoundFormatUlaw *ulaw; // to translate them to a format supported by the sound card.
wxSoundStreamCodec::SetSoundFormat(format); wxSoundFormatPcm pcm;
wxSoundFormatUlaw *ulaw;
ulaw = (wxSoundFormatUlaw *)m_sndformat;
wxSoundStreamCodec::SetSoundFormat(format);
pcm.SetSampleRate(ulaw->GetSampleRate());
pcm.SetBPS(16); ulaw = (wxSoundFormatUlaw *)m_sndformat;
pcm.SetChannels(1);
pcm.Signed(TRUE); pcm.SetSampleRate(ulaw->GetSampleRate());
pcm.SetOrder(wxBYTE_ORDER); pcm.SetBPS(16);
pcm.SetChannels(ulaw->GetChannels());
m_router->SetSoundFormat(pcm); pcm.Signed(TRUE);
pcm.SetOrder(wxBYTE_ORDER);
return TRUE;
m_router->SetSoundFormat(pcm);
return TRUE;
} }

View File

@@ -12,6 +12,8 @@
#pragma interface "sndulaw.h" #pragma interface "sndulaw.h"
#endif #endif
#include "wx/defs.h"
#include "sndcodec.h" #include "sndcodec.h"
#include "sndbase.h" #include "sndbase.h"
@@ -19,26 +21,27 @@
// ULAW format // ULAW format
// //
class WXDLLEXPORT wxSoundFormatUlaw: public wxSoundFormatBase { class WXDLLEXPORT wxSoundFormatUlaw: public wxSoundFormatBase {
public: public:
wxSoundFormatUlaw(); wxSoundFormatUlaw();
~wxSoundFormatUlaw(); ~wxSoundFormatUlaw();
void SetSampleRate(wxUint32 srate); void SetSampleRate(wxUint32 srate);
wxUint32 GetSampleRate() const; wxUint32 GetSampleRate() const;
void SetChannels(wxUint8 channels); void SetChannels(wxUint8 channels);
wxUint8 GetChannels() const; wxUint8 GetChannels() const;
wxSoundFormatType GetType() const { return wxSOUND_ULAW; } wxSoundFormatType GetType() const { return wxSOUND_ULAW; }
wxSoundFormatBase *Clone() const; wxSoundFormatBase *Clone() const;
wxUint32 GetTimeFromBytes(wxUint32 bytes) const; wxUint32 GetTimeFromBytes(wxUint32 bytes) const;
wxUint32 GetBytesFromTime(wxUint32 time) const; wxUint32 GetBytesFromTime(wxUint32 time) const;
bool operator !=(const wxSoundFormatBase& frmt2) const; bool operator !=(const wxSoundFormatBase& frmt2) const;
protected: protected:
wxUint32 m_srate; wxUint32 m_srate;
wxUint8 m_channels;
}; };
// //
@@ -47,19 +50,19 @@ class WXDLLEXPORT wxSoundFormatUlaw: public wxSoundFormatBase {
class WXDLLEXPORT wxSoundRouterStream; class WXDLLEXPORT wxSoundRouterStream;
class WXDLLEXPORT wxSoundStreamUlaw: public wxSoundStreamCodec { class WXDLLEXPORT wxSoundStreamUlaw: public wxSoundStreamCodec {
public: public:
wxSoundStreamUlaw(wxSoundStream& sndio); wxSoundStreamUlaw(wxSoundStream& sndio);
~wxSoundStreamUlaw(); ~wxSoundStreamUlaw();
wxSoundStream& Read(void *buffer, wxUint32 len); wxSoundStream& Read(void *buffer, wxUint32 len);
wxSoundStream& Write(const void *buffer, wxUint32 len); wxSoundStream& Write(const void *buffer, wxUint32 len);
bool SetSoundFormat(const wxSoundFormatBase& format); bool SetSoundFormat(const wxSoundFormatBase& format);
wxUint32 GetBestSize() const; wxUint32 GetBestSize() const;
protected: protected:
wxSoundRouterStream *m_router; wxSoundRouterStream *m_router;
}; };
#endif #endif

View File

@@ -60,7 +60,7 @@ wxString wxSoundWave::GetCodecName() const
bool wxSoundWave::CanRead() bool wxSoundWave::CanRead()
{ {
wxUint32 len, signature1, signature2; wxUint32 len, signature1, signature2;
m_snderror = wxSOUND_NOERR; m_snderror = wxSOUND_NOERROR;
// Test the main signatures: // Test the main signatures:
// "RIFF" // "RIFF"

View File

@@ -651,6 +651,7 @@ void wxSoundStreamWin::NotifyDoneBuffer(wxUint32 dev_handle, int flag)
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
bool wxSoundStreamWin::SetSoundFormat(wxSoundFormatBase& base) bool wxSoundStreamWin::SetSoundFormat(wxSoundFormatBase& base)
{ {
// TODO: detect best format
return wxSoundStream::SetSoundFormat(base); return wxSoundStream::SetSoundFormat(base);
} }

View File

@@ -1,4 +1,4 @@
//////////////////////////////////////////////////////////////////////////////// // -----------------------------------------------------------------------------
// Name: vidwin.h // Name: vidwin.h
// Purpose: wxMMedia // Purpose: wxMMedia
// Author: Guilhem Lavaux // Author: Guilhem Lavaux
@@ -6,7 +6,7 @@
// Updated: // Updated:
// Copyright: (C) 1998, 1999, 2000 Guilhem Lavaux // Copyright: (C) 1998, 1999, 2000 Guilhem Lavaux
// License: wxWindows license // License: wxWindows license
//////////////////////////////////////////////////////////////////////////////// // -----------------------------------------------------------------------------
#ifdef __GNUG__ #ifdef __GNUG__
#pragma implementation "vidwin.h" #pragma implementation "vidwin.h"
@@ -45,6 +45,7 @@ wxVideoWindows::wxVideoWindows(wxInputStream& str)
m_filename = wxGetTempFileName("wxvid"); m_filename = wxGetTempFileName("wxvid");
m_paused = FALSE; m_paused = FALSE;
m_stopped = TRUE; m_stopped = TRUE;
m_frameRate = 1.0;
wxFileOutputStream temp_file(m_filename); wxFileOutputStream temp_file(m_filename);
temp_file << str; temp_file << str;
@@ -60,6 +61,7 @@ wxVideoWindows::wxVideoWindows(const wxString& filename)
m_filename = filename; m_filename = filename;
m_paused = FALSE; m_paused = FALSE;
m_stopped = TRUE; m_stopped = TRUE;
m_frameRate = 1.0;
OpenFile(); OpenFile();
} }
@@ -73,17 +75,41 @@ wxVideoWindows::~wxVideoWindows(void)
void wxVideoWindows::OpenFile() 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; DWORD ret;
open_struct.lpstrDeviceType = "avivideo"; openStruct.lpstrDeviceType = "avivideo";
open_struct.lpstrElementName = (LPSTR)(m_filename.mb_str()); openStruct.lpstrElementName = (LPSTR)(m_filename.mb_str());
open_struct.hWndParent = 0; openStruct.hWndParent = 0;
ret = mciSendCommand(0, MCI_OPEN, ret = mciSendCommand(0, MCI_OPEN,
MCI_OPEN_ELEMENT|MCI_DGV_OPEN_PARENT|MCI_OPEN_TYPE|MCI_DGV_OPEN_32BIT, MCI_OPEN_ELEMENT|MCI_DGV_OPEN_PARENT|MCI_OPEN_TYPE|MCI_DGV_OPEN_32BIT,
(DWORD)(LPVOID)&open_struct); (DWORD)(LPVOID)&openStruct);
m_internal->m_dev_id = open_struct.wDeviceID; 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() bool wxVideoWindows::Pause()
@@ -91,7 +117,7 @@ bool wxVideoWindows::Pause()
if (m_paused || m_stopped) if (m_paused || m_stopped)
return TRUE; return TRUE;
m_paused = 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() bool wxVideoWindows::Resume()
@@ -114,7 +140,6 @@ bool wxVideoWindows::IsStopped() const
bool wxVideoWindows::GetSize(wxSize& size) const bool wxVideoWindows::GetSize(wxSize& size) const
{ {
// Two random numbers.
size.SetWidth(200); size.SetWidth(200);
size.SetHeight(200); size.SetHeight(200);
return TRUE; return TRUE;
@@ -169,16 +194,17 @@ bool wxVideoWindows::Stop()
if (m_stopped) if (m_stopped)
return FALSE; return FALSE;
m_stopped = TRUE; 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; return FALSE;
seekStruct.dwCallback = 0; seekStruct.dwCallback = 0;
seekStruct.dwTo = 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 // 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 wxString wxVideoWindows::GetMovieCodec() const
{ {
@@ -202,12 +228,12 @@ wxUint8 wxVideoWindows::GetChannels() const
wxUint8 wxVideoWindows::GetBPS() const wxUint8 wxVideoWindows::GetBPS() const
{ {
return 8; return m_bps;
} }
double wxVideoWindows::GetFrameRate() const double wxVideoWindows::GetFrameRate() const
{ {
return 1.0; return m_frameRate;
} }
wxUint32 wxVideoWindows::GetNbFrames() const wxUint32 wxVideoWindows::GetNbFrames() const

View File

@@ -59,6 +59,8 @@ protected:
struct VIDW_Internal *m_internal; struct VIDW_Internal *m_internal;
bool m_paused, m_stopped, m_remove_file; bool m_paused, m_stopped, m_remove_file;
wxString m_filename; wxString m_filename;
double m_frameRate;
wxUint8 m_bps;
void OpenFile(); void OpenFile();
public: public: