#include "wx/defs.h"
#include "wx/object.h"
#include "wx/event.h"
+#include "wx/stream.h"
// Process Event handling
class WXDLLEXPORT wxProcessEvent : public wxEvent
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);
// 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&);
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)
{
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;
+}
#include "wx/log.h"
#ifdef __WIN32__
+ #include "wx/stream.h"
#include "wx/process.h"
#endif
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
// ============================================================================
// only reached for space not inside quotes
break;
}
-
wxString commandArgs = pc;
wxWindow *winTop = wxTheApp->GetTopWindow();
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;
(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)
&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 )
{
#include "wx/process.h"
#include "wx/thread.h"
+#include "wx/stream.h"
+
#if wxUSE_GUI
#include "wx/unix/execute.h"
#endif
#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))
}
#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();
#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;
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
}
}
+ // 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);
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
}
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
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"),
// 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;
// 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
// ---------------------------------------------------------------------------
-// Name: sndsnd.cpp
+// Name: cdbase.cpp
// Purpose: wxMMedia
// Author: Guilhem Lavaux
// Created: 1997
-#include <stdio.h>
-
#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; \
} \
}
+// 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))
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))
m_snderror = wxSOUND_INVSTRM;
return FALSE;
}
+ m_snderror = wxSOUND_NOERROR;
data.BigEndianOrdered(TRUE);
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);
if (!SetSoundFormat(sndformat))
return FALSE;
+ // We pass all data left
m_input->SeekI(len-18, wxFromCurrent);
break;
}
// 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;
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);
// 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;
// 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;
// - 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;
// - cdata: User callback data
// ---------------------
typedef void (*wxSoundCallback)(wxSoundStream *stream, int evt,
- char *cdata);
+ void *cdata);
//
// Base class for sound format specification
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.
wxSoundStream *m_handler;
wxSoundCallback m_callback[2];
- char *m_cdata[2];
+ void *m_cdata[2];
protected:
// Handles event
#ifdef __GNUG__
#pragma implementation "sndcpcm.cpp"
#endif
-
#include <wx/wxprec.h>
+
+#ifndef WX_PRECOMP
+#include <wx/debug.h>
+#include <wx/log.h>
+#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
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
#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
//
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
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;
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;
}
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;
m_sndformat = format.Clone();
if (!m_sndformat) {
- m_snderror = wxSOUND_MEMERR;
+ m_snderror = wxSOUND_MEMERROR;
return FALSE;
}
pcm_format = (wxSoundFormatPcm *)m_sndformat;
// 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;
{
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());
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;
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;
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)
// --------------------------------------------------------------------------
wxSoundFormatG72X::wxSoundFormatG72X()
- : m_srate(22050)
+ : m_srate(22050)
{
}
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);
}
// --------------------------------------------------------------------------
// --------------------------------------------------------------------------
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;
+ }
}
ioctl(m_fd, SNDCTL_DSP_GETBLKSIZE, &m_bufsize);
- m_snderror = wxSOUND_NOERR;
+ m_snderror = wxSOUND_NOERROR;
close(m_fd);
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;
}
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;
}
m_sndformat = format.Clone();
if (!m_sndformat) {
- m_snderror = wxSOUND_MEMERR;
+ m_snderror = wxSOUND_MEMERROR;
return FALSE;
}
pcm_format = (wxSoundFormatPcm *)m_sndformat;
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;
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);
// --------------------------------------------------------------------------
wxSoundFormatUlaw::wxSoundFormatUlaw()
- : m_srate(22050)
+ : m_srate(22050), m_channels(1)
{
}
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);
}
// --------------------------------------------------------------------------
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;
}
#pragma interface "sndulaw.h"
#endif
+#include "wx/defs.h"
+
#include "sndcodec.h"
#include "sndbase.h"
// 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;
};
//
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
bool wxSoundWave::CanRead()
{
wxUint32 len, signature1, signature2;
- m_snderror = wxSOUND_NOERR;
+ m_snderror = wxSOUND_NOERROR;
// Test the main signatures:
// "RIFF"
// -------------------------------------------------------------------------
bool wxSoundStreamWin::SetSoundFormat(wxSoundFormatBase& base)
{
+ // TODO: detect best format
return wxSoundStream::SetSoundFormat(base);
}
-////////////////////////////////////////////////////////////////////////////////
+// -----------------------------------------------------------------------------
// Name: vidwin.h
// Purpose: wxMMedia
// Author: Guilhem Lavaux
// Updated:
// Copyright: (C) 1998, 1999, 2000 Guilhem Lavaux
// License: wxWindows license
-////////////////////////////////////////////////////////////////////////////////
+// -----------------------------------------------------------------------------
#ifdef __GNUG__
#pragma implementation "vidwin.h"
m_filename = wxGetTempFileName("wxvid");
m_paused = FALSE;
m_stopped = TRUE;
+ m_frameRate = 1.0;
wxFileOutputStream temp_file(m_filename);
temp_file << str;
m_filename = filename;
m_paused = FALSE;
m_stopped = TRUE;
+ m_frameRate = 1.0;
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;
- 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()
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()
bool wxVideoWindows::GetSize(wxSize& size) const
{
- // Two random numbers.
size.SetWidth(200);
size.SetHeight(200);
return TRUE;
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
{
wxUint8 wxVideoWindows::GetBPS() const
{
- return 8;
+ return m_bps;
}
double wxVideoWindows::GetFrameRate() const
{
- return 1.0;
+ return m_frameRate;
}
wxUint32 wxVideoWindows::GetNbFrames() const
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: