Removed all wxMMedia2 files
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@6462 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -1,4 +0,0 @@
|
||||
all:
|
||||
cd lib; make
|
||||
cd sample; make
|
||||
cd board; make
|
@@ -1,48 +0,0 @@
|
||||
--------------------------------------------------------------------------
|
||||
| wxMultimedia (c) 1998, 1999, 2000 Guilhem Lavaux
|
||||
| wxWindows license
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
This is the wxMultimedia package. It intends to be a portable way to access
|
||||
some multimedia component on variable system. For the moment, I implemented
|
||||
sound, video and CD access.
|
||||
|
||||
Sound features:
|
||||
* low level/OSS style access to the sound card. You can open/setup the
|
||||
parameters of the sound card then write/read directly to/from it.
|
||||
* mid level codecs: compressors and sound codec are supported. For the
|
||||
moment there is a support for G711/G721/G723 and MULAW formats (as well
|
||||
PCM).
|
||||
* high level format: WAV file format is supported in read/write and AIFF
|
||||
format in read only
|
||||
|
||||
|
||||
Sound bugs:
|
||||
* it seems there are still some bugs in the recording code on Windows
|
||||
on Cygwin B20.1 (to be verified)
|
||||
* wave files created with wxSoundWave have some problem with Windows Media
|
||||
Player (not windows recorder)
|
||||
|
||||
Video features:
|
||||
* high level video file playing: on Unix you can play (through xanim) video
|
||||
files directly into your application
|
||||
* MPEG video file to be supported through SMPEG as soon as I have some free
|
||||
time
|
||||
|
||||
Video bugs:
|
||||
* AVI file works on Windows
|
||||
|
||||
CD features:
|
||||
* standard access to the CDAUDIO interface
|
||||
|
||||
CD bugs:
|
||||
|
||||
----------------
|
||||
| INSTALLATION |
|
||||
----------------
|
||||
|
||||
You need to move the three files included in this directory:
|
||||
- utilsunx.cpp => src/unix
|
||||
- process.cpp => src/common
|
||||
- process.h => include/wx
|
||||
- utilsexc.cpp => src/msw
|
@@ -1,38 +0,0 @@
|
||||
#
|
||||
# File: makefile.unx
|
||||
# Author: Julian Smart
|
||||
# Created: 1998
|
||||
# Updated:
|
||||
# Copyright: (c) 1998 Julian Smart
|
||||
#
|
||||
# "%W% %G%"
|
||||
#
|
||||
# Makefile for minimal example (UNIX).
|
||||
|
||||
top_srcdir = @top_srcdir@
|
||||
top_builddir = ../../..
|
||||
program_dir = utils/wxMMedia2/board
|
||||
|
||||
PROGRAM=mmboard
|
||||
|
||||
OBJECTS=mmboard.o mmbman.o
|
||||
|
||||
EXTRA_CPPFLAGS= -I$(top_srcdir)/utils/wxMMedia2/lib
|
||||
|
||||
EXTRA_LIBS= ../lib/libwxmmedia2.a -lesd
|
||||
# the comment at the end of the next line is needed because otherwise autoconf
|
||||
# would remove this line completely - it contains a built-in hack to remove
|
||||
# any VPATH assignment not containing ':'
|
||||
VPATH = @PATH_IFS@$(top_srcdir)/utils/wxMMedia2/board # ':' for autoconf
|
||||
|
||||
include ../../../src/make.env
|
||||
|
||||
.SUFFIXES: .o .cpp .c
|
||||
|
||||
.cpp.o:
|
||||
$(CC) -c $(CPPFLAGS) $(EXTRA_CPPFLAGS) -o $@ $<
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
mmboard: $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) -o mmboard $(OBJECTS) $(EXTRA_LIBS) $(LDLIBS) $(top_builddir)/lib/@WX_TARGET_LIBRARY@
|
@@ -1,24 +0,0 @@
|
||||
/* XPM */
|
||||
static char * eject_xpm[] = {
|
||||
"15 16 5 1",
|
||||
" c None",
|
||||
". c #949594",
|
||||
"+ c #000000",
|
||||
"@ c #FFFFFF",
|
||||
"# c #8E8E8E",
|
||||
" . ",
|
||||
" .+@ ",
|
||||
" .+++@ ",
|
||||
" .+++++@ ",
|
||||
" .+++++++@ ",
|
||||
" .+++++++++@ ",
|
||||
" .+++++++++++@ ",
|
||||
".+############@",
|
||||
".@@@@@@@@@@@@@@",
|
||||
" ",
|
||||
"...............",
|
||||
".++++++++++++#@",
|
||||
".++++++++++++#@",
|
||||
".++++++++++++#@",
|
||||
".+############@",
|
||||
".@@@@@@@@@@@@@@"};
|
@@ -1,20 +0,0 @@
|
||||
#
|
||||
# File: makefile.vc
|
||||
# Author: Julian Smart
|
||||
# Created: 1999
|
||||
# Updated:
|
||||
# Copyright: (c) Julian Smart
|
||||
#
|
||||
# Makefile : Builds sample (VC++, WIN32)
|
||||
# Use FINAL=1 argument to nmake to build final version with no debug info.
|
||||
|
||||
# Set WXDIR for your system
|
||||
WXDIR = $(WXWIN)
|
||||
EXTRAINC= -I..\lib
|
||||
EXTRALIBS= $(WXDIR)\lib\mmedia2.lib
|
||||
|
||||
PROGRAM=mmboard
|
||||
OBJECTS = $(PROGRAM).obj mmbman.obj
|
||||
|
||||
!include $(WXDIR)\src\makeprog.vc
|
||||
|
@@ -1,512 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: mmbman.cpp
|
||||
// Purpose: Multimedia Board manager
|
||||
// Author: Guilhem Lavaux, <guilhem.lavaux@libertysurf.fr>
|
||||
// Modified by:
|
||||
// Created: 13/02/2000
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2000, Guilhem Lavaux
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "mmbman.cpp"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
// for all others, include the necessary headers (this file is usually all you
|
||||
// need because it includes almost all "standard" wxWindows headers
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
// Personal headers
|
||||
|
||||
#include "wx/stream.h"
|
||||
#include "wx/wfstream.h"
|
||||
|
||||
#include "sndbase.h"
|
||||
#include "sndfile.h"
|
||||
#include "sndwav.h"
|
||||
#include "sndaiff.h"
|
||||
#include "sndpcm.h"
|
||||
#include "sndulaw.h"
|
||||
|
||||
#ifdef __UNIX__
|
||||
#include "sndoss.h"
|
||||
#include "sndesd.h"
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include "sndwin.h"
|
||||
#endif
|
||||
|
||||
#include "vidbase.h"
|
||||
#ifdef __UNIX__
|
||||
#include "vidxanm.h"
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include "vidwin.h"
|
||||
#endif
|
||||
|
||||
#include "mmboard.h"
|
||||
#include "mmbman.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Private class definitions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
class MMBoardSoundFile: public MMBoardFile {
|
||||
public:
|
||||
MMBoardSoundFile(const wxString& filename);
|
||||
~MMBoardSoundFile();
|
||||
|
||||
bool NeedWindow();
|
||||
|
||||
void SetWindow(wxWindow *window);
|
||||
|
||||
void Play();
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Stop();
|
||||
|
||||
MMBoardTime GetPosition();
|
||||
MMBoardTime GetLength();
|
||||
void SetPosition(MMBoardTime btime);
|
||||
|
||||
bool IsStopped();
|
||||
bool IsPaused();
|
||||
|
||||
wxString GetStringType();
|
||||
wxString GetStringInformation();
|
||||
|
||||
protected:
|
||||
wxSoundFileStream *GetDecoder();
|
||||
|
||||
wxSoundStream *m_output_stream;
|
||||
wxInputStream *m_input_stream;
|
||||
wxSoundFileStream *m_file_stream;
|
||||
|
||||
MMBoardTime m_length;
|
||||
wxUint8 m_file_type;
|
||||
};
|
||||
|
||||
class MMBoardVideoFile: public MMBoardFile {
|
||||
public:
|
||||
MMBoardVideoFile(const wxString& filename);
|
||||
~MMBoardVideoFile();
|
||||
|
||||
bool NeedWindow();
|
||||
|
||||
void SetWindow(wxWindow *window);
|
||||
|
||||
void Play();
|
||||
void Pause();
|
||||
void Resume();
|
||||
void Stop();
|
||||
|
||||
MMBoardTime GetPosition();
|
||||
MMBoardTime GetLength();
|
||||
void SetPosition(MMBoardTime btime);
|
||||
|
||||
bool IsStopped();
|
||||
bool IsPaused();
|
||||
|
||||
wxString GetStringType();
|
||||
wxString GetStringInformation();
|
||||
|
||||
protected:
|
||||
wxWindow *m_output_window;
|
||||
wxVideoBaseDriver *m_video_driver;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Implementation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#define MMBoard_UNKNOWNTYPE 0
|
||||
#define MMBoard_WAVE 1
|
||||
#define MMBoard_AIFF 2
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MMBoardSoundFile
|
||||
|
||||
MMBoardSoundFile::MMBoardSoundFile(const wxString& filename)
|
||||
: MMBoardFile()
|
||||
{
|
||||
m_input_stream = new wxFileInputStream(filename);
|
||||
m_output_stream = MMBoardManager::OpenSoundStream();
|
||||
|
||||
m_file_stream = GetDecoder();
|
||||
|
||||
if (!m_file_stream) {
|
||||
SetError(MMBoard_UnknownFile);
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute length
|
||||
wxUint32 length, seconds;
|
||||
|
||||
length = m_file_stream->GetLength();
|
||||
seconds = m_file_stream->GetSoundFormat().GetTimeFromBytes(length);
|
||||
m_length.seconds = seconds % 60;
|
||||
m_length.minutes = (seconds / 60) % 60;
|
||||
m_length.hours = seconds / 3600;
|
||||
}
|
||||
|
||||
MMBoardSoundFile::~MMBoardSoundFile()
|
||||
{
|
||||
if (m_file_stream)
|
||||
delete m_file_stream;
|
||||
MMBoardManager::UnrefSoundStream(m_output_stream);
|
||||
delete m_input_stream;
|
||||
}
|
||||
|
||||
wxSoundFileStream *MMBoardSoundFile::GetDecoder()
|
||||
{
|
||||
wxSoundFileStream *f_stream;
|
||||
|
||||
// First, we try a Wave decoder
|
||||
f_stream = new wxSoundWave(*m_input_stream, *m_output_stream);
|
||||
m_file_type = MMBoard_WAVE;
|
||||
if (f_stream->CanRead())
|
||||
return f_stream;
|
||||
delete f_stream;
|
||||
|
||||
// Then, a AIFF decoder
|
||||
f_stream = new wxSoundAiff(*m_input_stream, *m_output_stream);
|
||||
m_file_type = MMBoard_AIFF;
|
||||
if (f_stream->CanRead())
|
||||
return f_stream;
|
||||
delete f_stream;
|
||||
|
||||
m_file_type = MMBoard_UNKNOWNTYPE;
|
||||
|
||||
// TODO: automate
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MMBoardTime MMBoardSoundFile::GetLength()
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
bool MMBoardSoundFile::IsStopped()
|
||||
{
|
||||
return m_file_stream->IsStopped();
|
||||
}
|
||||
|
||||
bool MMBoardSoundFile::IsPaused()
|
||||
{
|
||||
return m_file_stream->IsPaused();
|
||||
}
|
||||
|
||||
MMBoardTime MMBoardSoundFile::GetPosition()
|
||||
{
|
||||
wxUint32 length, seconds;
|
||||
MMBoardTime file_time;
|
||||
|
||||
file_time.seconds = file_time.minutes = file_time.hours = 0;
|
||||
if (m_file_stream->IsStopped())
|
||||
return file_time;
|
||||
|
||||
length = m_file_stream->GetPosition();
|
||||
seconds = m_file_stream->GetSoundFormat().GetTimeFromBytes(length);
|
||||
file_time.seconds = seconds % 60;
|
||||
file_time.minutes = (seconds / 60) % 60;
|
||||
file_time.hours = seconds / 3600;
|
||||
|
||||
return file_time;
|
||||
}
|
||||
|
||||
void MMBoardSoundFile::SetPosition(MMBoardTime btime)
|
||||
{
|
||||
wxUint32 itime;
|
||||
|
||||
itime = btime.seconds + btime.minutes * 60 + btime.hours;
|
||||
|
||||
m_file_stream->SetPosition(
|
||||
m_file_stream->GetSoundFormat().GetBytesFromTime(itime)
|
||||
);
|
||||
}
|
||||
|
||||
bool MMBoardSoundFile::NeedWindow()
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void MMBoardSoundFile::SetWindow(wxWindow *window)
|
||||
{
|
||||
}
|
||||
|
||||
void MMBoardSoundFile::Play()
|
||||
{
|
||||
m_file_stream->Play();
|
||||
}
|
||||
|
||||
void MMBoardSoundFile::Pause()
|
||||
{
|
||||
m_file_stream->Pause();
|
||||
}
|
||||
|
||||
void MMBoardSoundFile::Resume()
|
||||
{
|
||||
m_file_stream->Resume();
|
||||
}
|
||||
|
||||
void MMBoardSoundFile::Stop()
|
||||
{
|
||||
m_file_stream->Stop();
|
||||
}
|
||||
|
||||
wxString MMBoardSoundFile::GetStringType()
|
||||
{
|
||||
switch (m_file_type) {
|
||||
case MMBoard_WAVE:
|
||||
return wxString(wxT("WAVE file"));
|
||||
break;
|
||||
case MMBoard_AIFF:
|
||||
return wxString(wxT("AIFF file"));
|
||||
break;
|
||||
default:
|
||||
return wxString(wxT("Unknown file"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wxString MMBoardSoundFile::GetStringInformation()
|
||||
{
|
||||
wxString info;
|
||||
wxSoundFormatBase *format;
|
||||
|
||||
format = &(m_file_stream->GetSoundFormat());
|
||||
|
||||
info = wxT("Data encoding: ");
|
||||
switch (format->GetType()) {
|
||||
case wxSOUND_PCM: {
|
||||
wxSoundFormatPcm *pcm_format = (wxSoundFormatPcm *)format;
|
||||
|
||||
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"),
|
||||
pcm_format->GetSampleRate(),
|
||||
pcm_format->GetBPS(),
|
||||
pcm_format->GetChannels());
|
||||
|
||||
break;
|
||||
}
|
||||
case wxSOUND_ULAW: {
|
||||
wxSoundFormatUlaw *ulaw_format = (wxSoundFormatUlaw *)format;
|
||||
info += wxT("ULAW\n");
|
||||
info += wxString::Format(wxT("Sampling rate: %d\n"), ulaw_format->GetSampleRate());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
info += wxT("Unknown");
|
||||
break;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MMBoardVideoFile
|
||||
|
||||
MMBoardVideoFile::MMBoardVideoFile(const wxString& filename)
|
||||
{
|
||||
m_output_window = NULL;
|
||||
|
||||
#if defined(__UNIX__)
|
||||
m_video_driver = new wxVideoXANIM(filename);
|
||||
#elif defined(__WIN32__)
|
||||
m_video_driver = new wxVideoWindows(filename);
|
||||
#else
|
||||
m_video_driver = NULL;
|
||||
SetError(MMBoard_UnknownFile);
|
||||
#endif
|
||||
}
|
||||
|
||||
MMBoardVideoFile::~MMBoardVideoFile()
|
||||
{
|
||||
if (m_video_driver)
|
||||
delete m_video_driver;
|
||||
}
|
||||
|
||||
bool MMBoardVideoFile::NeedWindow()
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void MMBoardVideoFile::SetWindow(wxWindow *window)
|
||||
{
|
||||
m_output_window = window;
|
||||
m_video_driver->AttachOutput(*window);
|
||||
|
||||
wxSize size;
|
||||
m_video_driver->GetSize(size);
|
||||
window->SetSize(size);
|
||||
// BAD BAD
|
||||
// and we remove
|
||||
// window->GetParent()->GetSizer()->Fit(window->GetParent());
|
||||
}
|
||||
|
||||
void MMBoardVideoFile::Play()
|
||||
{
|
||||
m_video_driver->Play();
|
||||
}
|
||||
|
||||
void MMBoardVideoFile::Pause()
|
||||
{
|
||||
m_video_driver->Pause();
|
||||
}
|
||||
|
||||
void MMBoardVideoFile::Resume()
|
||||
{
|
||||
m_video_driver->Resume();
|
||||
}
|
||||
|
||||
void MMBoardVideoFile::Stop()
|
||||
{
|
||||
m_video_driver->Stop();
|
||||
}
|
||||
|
||||
MMBoardTime MMBoardVideoFile::GetPosition()
|
||||
{
|
||||
MMBoardTime btime;
|
||||
|
||||
btime.seconds = btime.minutes = btime.hours = 0;
|
||||
return btime;
|
||||
}
|
||||
|
||||
MMBoardTime MMBoardVideoFile::GetLength()
|
||||
{
|
||||
MMBoardTime btime;
|
||||
int frameTime;
|
||||
|
||||
frameTime = (int)( m_video_driver->GetNbFrames() / m_video_driver->GetFrameRate());
|
||||
|
||||
btime.seconds = frameTime % 60;
|
||||
btime.minutes = (frameTime / 60) % 60;
|
||||
btime.hours = frameTime / 3600;
|
||||
return btime;
|
||||
}
|
||||
|
||||
void MMBoardVideoFile::SetPosition(MMBoardTime btime)
|
||||
{
|
||||
}
|
||||
|
||||
bool MMBoardVideoFile::IsStopped()
|
||||
{
|
||||
return m_video_driver->IsStopped();
|
||||
}
|
||||
|
||||
bool MMBoardVideoFile::IsPaused()
|
||||
{
|
||||
return m_video_driver->IsPaused();
|
||||
}
|
||||
|
||||
wxString MMBoardVideoFile::GetStringType()
|
||||
{
|
||||
return wxString(wxT("Video XANIM"));
|
||||
}
|
||||
|
||||
wxString MMBoardVideoFile::GetStringInformation()
|
||||
{
|
||||
wxString info;
|
||||
|
||||
info = wxT("Video codec: ");
|
||||
info += m_video_driver->GetMovieCodec() + "\n";
|
||||
info += wxT("Audio codec: ");
|
||||
info += m_video_driver->GetAudioCodec();
|
||||
info += wxString::Format(" Sample rate: %d Channels: %d\n", m_video_driver->GetSampleRate(),
|
||||
m_video_driver->GetBPS());
|
||||
info += wxString::Format(" Frame rate: %.01f", m_video_driver->GetFrameRate());
|
||||
return info;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MMBoardFile
|
||||
|
||||
MMBoardFile::MMBoardFile()
|
||||
{
|
||||
m_error = 0;
|
||||
}
|
||||
|
||||
MMBoardFile::~MMBoardFile()
|
||||
{
|
||||
}
|
||||
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MMBoardManager
|
||||
|
||||
MMBoardFile *MMBoardManager::Open(const wxString& filename)
|
||||
{
|
||||
MMBoardFile *file;
|
||||
|
||||
// Test the audio codec
|
||||
file = new MMBoardSoundFile(filename);
|
||||
if (!file->GetError())
|
||||
return file;
|
||||
delete file;
|
||||
|
||||
// Test the video codec
|
||||
file = new MMBoardVideoFile(filename);
|
||||
if (!file->GetError())
|
||||
return file;
|
||||
delete file;
|
||||
|
||||
// Arrrgh, we just could not see what is that file ...
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DECLARE_APP(MMBoardApp)
|
||||
|
||||
wxSoundStream *MMBoardManager::OpenSoundStream()
|
||||
{
|
||||
#ifdef __UNIX__
|
||||
if ((wxGetApp().m_caps & MM_SOUND_ESD) != 0)
|
||||
return new wxSoundStreamESD();
|
||||
|
||||
if ((wxGetApp().m_caps & MM_SOUND_OSS) != 0)
|
||||
return new wxSoundStreamOSS();
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
if ((wxGetApp().m_caps & MM_SOUND_WIN) != 0)
|
||||
return new wxSoundStreamWin();
|
||||
#endif
|
||||
|
||||
wxMessageBox("You are trying to open a multimedia but you have not devices", "Error", wxOK | wxICON_ERROR, NULL);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MMBoardManager::UnrefSoundStream(wxSoundStream *stream)
|
||||
{
|
||||
delete stream;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@@ -1,84 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: mmbman.h
|
||||
// Purpose: Multimedia Board manager
|
||||
// Author: Guilhem Lavaux, <guilhem.lavaux@libertysurf.fr>
|
||||
// Modified by:
|
||||
// Created: 13/02/2000
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2000, Guilhem Lavaux
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MMBMAN_APP_H_
|
||||
#define _MMBMAN_APP_H_
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "mmbman.cpp"
|
||||
#endif
|
||||
|
||||
#include "wx/stream.h"
|
||||
#include "sndbase.h"
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Base structure definitions
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
typedef struct {
|
||||
wxUint8 seconds, minutes, hours;
|
||||
} MMBoardTime;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constants
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
#define MMBoard_NoError 0
|
||||
#define MMBoard_UnknownFile 1
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Interface definition: MMBoardFile
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
class MMBoardFile {
|
||||
public:
|
||||
MMBoardFile();
|
||||
virtual ~MMBoardFile();
|
||||
|
||||
virtual bool NeedWindow() = 0;
|
||||
|
||||
virtual void SetWindow(wxWindow *window) = 0;
|
||||
|
||||
virtual void Play() = 0;
|
||||
virtual void Pause() = 0;
|
||||
virtual void Resume() = 0;
|
||||
virtual void Stop() = 0;
|
||||
|
||||
virtual MMBoardTime GetPosition() = 0;
|
||||
virtual MMBoardTime GetLength() = 0;
|
||||
virtual void SetPosition(MMBoardTime btime) = 0;
|
||||
|
||||
virtual bool IsStopped() = 0;
|
||||
virtual bool IsPaused() = 0;
|
||||
|
||||
virtual wxString GetStringType() = 0;
|
||||
virtual wxString GetStringInformation() = 0;
|
||||
|
||||
void SetError(wxUint8 error) { m_error = error; }
|
||||
wxUint8 GetError() const { return m_error; }
|
||||
|
||||
protected:
|
||||
wxUint8 m_error;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Main manager
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
class MMBoardManager {
|
||||
public:
|
||||
static MMBoardFile *Open(const wxString& filename);
|
||||
|
||||
static wxSoundStream *OpenSoundStream();
|
||||
static void UnrefSoundStream(wxSoundStream *stream);
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,570 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: mmboard.cpp
|
||||
// Purpose: Multimedia Library sample
|
||||
// Author: Guilhem Lavaux (created from minimal by J. Smart)
|
||||
// Modified by:
|
||||
// Created: 13/02/2000
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Guilhem Lavaux
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "mmboard.cpp"
|
||||
#endif
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
// for all others, include the necessary headers (this file is usually all you
|
||||
// need because it includes almost all "standard" wxWindows headers
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ressources
|
||||
// ----------------------------------------------------------------------------
|
||||
// the application icon
|
||||
#if defined(__WXGTK__) || defined(__WXMOTIF__)
|
||||
#include "mondrian.xpm"
|
||||
#endif
|
||||
|
||||
// include multimedia classes
|
||||
#include "sndbase.h"
|
||||
#ifdef __WIN32__
|
||||
#include "sndwin.h"
|
||||
#endif
|
||||
#ifdef __UNIX__
|
||||
#include "sndoss.h"
|
||||
#include "sndesd.h"
|
||||
#endif
|
||||
|
||||
#include "wx/statline.h"
|
||||
#include "wx/stattext.h"
|
||||
|
||||
// include personnal classes
|
||||
#include "mmboard.h"
|
||||
#include "mmbman.h"
|
||||
|
||||
#include "play.xpm"
|
||||
#include "stop.xpm"
|
||||
#include "eject.xpm"
|
||||
#include "pause.xpm"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private classes
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Main Multimedia Board frame
|
||||
class MMBoardFrame : public wxFrame
|
||||
{
|
||||
public:
|
||||
// ctor(s)
|
||||
MMBoardFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
|
||||
// dtor
|
||||
~MMBoardFrame();
|
||||
|
||||
// event handlers
|
||||
void OnQuit(wxCommandEvent& event);
|
||||
void OnAbout(wxCommandEvent& event);
|
||||
void OnOpen(wxCommandEvent& event);
|
||||
void OnPlay(wxCommandEvent& event);
|
||||
void OnStop(wxCommandEvent& event);
|
||||
void OnPause(wxCommandEvent& event);
|
||||
void OnEject(wxCommandEvent& event);
|
||||
void OnRefreshInfo(wxEvent& event);
|
||||
void OnSetPosition(wxCommandEvent& event);
|
||||
|
||||
void OpenVideoWindow();
|
||||
void CloseVideoWindow();
|
||||
|
||||
private:
|
||||
// any class wishing to process wxWindows events must use this macro
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
private:
|
||||
void UpdateMMedInfo();
|
||||
void UpdateInfoText();
|
||||
|
||||
MMBoardFile *m_opened_file;
|
||||
|
||||
wxSlider *m_positionSlider;
|
||||
wxBitmapButton *m_playButton, *m_pauseButton, *m_stopButton, *m_ejectButton;
|
||||
wxStaticText *m_fileType, *m_infoText;
|
||||
wxWindow *m_video_window;
|
||||
|
||||
wxPanel *m_panel;
|
||||
wxSizer *m_sizer;
|
||||
|
||||
wxTimer *m_refreshTimer;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// IDs for the controls and the menu commands
|
||||
enum
|
||||
{
|
||||
// menu items
|
||||
MMBoard_Quit = 1,
|
||||
MMBoard_Open,
|
||||
MMBoard_About,
|
||||
MMBoard_PositionSlider,
|
||||
MMBoard_PlayButton,
|
||||
MMBoard_PauseButton,
|
||||
MMBoard_ResumeButton,
|
||||
MMBoard_StopButton,
|
||||
MMBoard_EjectButton,
|
||||
MMBoard_RefreshInfo
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// event tables and other macros for wxWindows
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
BEGIN_EVENT_TABLE(MMBoardFrame, wxFrame)
|
||||
EVT_MENU(MMBoard_Quit, MMBoardFrame::OnQuit)
|
||||
EVT_MENU(MMBoard_About, MMBoardFrame::OnAbout)
|
||||
EVT_MENU(MMBoard_Open, MMBoardFrame::OnOpen)
|
||||
EVT_BUTTON(MMBoard_PlayButton, MMBoardFrame::OnPlay)
|
||||
EVT_BUTTON(MMBoard_StopButton, MMBoardFrame::OnStop)
|
||||
EVT_BUTTON(MMBoard_PauseButton, MMBoardFrame::OnPause)
|
||||
EVT_BUTTON(MMBoard_EjectButton, MMBoardFrame::OnEject)
|
||||
EVT_SLIDER(MMBoard_PositionSlider, MMBoardFrame::OnSetPosition)
|
||||
EVT_CUSTOM(wxEVT_TIMER, MMBoard_RefreshInfo, MMBoardFrame::OnRefreshInfo)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Main board application launcher
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_APP(MMBoardApp)
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// the application class
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool MMBoardApp::OnInit()
|
||||
{
|
||||
// create the main application window
|
||||
MMBoardFrame *frame = new MMBoardFrame("Multimedia Board",
|
||||
wxPoint(50, 50), wxSize(450, 340));
|
||||
|
||||
// and show it (the frames, unlike simple controls, are not shown when
|
||||
// created initially)
|
||||
frame->Show(TRUE);
|
||||
|
||||
m_caps = TestMultimediaCaps();
|
||||
|
||||
if (!m_caps) {
|
||||
wxMessageBox("Your system has no multimedia capabilities. We are exiting now.", "Major error !", wxOK | wxICON_ERROR, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wxString msg;
|
||||
msg.Printf("Detected : %s%s%s", (m_caps & MM_SOUND_OSS) ? "OSS " : "",
|
||||
(m_caps & MM_SOUND_ESD) ? "ESD " : "",
|
||||
(m_caps & MM_SOUND_WIN) ? "WIN" : "");
|
||||
|
||||
wxMessageBox(msg, "Good !", wxOK | wxICON_INFORMATION, NULL);
|
||||
|
||||
// success: wxApp::OnRun() will be called which will enter the main message
|
||||
// loop and the application will run. If we returned FALSE here, the
|
||||
// application would exit immediately.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
wxUint8 MMBoardApp::TestMultimediaCaps()
|
||||
{
|
||||
wxSoundStream *dev;
|
||||
wxUint8 caps;
|
||||
|
||||
caps = 0;
|
||||
|
||||
#ifdef __UNIX__
|
||||
// We now test the ESD support
|
||||
|
||||
dev = new wxSoundStreamESD();
|
||||
if (dev->GetError() == wxSOUND_NOERROR)
|
||||
caps |= MM_SOUND_ESD;
|
||||
delete dev;
|
||||
|
||||
// We test the OSS (Open Sound System) support.
|
||||
// WARNING: There is a conflict between ESD and ALSA
|
||||
|
||||
dev = new wxSoundStreamOSS();
|
||||
if (dev->GetError() == wxSOUND_NOERROR)
|
||||
caps |= MM_SOUND_OSS;
|
||||
delete dev;
|
||||
#endif
|
||||
|
||||
#ifdef __WIN32__
|
||||
// We test the Windows sound support.
|
||||
|
||||
dev = new wxSoundStreamWin();
|
||||
if (dev->GetError() == wxSOUND_NOERR)
|
||||
caps |= MM_SOUND_WIN;
|
||||
delete dev;
|
||||
#endif
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// main frame
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// frame constructor
|
||||
MMBoardFrame::MMBoardFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
|
||||
: wxFrame((wxFrame *)NULL, -1, title, pos, size)
|
||||
{
|
||||
#ifdef __WXMAC__
|
||||
// we need this in order to allow the about menu relocation, since ABOUT is
|
||||
// not the default id of the about menu
|
||||
wxApp::s_macAboutMenuItemId = MMBoard_About;
|
||||
#endif
|
||||
|
||||
// set the frame icon
|
||||
SetIcon(wxICON(mondrian));
|
||||
|
||||
// create a menu bar
|
||||
wxMenu *menuFile = new wxMenu(wxT(""), wxMENU_TEAROFF);
|
||||
|
||||
// the "About" item should be in the help menu
|
||||
wxMenu *helpMenu = new wxMenu;
|
||||
helpMenu->Append(MMBoard_About, wxT("&About...\tCtrl-A"), wxT("Show about dialog"));
|
||||
|
||||
menuFile->Append(MMBoard_Open, wxT("&Open\tAlt-O"), wxT("Open file"));
|
||||
menuFile->AppendSeparator();
|
||||
menuFile->Append(MMBoard_Quit, wxT("E&xit\tAlt-X"), wxT("Quit this program"));
|
||||
|
||||
// now append the freshly created menu to the menu bar...
|
||||
wxMenuBar *menuBar = new wxMenuBar();
|
||||
menuBar->Append(menuFile, wxT("&File"));
|
||||
menuBar->Append(helpMenu, wxT("&Help"));
|
||||
|
||||
// ... and attach this menu bar to the frame
|
||||
SetMenuBar(menuBar);
|
||||
|
||||
#if wxUSE_STATUSBAR
|
||||
// create a status bar just for fun (by default with 1 pane only)
|
||||
CreateStatusBar(3);
|
||||
SetStatusText(wxT("Welcome to wxWindows!"));
|
||||
#endif // wxUSE_STATUSBAR
|
||||
|
||||
// Misc variables
|
||||
m_opened_file = NULL;
|
||||
|
||||
m_panel = new wxPanel(this, -1);
|
||||
|
||||
// Initialize main slider
|
||||
m_positionSlider = new wxSlider( m_panel, MMBoard_PositionSlider, 0, 0, 60,
|
||||
wxDefaultPosition, wxSize(300, -1),
|
||||
wxSL_HORIZONTAL | wxSL_AUTOTICKS);
|
||||
m_positionSlider->SetPageSize(60); // 60 secs
|
||||
m_positionSlider->Enable(FALSE);
|
||||
|
||||
// Initialize info panel
|
||||
wxPanel *infoPanel = new wxPanel( m_panel, -1);
|
||||
infoPanel->SetBackgroundColour(*wxBLACK);
|
||||
infoPanel->SetForegroundColour(*wxWHITE);
|
||||
|
||||
wxBoxSizer *infoSizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_fileType = new wxStaticText(infoPanel, -1, wxT(""));
|
||||
wxStaticLine *line = new wxStaticLine(infoPanel, -1);
|
||||
m_infoText = new wxStaticText(infoPanel, -1, "");
|
||||
|
||||
UpdateInfoText();
|
||||
|
||||
infoSizer->Add(m_fileType, 0, wxGROW | wxALL, 1);
|
||||
infoSizer->Add(line, 0, wxGROW | wxCENTRE, 20);
|
||||
infoSizer->Add(m_infoText, 0, wxGROW | wxALL, 1);
|
||||
|
||||
infoPanel->SetSizer(infoSizer);
|
||||
infoPanel->SetAutoLayout(TRUE);
|
||||
|
||||
// Bitmap button panel
|
||||
wxBoxSizer *buttonSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
wxBitmap *play_bmp = new wxBitmap(play_back_xpm);
|
||||
wxBitmap *stop_bmp = new wxBitmap(stop_back_xpm);
|
||||
wxBitmap *eject_bmp = new wxBitmap(eject_xpm);
|
||||
wxBitmap *pause_bmp = new wxBitmap(pause_xpm);
|
||||
|
||||
m_playButton = new wxBitmapButton(m_panel, MMBoard_PlayButton, *play_bmp);
|
||||
m_playButton->Enable(FALSE);
|
||||
m_pauseButton = new wxBitmapButton(m_panel, MMBoard_PauseButton, *pause_bmp);
|
||||
m_pauseButton->Enable(FALSE);
|
||||
m_stopButton = new wxBitmapButton(m_panel, MMBoard_StopButton, *stop_bmp);
|
||||
m_stopButton->Enable(FALSE);
|
||||
m_ejectButton = new wxBitmapButton(m_panel, MMBoard_EjectButton, *eject_bmp);
|
||||
m_ejectButton->Enable(FALSE);
|
||||
|
||||
buttonSizer->Add(m_playButton, 0, wxALL, 2);
|
||||
buttonSizer->Add(m_pauseButton, 0, wxALL, 2);
|
||||
buttonSizer->Add(m_stopButton, 0, wxALL, 2);
|
||||
buttonSizer->Add(m_ejectButton, 0, wxALL, 2);
|
||||
|
||||
// Top sizer
|
||||
m_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
m_sizer->Add(new wxStaticLine(m_panel, -1), 0, wxGROW | wxCENTRE, 0);
|
||||
m_sizer->Add(m_positionSlider, 0, wxCENTRE | wxGROW | wxALL, 2);
|
||||
m_sizer->Add(new wxStaticLine(m_panel, -1), 0, wxGROW | wxCENTRE, 0);
|
||||
m_sizer->Add(buttonSizer, 0, wxALL, 0);
|
||||
m_sizer->Add(new wxStaticLine(m_panel, -1), 0, wxGROW | wxCENTRE, 0);
|
||||
m_sizer->Add(infoPanel, 1, wxCENTRE | wxGROW, 0);
|
||||
|
||||
m_panel->SetSizer(m_sizer);
|
||||
m_panel->SetAutoLayout(TRUE);
|
||||
m_sizer->Fit(this);
|
||||
m_sizer->SetSizeHints(this);
|
||||
|
||||
// Timer
|
||||
m_refreshTimer = new wxTimer(this, MMBoard_RefreshInfo);
|
||||
|
||||
// Video window
|
||||
m_video_window = NULL;
|
||||
|
||||
// Multimedia file
|
||||
m_opened_file = NULL;
|
||||
}
|
||||
|
||||
MMBoardFrame::~MMBoardFrame()
|
||||
{
|
||||
if (m_opened_file)
|
||||
delete m_opened_file;
|
||||
|
||||
delete m_refreshTimer;
|
||||
}
|
||||
|
||||
void MMBoardFrame::OpenVideoWindow()
|
||||
{
|
||||
if (m_video_window)
|
||||
return;
|
||||
|
||||
m_video_window = new wxWindow(m_panel, -1, wxDefaultPosition, wxSize(200, 200));
|
||||
m_video_window->SetBackgroundColour(*wxBLACK);
|
||||
m_sizer->Prepend(m_video_window, 2, wxGROW | wxSHRINK | wxCENTRE, 1);
|
||||
|
||||
m_sizer->Fit(this);
|
||||
}
|
||||
|
||||
void MMBoardFrame::CloseVideoWindow()
|
||||
{
|
||||
if (!m_video_window)
|
||||
return;
|
||||
|
||||
m_sizer->Remove(m_video_window);
|
||||
delete m_video_window;
|
||||
m_video_window = NULL;
|
||||
|
||||
m_sizer->Fit(this);
|
||||
}
|
||||
|
||||
// event handlers
|
||||
|
||||
void MMBoardFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
// TRUE is to force the frame to close
|
||||
Close(TRUE);
|
||||
}
|
||||
|
||||
void MMBoardFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxString msg;
|
||||
msg.Printf( wxT("wxWindows Multimedia board v1.0a, wxMMedia v2.0a:\n")
|
||||
wxT("an example of the capabilities of the wxWindows multimedia classes.\n")
|
||||
wxT("Copyright 1999, 2000, Guilhem Lavaux.\n"));
|
||||
|
||||
wxMessageBox(msg, "About MMBoard", wxOK | wxICON_INFORMATION, this);
|
||||
}
|
||||
|
||||
void MMBoardFrame::OnOpen(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxString selected_file;
|
||||
|
||||
if (m_opened_file) {
|
||||
if (!m_opened_file->IsStopped()) {
|
||||
wxCommandEvent event2;
|
||||
OnStop(event2);
|
||||
}
|
||||
delete m_opened_file;
|
||||
}
|
||||
|
||||
// select a file to be opened
|
||||
selected_file = wxLoadFileSelector("multimedia", "*", NULL, this);
|
||||
if (selected_file.IsNull())
|
||||
return;
|
||||
|
||||
m_opened_file = MMBoardManager::Open(selected_file);
|
||||
|
||||
// Change the range values of the slider.
|
||||
MMBoardTime length;
|
||||
|
||||
length = m_opened_file->GetLength();
|
||||
m_positionSlider->SetRange(0, length.hours * 3600 + length.minutes * 60 + length.seconds);
|
||||
|
||||
// Update misc info
|
||||
UpdateMMedInfo();
|
||||
|
||||
SetStatusText(selected_file, 2);
|
||||
|
||||
// Update info text
|
||||
UpdateInfoText();
|
||||
|
||||
// Enable a few buttons
|
||||
m_playButton->Enable(TRUE);
|
||||
m_ejectButton->Enable(TRUE);
|
||||
m_positionSlider->Enable(TRUE);
|
||||
|
||||
if (m_opened_file->NeedWindow()) {
|
||||
OpenVideoWindow();
|
||||
m_opened_file->SetWindow(m_video_window);
|
||||
} else
|
||||
CloseVideoWindow();
|
||||
}
|
||||
|
||||
void MMBoardFrame::UpdateInfoText()
|
||||
{
|
||||
wxString infotext1, infotext2;
|
||||
|
||||
if (m_opened_file) {
|
||||
infotext1 = wxT("File type:\n\t");
|
||||
infotext1 += m_opened_file->GetStringType() + wxT("\n");
|
||||
|
||||
infotext2 = wxT("File informations:\n\n");
|
||||
infotext2 += m_opened_file->GetStringInformation();
|
||||
} else {
|
||||
infotext1 = wxT("File type: \n\tNo file opened");
|
||||
infotext2 = wxT("File informations:\nNo information\n\n\n\n\n");
|
||||
}
|
||||
|
||||
m_fileType->SetLabel(infotext1);
|
||||
m_infoText->SetLabel(infotext2);
|
||||
}
|
||||
|
||||
void MMBoardFrame::UpdateMMedInfo()
|
||||
{
|
||||
wxString temp_string;
|
||||
MMBoardTime current, length;
|
||||
|
||||
if (m_opened_file) {
|
||||
current = m_opened_file->GetPosition();
|
||||
length = m_opened_file->GetLength();
|
||||
} else {
|
||||
current.hours = current.minutes = current.seconds = 0;
|
||||
length = current;
|
||||
}
|
||||
|
||||
// We refresh the status bar
|
||||
temp_string.Printf(wxT("%02d:%02d / %02d:%02d"), current.hours * 60 + current.minutes,
|
||||
current.seconds, length.hours * 60 + length.minutes, length.seconds);
|
||||
SetStatusText(temp_string, 1);
|
||||
|
||||
// We set the slider position
|
||||
m_positionSlider->SetValue(current.hours * 3600 + current.minutes * 60 + current.seconds);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Playing management, refreshers, ...
|
||||
|
||||
void MMBoardFrame::OnRefreshInfo(wxEvent& WXUNUSED(event))
|
||||
{
|
||||
UpdateMMedInfo();
|
||||
|
||||
if (m_opened_file->IsStopped()) {
|
||||
m_refreshTimer->Stop();
|
||||
m_playButton->Enable(TRUE);
|
||||
m_stopButton->Enable(FALSE);
|
||||
m_pauseButton->Enable(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void MMBoardFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
m_stopButton->Enable(TRUE);
|
||||
m_pauseButton->Enable(TRUE);
|
||||
m_playButton->Enable(FALSE);
|
||||
|
||||
if (m_opened_file->IsPaused()) {
|
||||
m_opened_file->Resume();
|
||||
return;
|
||||
}
|
||||
|
||||
m_refreshTimer->Start(1000, FALSE);
|
||||
|
||||
m_opened_file->Play();
|
||||
|
||||
m_stopButton->Enable(TRUE);
|
||||
m_pauseButton->Enable(TRUE);
|
||||
m_playButton->Enable(FALSE);
|
||||
}
|
||||
|
||||
void MMBoardFrame::OnStop(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
m_opened_file->Stop();
|
||||
m_refreshTimer->Stop();
|
||||
|
||||
m_stopButton->Enable(FALSE);
|
||||
m_playButton->Enable(TRUE);
|
||||
|
||||
UpdateMMedInfo();
|
||||
}
|
||||
|
||||
void MMBoardFrame::OnPause(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
m_opened_file->Pause();
|
||||
|
||||
m_playButton->Enable(TRUE);
|
||||
m_pauseButton->Enable(FALSE);
|
||||
}
|
||||
|
||||
void MMBoardFrame::OnEject(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
m_opened_file->Stop();
|
||||
|
||||
delete m_opened_file;
|
||||
m_opened_file = NULL;
|
||||
|
||||
m_playButton->Enable(FALSE);
|
||||
m_pauseButton->Enable(FALSE);
|
||||
m_stopButton->Enable(FALSE);
|
||||
m_ejectButton->Enable(FALSE);
|
||||
m_positionSlider->Enable(FALSE);
|
||||
|
||||
UpdateInfoText();
|
||||
UpdateMMedInfo();
|
||||
}
|
||||
|
||||
void MMBoardFrame::OnSetPosition(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
wxUint32 itime;
|
||||
MMBoardTime btime;
|
||||
|
||||
itime = m_positionSlider->GetValue();
|
||||
btime.seconds = itime % 60;
|
||||
btime.minutes = (itime / 60) % 60;
|
||||
btime.hours = itime / 3600;
|
||||
m_opened_file->SetPosition(btime);
|
||||
|
||||
UpdateMMedInfo();
|
||||
}
|
||||
|
@@ -1,7 +0,0 @@
|
||||
NAME Minimal
|
||||
DESCRIPTION 'Minimal wxWindows application'
|
||||
EXETYPE WINDOWS
|
||||
CODE PRELOAD MOVEABLE DISCARDABLE
|
||||
DATA PRELOAD MOVEABLE MULTIPLE
|
||||
HEAPSIZE 4048
|
||||
STACKSIZE 16000
|
@@ -1,57 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: mmboard.h
|
||||
// Purpose: Multimedia Board header
|
||||
// Author: Guilhem Lavaux, <guilhem.lavaux@libertysurf.fr>
|
||||
// Modified by:
|
||||
// Created: 13/02/2000
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 2000, Guilhem Lavaux
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MMBOARD_APP_H_
|
||||
#define _MMBOARD_APP_H_
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "mmboard.cpp"
|
||||
#endif
|
||||
|
||||
// for compilers that support precompilation, includes "wx/wx.h"
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
// for all others, include the necessary headers
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// constants
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#define MM_SOUND_OSS 0x01
|
||||
#define MM_SOUND_ESD 0x02
|
||||
#define MM_SOUND_WIN 0x04
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Class definitions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Define a new application type, each program should derive a class from wxApp
|
||||
class MMBoardApp : public wxApp
|
||||
{
|
||||
public:
|
||||
wxUint8 m_caps;
|
||||
|
||||
// override base class virtuals
|
||||
// ----------------------------
|
||||
|
||||
virtual bool OnInit();
|
||||
|
||||
wxUint8 TestMultimediaCaps();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,6 +0,0 @@
|
||||
mondrian ICON "mondrian.ico"
|
||||
#include "wx/msw/wx.rc"
|
||||
|
||||
#define MINIMAL_QUIT 1
|
||||
#define MINIMAL_ABOUT 102
|
||||
|
@@ -1,6 +0,0 @@
|
||||
ICON 1 PRELOAD "mondros2.ico"
|
||||
#include "H:\DEV\WX2\wxWindows\include\wx\os2\wx.rc"
|
||||
|
||||
#define MINIMAL_QUIT 1
|
||||
#define MINIMAL_ABOUT 102
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 766 B |
@@ -1,44 +0,0 @@
|
||||
/* XPM */
|
||||
static char *mondrian_xpm[] = {
|
||||
/* columns rows colors chars-per-pixel */
|
||||
"32 32 6 1",
|
||||
" c Black",
|
||||
". c Blue",
|
||||
"X c #00bf00",
|
||||
"o c Red",
|
||||
"O c Yellow",
|
||||
"+ c Gray100",
|
||||
/* pixels */
|
||||
" ",
|
||||
" oooooo +++++++++++++++++++++++ ",
|
||||
" oooooo +++++++++++++++++++++++ ",
|
||||
" oooooo +++++++++++++++++++++++ ",
|
||||
" oooooo +++++++++++++++++++++++ ",
|
||||
" oooooo +++++++++++++++++++++++ ",
|
||||
" oooooo +++++++++++++++++++++++ ",
|
||||
" oooooo +++++++++++++++++++++++ ",
|
||||
" ",
|
||||
" ++++++ ++++++++++++++++++ .... ",
|
||||
" ++++++ ++++++++++++++++++ .... ",
|
||||
" ++++++ ++++++++++++++++++ .... ",
|
||||
" ++++++ ++++++++++++++++++ .... ",
|
||||
" ++++++ ++++++++++++++++++ .... ",
|
||||
" ++++++ ++++++++++++++++++ ",
|
||||
" ++++++ ++++++++++++++++++ ++++ ",
|
||||
" ++++++ ++++++++++++++++++ ++++ ",
|
||||
" ++++++ ++++++++++++++++++ ++++ ",
|
||||
" ++++++ ++++++++++++++++++ ++++ ",
|
||||
" ++++++ ++++++++++++++++++ ++++ ",
|
||||
" ++++++ ++++++++++++++++++ ++++ ",
|
||||
" ++++++ ++++++++++++++++++ ++++ ",
|
||||
" ++++++ ++++++++++++++++++ ++++ ",
|
||||
" ++++++ ++++++++++++++++++ ++++ ",
|
||||
" ++++++ ++++ ",
|
||||
" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
|
||||
" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
|
||||
" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
|
||||
" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
|
||||
" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
|
||||
" ++++++ OOOOOOOOOOOO XXXXX ++++ ",
|
||||
" "
|
||||
};
|
Binary file not shown.
@@ -1,23 +0,0 @@
|
||||
/* XPM */
|
||||
static char * pause_xpm[] = {
|
||||
"13 15 5 1",
|
||||
" c None",
|
||||
". c #949594",
|
||||
"+ c #000000",
|
||||
"@ c #8E8E8E",
|
||||
"# c #FFFFFF",
|
||||
"...... ......",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+++@# .+++@#",
|
||||
".+@@@# .+@@@#",
|
||||
".##### .#####"};
|
@@ -1,23 +0,0 @@
|
||||
/* XPM */
|
||||
static char * play_back_xpm[] = {
|
||||
"13 15 5 1",
|
||||
" c None",
|
||||
". c #949594",
|
||||
"+ c #000000",
|
||||
"@ c #8E8E8E",
|
||||
"# c #FFFFFF",
|
||||
"...... ",
|
||||
".+++++. ",
|
||||
".++++++. ",
|
||||
".+++++++. ",
|
||||
".++++++++. ",
|
||||
".+++++++++. ",
|
||||
".++++++++++. ",
|
||||
".++++++++++@#",
|
||||
".+++++++++@# ",
|
||||
".++++++++@# ",
|
||||
".+++++++@# ",
|
||||
".++++++@# ",
|
||||
".+++++@# ",
|
||||
".+@@@@# ",
|
||||
".##### "};
|
@@ -1,23 +0,0 @@
|
||||
/* XPM */
|
||||
static char * stop_back_xpm[] = {
|
||||
"13 15 5 1",
|
||||
" c None",
|
||||
". c #949594",
|
||||
"+ c #000000",
|
||||
"@ c #8E8E8E",
|
||||
"# c #FFFFFF",
|
||||
".............",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".++++++++++@#",
|
||||
".+@@@@@@@@@@#",
|
||||
".############"};
|
@@ -1,26 +0,0 @@
|
||||
#
|
||||
# File: Makefile
|
||||
# Author: Guilhem Lavaux
|
||||
# Created: 1998
|
||||
# Updated:
|
||||
# Copyright: (c) 1998 Julian Smart
|
||||
#
|
||||
# "%W% %G%"
|
||||
#
|
||||
# Makefile for wxMultiMedia (UNIX).
|
||||
|
||||
top_srcdir = @top_srcdir@/..
|
||||
top_builddir = ../../..
|
||||
|
||||
VPATH= $(top_srcdir)/utils/wxMMedia2/lib
|
||||
|
||||
LIBTARGET=libwxmmedia2
|
||||
|
||||
OBJECTS=sndbase.o sndcodec.o sndpcm.o sndcpcm.o sndulaw.o sndfile.o sndoss.o\
|
||||
sndesd.o sndaiff.o sndwav.o sndg72x.o \
|
||||
g711.o g721.o g723_24.o g723_40.o g72x.o \
|
||||
cdbase.o cdunix.o \
|
||||
vidbase.o vidxanm.o
|
||||
|
||||
include $(top_builddir)/src/makelib.env
|
||||
|
@@ -1,55 +0,0 @@
|
||||
// ---------------------------------------------------------------------------
|
||||
// Name: cdbase.cpp
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1999
|
||||
// Copyright: (C) 1997, 1998, 1999 Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
// ---------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
#include "wx/wxprec.h"
|
||||
#include "cdbase.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxCDAudio, wxObject)
|
||||
|
||||
wxCDtime wxCDAudio::CDtoc::GetTrackTime(wxUint8 track) const
|
||||
{
|
||||
if (track > total_time.track) {
|
||||
wxCDtime dummy_time = {0, 0, 0, 0};
|
||||
return dummy_time;
|
||||
}
|
||||
return tracks_time[track];
|
||||
}
|
||||
|
||||
wxCDtime wxCDAudio::CDtoc::GetTrackPos(wxUint8 track) const
|
||||
{
|
||||
if (track > total_time.track) {
|
||||
wxCDtime dummy_time = {0, 0, 0, 0};
|
||||
return dummy_time;
|
||||
}
|
||||
return tracks_pos[track];
|
||||
}
|
||||
|
||||
bool wxCDAudio::Play(const wxCDtime& beg_play)
|
||||
{
|
||||
return Play(beg_play, GetToc().GetTotalTime());
|
||||
}
|
||||
|
||||
bool wxCDAudio::Play(wxUint8 beg_track, wxUint8 end_track)
|
||||
{
|
||||
wxCDtime beg_play = GetToc().GetTrackPos(beg_track);
|
||||
wxCDtime end_play;
|
||||
|
||||
if (end_track)
|
||||
end_play = GetToc().GetTrackPos(end_track);
|
||||
else
|
||||
end_play = GetToc().GetTotalTime();
|
||||
return Play(beg_play, end_play);
|
||||
}
|
@@ -1,76 +0,0 @@
|
||||
// -*- c++ -*-
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// Name: cdbase.h
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1998
|
||||
// Copyright: (C) 1997, 1998, Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef __CDA_base_H__
|
||||
#define __CDA_base_H__
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#include "wx/object.h"
|
||||
|
||||
typedef struct wxCDtime {
|
||||
wxUint8 track;
|
||||
wxUint8 hour, min, sec;
|
||||
} wxCDtime;
|
||||
|
||||
class WXDLLEXPORT wxCDAudio : public wxObject {
|
||||
DECLARE_ABSTRACT_CLASS(wxCDAudio)
|
||||
public:
|
||||
typedef enum { PLAYING, PAUSED, STOPPED } CDstatus;
|
||||
// Table of contents manager
|
||||
class CDtoc {
|
||||
protected:
|
||||
wxCDtime *tracks_time, *tracks_pos;
|
||||
wxCDtime total_time;
|
||||
public:
|
||||
//
|
||||
CDtoc(wxCDtime& tot_tm, wxCDtime *trks_tm, wxCDtime *trks_pos)
|
||||
{ tracks_time = trks_tm; total_time = tot_tm; tracks_pos = trks_pos; }
|
||||
|
||||
// Returns the length of the specified track
|
||||
// track: track to get length
|
||||
wxCDtime GetTrackTime(wxUint8 track) const;
|
||||
// Returns the position of the specified track
|
||||
// track: track to get position
|
||||
wxCDtime GetTrackPos(wxUint8 track) const;
|
||||
// Returns the total time
|
||||
inline wxCDtime GetTotalTime() const { return total_time; }
|
||||
};
|
||||
public:
|
||||
//
|
||||
wxCDAudio() : wxObject() {}
|
||||
//
|
||||
virtual ~wxCDAudio() {}
|
||||
|
||||
// Play audio at the specified position
|
||||
virtual bool Play(const wxCDtime& beg_play, const wxCDtime& end_play) = 0;
|
||||
// Play audio from the specified to the end of the CD audio
|
||||
bool Play(const wxCDtime& beg_play);
|
||||
//
|
||||
bool Play(wxUint8 beg_track, wxUint8 end_track = 0);
|
||||
// Pause the audio playing
|
||||
virtual bool Pause() = 0;
|
||||
// Resume a paused audio playing
|
||||
virtual bool Resume() = 0;
|
||||
// Get the current CD status
|
||||
virtual CDstatus GetStatus() = 0;
|
||||
// Get the current playing time
|
||||
virtual wxCDtime GetTime() = 0;
|
||||
// Returns the table of contents
|
||||
virtual const CDtoc& GetToc() = 0;
|
||||
// CD ok
|
||||
virtual bool Ok() const = 0;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,201 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Name: cdlinux.cpp
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1998
|
||||
// Copyright: (C) 1997, 1998, Guilhem Lavaux
|
||||
// CVS Id: $Id$
|
||||
// License: wxWindows license
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "cdunix.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#include <linux/cdrom.h>
|
||||
#else
|
||||
// For Solaris
|
||||
#include <sys/cdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef WX_PRECOMP
|
||||
#include "wx/wxprec.h"
|
||||
#else
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
#include "cdbase.h"
|
||||
#include "cdunix.h"
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxCDAudioLinux, wxCDAudio)
|
||||
|
||||
wxCDAudioLinux::wxCDAudioLinux()
|
||||
: wxCDAudio(), m_fd(-1)
|
||||
{
|
||||
OpenDevice("/dev/cdrom");
|
||||
}
|
||||
|
||||
wxCDAudioLinux::wxCDAudioLinux(const char *dev_name)
|
||||
: wxCDAudio(), m_fd(-1)
|
||||
{
|
||||
OpenDevice(dev_name);
|
||||
}
|
||||
|
||||
wxCDAudioLinux::~wxCDAudioLinux()
|
||||
{
|
||||
if (m_fd != -1) {
|
||||
close(m_fd);
|
||||
wxDELETE(m_trksize);
|
||||
wxDELETE(m_trkpos);
|
||||
}
|
||||
}
|
||||
|
||||
void wxCDAudioLinux::OpenDevice(const char *dev_name)
|
||||
{
|
||||
struct cdrom_tocentry entry, old_entry;
|
||||
struct cdrom_tochdr diskinf;
|
||||
struct cdrom_msf0 *msf = &entry.cdte_addr.msf,
|
||||
*old_msf = &old_entry.cdte_addr.msf;
|
||||
wxCDtime *the_track;
|
||||
wxCDtime tot_tm;
|
||||
wxUint8 nb_tracks, i;
|
||||
int hour, minute, second;
|
||||
|
||||
if (m_fd != -1)
|
||||
return;
|
||||
|
||||
m_fd = open(dev_name, O_RDONLY);
|
||||
if (m_fd == -1) {
|
||||
m_toc = NULL;
|
||||
return;
|
||||
}
|
||||
m_status = STOPPED;
|
||||
|
||||
ioctl(m_fd, CDROMREADTOCHDR, &diskinf);
|
||||
|
||||
nb_tracks = diskinf.cdth_trk1-diskinf.cdth_trk0+1;
|
||||
m_trksize = new wxCDtime[nb_tracks+1];
|
||||
m_trkpos = new wxCDtime[nb_tracks+1];
|
||||
|
||||
old_msf->minute = 0;
|
||||
old_msf->second = 0;
|
||||
for (i=diskinf.cdth_trk0;i<=diskinf.cdth_trk1;i++) {
|
||||
entry.cdte_track = i;
|
||||
entry.cdte_format = CDROM_MSF;
|
||||
ioctl(m_fd, CDROMREADTOCENTRY, &entry);
|
||||
|
||||
minute = msf->minute - old_msf->minute;
|
||||
second = msf->second - old_msf->second;
|
||||
if (second < 0) {
|
||||
minute--;
|
||||
second += 60;
|
||||
}
|
||||
|
||||
hour = minute / 60;
|
||||
minute %= 60;
|
||||
|
||||
the_track = &m_trksize[i-diskinf.cdth_trk0];
|
||||
the_track->track = i-diskinf.cdth_trk0;
|
||||
the_track->hour = hour;
|
||||
the_track->min = minute;
|
||||
the_track->sec = second;
|
||||
|
||||
the_track = &m_trkpos[i-diskinf.cdth_trk0];
|
||||
the_track->track = i-diskinf.cdth_trk0;
|
||||
the_track->hour = old_msf->minute / 60;
|
||||
the_track->min = old_msf->minute % 60;
|
||||
the_track->sec = old_msf->second;
|
||||
old_entry = entry;
|
||||
}
|
||||
|
||||
entry.cdte_track = CDROM_LEADOUT;
|
||||
entry.cdte_format = CDROM_MSF;
|
||||
ioctl(m_fd, CDROMREADTOCENTRY, &entry);
|
||||
|
||||
tot_tm.track = nb_tracks;
|
||||
tot_tm.hour = msf->minute / 60;
|
||||
tot_tm.min = msf->minute % 60;
|
||||
tot_tm.sec = msf->second % 60;
|
||||
|
||||
m_trksize[nb_tracks].track = nb_tracks;
|
||||
minute = msf->minute - old_msf->minute;
|
||||
second = msf->second - old_msf->second;
|
||||
if (second < 0) {
|
||||
minute--;
|
||||
second += 60;
|
||||
}
|
||||
hour = minute / 60;
|
||||
minute %= 60;
|
||||
|
||||
m_trksize[nb_tracks].hour = hour;
|
||||
m_trksize[nb_tracks].min = minute;
|
||||
m_trksize[nb_tracks].sec = second;
|
||||
m_trkpos[nb_tracks].track = nb_tracks;
|
||||
m_trkpos[nb_tracks].hour = old_msf->minute / 60;
|
||||
m_trkpos[nb_tracks].min = old_msf->minute % 60;
|
||||
m_trkpos[nb_tracks].sec = old_msf->second;
|
||||
|
||||
m_toc = new CDtoc(tot_tm, m_trksize, m_trkpos);
|
||||
}
|
||||
|
||||
bool wxCDAudioLinux::Play(const wxCDtime& beg_time, const wxCDtime& end_time)
|
||||
{
|
||||
struct cdrom_msf track_msf;
|
||||
|
||||
track_msf.cdmsf_min0 = beg_time.hour * 60 + beg_time.min;
|
||||
track_msf.cdmsf_sec0 = beg_time.sec;
|
||||
track_msf.cdmsf_frame0 = 0;
|
||||
track_msf.cdmsf_min1 = end_time.hour * 60 + end_time.min;
|
||||
track_msf.cdmsf_sec1 = end_time.sec;
|
||||
track_msf.cdmsf_frame1 = 0;
|
||||
return (ioctl(m_fd, CDROMPLAYMSF, &track_msf) != -1);
|
||||
}
|
||||
|
||||
bool wxCDAudioLinux::Pause()
|
||||
{
|
||||
return (ioctl(m_fd, CDROMPAUSE, 0) != -1);
|
||||
}
|
||||
|
||||
bool wxCDAudioLinux::Resume()
|
||||
{
|
||||
return (ioctl(m_fd, CDROMRESUME, 0) != -1);
|
||||
}
|
||||
|
||||
wxCDAudio::CDstatus wxCDAudioLinux::GetStatus()
|
||||
{
|
||||
struct cdrom_subchnl subchnl;
|
||||
ioctl(m_fd, CDROMSUBCHNL, &subchnl);
|
||||
switch (subchnl.cdsc_audiostatus) {
|
||||
case CDROM_AUDIO_PLAY: return PLAYING;
|
||||
case CDROM_AUDIO_PAUSED: return PAUSED;
|
||||
case CDROM_AUDIO_COMPLETED: return STOPPED;
|
||||
}
|
||||
|
||||
return STOPPED;
|
||||
}
|
||||
|
||||
wxCDtime wxCDAudioLinux::GetTime()
|
||||
{
|
||||
wxCDtime cdtime;
|
||||
struct cdrom_subchnl subchnl;
|
||||
|
||||
ioctl(m_fd, CDROMSUBCHNL, &subchnl);
|
||||
cdtime.track = subchnl.cdsc_trk;
|
||||
cdtime.min = subchnl.cdsc_reladdr.msf.minute;
|
||||
cdtime.hour = cdtime.min / 60;
|
||||
cdtime.min %= 60;
|
||||
cdtime.sec = subchnl.cdsc_reladdr.msf.second;
|
||||
|
||||
return cdtime;
|
||||
}
|
||||
|
||||
wxCDAudio::CDtoc& wxCDAudioLinux::GetToc()
|
||||
{
|
||||
return *m_toc;
|
||||
}
|
@@ -1,60 +0,0 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// Name: cdunix.h
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1998
|
||||
// Copyright: (C) 1997, 1998, Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef __CDUNIXH__
|
||||
#define __CDUNIXH__
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
#ifdef WX_PRECOMP
|
||||
#include "wx/wxprec.h"
|
||||
#else
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
#include "cdbase.h"
|
||||
|
||||
///
|
||||
class WXDLLEXPORT wxCDAudioLinux : public wxCDAudio {
|
||||
DECLARE_DYNAMIC_CLASS(wxCDAudioLinux)
|
||||
protected:
|
||||
wxCDtime m_time;
|
||||
CDstatus m_status;
|
||||
CDtoc *m_toc;
|
||||
int m_fd;
|
||||
wxCDtime *m_trksize, *m_trkpos;
|
||||
public:
|
||||
///
|
||||
wxCDAudioLinux();
|
||||
///
|
||||
wxCDAudioLinux(const char *dev_name);
|
||||
///
|
||||
virtual ~wxCDAudioLinux();
|
||||
|
||||
///
|
||||
virtual bool Play(const wxCDtime& beg_time, const wxCDtime& end_time);
|
||||
///
|
||||
virtual bool Pause();
|
||||
///
|
||||
virtual bool Resume();
|
||||
///
|
||||
virtual CDstatus GetStatus();
|
||||
///
|
||||
virtual wxCDtime GetTime();
|
||||
///
|
||||
virtual CDtoc& GetToc();
|
||||
///
|
||||
virtual inline bool Ok() const { return (m_fd != -1); }
|
||||
protected:
|
||||
///
|
||||
void OpenDevice(const char *dev_name);
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,202 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Name: cdwin.cpp
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1998
|
||||
// Copyright: (C) 1997, 1998, Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "cdwin.h"
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <mmsystem.h>
|
||||
#include "wx/wxprec.h"
|
||||
#define WXMMEDIA_INTERNAL
|
||||
#include "cdbase.h"
|
||||
#include "cdwin.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
wxCDAudioWin::wxCDAudioWin(void)
|
||||
: wxCDAudio(), m_trksize(NULL), m_trkpos(NULL), m_ok(TRUE), m_toc(NULL)
|
||||
{
|
||||
MCI_OPEN_PARMS open_struct;
|
||||
MCI_SET_PARMS set_struct;
|
||||
DWORD ret;
|
||||
|
||||
m_internal = new CDAW_Internal;
|
||||
open_struct.lpstrDeviceType = "cdaudio";
|
||||
ret = mciSendCommand(NULL, MCI_OPEN, MCI_OPEN_TYPE,
|
||||
(DWORD)&open_struct);
|
||||
if (ret) {
|
||||
m_ok = FALSE;
|
||||
return;
|
||||
}
|
||||
m_internal->dev_id = open_struct.wDeviceID;
|
||||
|
||||
set_struct.dwTimeFormat = MCI_FORMAT_MSF;
|
||||
ret = mciSendCommand(m_internal->dev_id, MCI_SET, MCI_SET_TIME_FORMAT,
|
||||
(DWORD)(LPVOID)&set_struct);
|
||||
|
||||
PrepareToc();
|
||||
|
||||
set_struct.dwTimeFormat = MCI_FORMAT_TMSF;
|
||||
ret = mciSendCommand(m_internal->dev_id, MCI_SET, MCI_SET_TIME_FORMAT,
|
||||
(DWORD)(LPVOID)&set_struct);
|
||||
}
|
||||
|
||||
wxCDAudioWin::~wxCDAudioWin(void)
|
||||
{
|
||||
if (m_ok) {
|
||||
mciSendCommand(m_internal->dev_id, MCI_CLOSE, 0, NULL);
|
||||
delete m_toc;
|
||||
delete[] m_trksize;
|
||||
delete[] m_trkpos;
|
||||
}
|
||||
delete m_internal;
|
||||
}
|
||||
|
||||
void wxCDAudioWin::PrepareToc(void)
|
||||
{
|
||||
MCI_STATUS_PARMS status_struct;
|
||||
wxUint16 i, nb_m_trksize;
|
||||
wxCDtime total_time, *trk;
|
||||
DWORD ret, tmem;
|
||||
|
||||
if (!m_ok)
|
||||
return;
|
||||
|
||||
status_struct.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
|
||||
ret = mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
|
||||
(DWORD)&status_struct);
|
||||
nb_m_trksize = status_struct.dwReturn;
|
||||
|
||||
m_trksize = new wxCDtime[nb_m_trksize+1];
|
||||
m_trkpos = new wxCDtime[nb_m_trksize+1];
|
||||
|
||||
status_struct.dwItem = MCI_STATUS_LENGTH;
|
||||
ret = mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
|
||||
(DWORD)&status_struct);
|
||||
total_time.track = nb_m_trksize;
|
||||
tmem = status_struct.dwReturn;
|
||||
total_time.min = MCI_MSF_MINUTE(tmem);
|
||||
total_time.sec = MCI_MSF_SECOND(tmem);
|
||||
total_time.hour = total_time.min / 60;
|
||||
total_time.min %= 60;
|
||||
|
||||
for (i=1;i<=nb_m_trksize;i++) {
|
||||
status_struct.dwItem = MCI_STATUS_POSITION;
|
||||
status_struct.dwTrack = i;
|
||||
ret = mciSendCommand(m_internal->dev_id, MCI_STATUS,
|
||||
MCI_STATUS_ITEM | MCI_TRACK,
|
||||
(DWORD)(LPVOID)&status_struct);
|
||||
tmem = status_struct.dwReturn;
|
||||
|
||||
trk = &m_trkpos[i];
|
||||
trk->track = i;
|
||||
trk->min = MCI_MSF_MINUTE(tmem);
|
||||
trk->sec = MCI_MSF_SECOND(tmem);
|
||||
trk->hour = trk->min / 60;
|
||||
trk->min %= 60;
|
||||
|
||||
status_struct.dwItem = MCI_STATUS_LENGTH;
|
||||
status_struct.dwTrack = i;
|
||||
ret = mciSendCommand(m_internal->dev_id, MCI_STATUS,
|
||||
MCI_STATUS_ITEM | MCI_TRACK,
|
||||
(DWORD)(LPVOID)&status_struct);
|
||||
tmem = status_struct.dwReturn;
|
||||
|
||||
trk = &m_trksize[i];
|
||||
trk->track = i;
|
||||
trk->min = MCI_MSF_MINUTE(tmem);
|
||||
trk->sec = MCI_MSF_SECOND(tmem);
|
||||
trk->hour = trk->min / 60;
|
||||
trk->min %= 60;
|
||||
}
|
||||
|
||||
m_toc = new CDtoc(total_time, m_trksize, m_trkpos);
|
||||
}
|
||||
|
||||
bool wxCDAudioWin::Play(const wxCDtime& beg_time, const wxCDtime& end_time)
|
||||
{
|
||||
DWORD tmsf;
|
||||
MCI_PLAY_PARMS play_struct;
|
||||
|
||||
if (!m_ok)
|
||||
return FALSE;
|
||||
|
||||
tmsf = MCI_MAKE_TMSF(beg_time.track, beg_time.min,
|
||||
beg_time.sec, 0);
|
||||
play_struct.dwFrom = tmsf;
|
||||
tmsf = MCI_MAKE_TMSF(end_time.track, end_time.min,
|
||||
end_time.sec, 0);
|
||||
play_struct.dwTo = tmsf;
|
||||
|
||||
mciSendCommand(m_internal->dev_id, MCI_PLAY, 0, (DWORD)&play_struct);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxCDAudioWin::Pause(void)
|
||||
{
|
||||
if (!m_ok)
|
||||
return FALSE;
|
||||
|
||||
return (mciSendCommand(m_internal->dev_id, MCI_PAUSE, 0, 0) == 0);
|
||||
}
|
||||
|
||||
bool wxCDAudioWin::Resume(void)
|
||||
{
|
||||
if (!m_ok)
|
||||
return FALSE;
|
||||
|
||||
return (mciSendCommand(m_internal->dev_id, MCI_RESUME, 0, 0) == 0);
|
||||
}
|
||||
|
||||
wxCDAudio::CDstatus wxCDAudioWin::GetStatus(void)
|
||||
{
|
||||
MCI_STATUS_PARMS status_struct;
|
||||
|
||||
if (!m_ok)
|
||||
return STOPPED;
|
||||
|
||||
status_struct.dwItem = MCI_STATUS_MODE;
|
||||
mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
|
||||
(DWORD)&status_struct);
|
||||
switch (status_struct.dwReturn) {
|
||||
case MCI_MODE_PAUSE:
|
||||
return PAUSED;
|
||||
case MCI_MODE_PLAY:
|
||||
return PLAYING;
|
||||
}
|
||||
return STOPPED;
|
||||
}
|
||||
|
||||
wxCDtime wxCDAudioWin::GetTime(void)
|
||||
{
|
||||
MCI_STATUS_PARMS status_struct;
|
||||
wxCDtime cd_time = {-1, -1, -1, -1};
|
||||
|
||||
if (!m_ok)
|
||||
return cd_time;
|
||||
|
||||
status_struct.dwItem = MCI_STATUS_TIME_FORMAT;
|
||||
mciSendCommand(m_internal->dev_id, MCI_STATUS, MCI_STATUS_ITEM,
|
||||
(DWORD)&status_struct);
|
||||
cd_time.track = MCI_TMSF_TRACK(status_struct.dwReturn);
|
||||
cd_time.min = MCI_TMSF_MINUTE(status_struct.dwReturn);
|
||||
cd_time.sec = MCI_TMSF_SECOND(status_struct.dwReturn);
|
||||
cd_time.hour = cd_time.min / 60;
|
||||
cd_time.min %= 60;
|
||||
return cd_time;
|
||||
}
|
||||
|
||||
const wxCDAudio::CDtoc& wxCDAudioWin::GetToc(void)
|
||||
{
|
||||
return *m_toc;
|
||||
}
|
@@ -1,62 +0,0 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// Name: cdwin.h
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1998
|
||||
// Copyright: (C) 1997, 1998, Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
#ifndef __CDA_win_H__
|
||||
#define __CDA_win_H__
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface
|
||||
#endif
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
#include "cdbase.h"
|
||||
|
||||
#ifdef WXMMEDIA_INTERNAL
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
typedef struct CDAW_Internal {
|
||||
MCIDEVICEID dev_id;
|
||||
} CDAW_Internal;
|
||||
#endif
|
||||
|
||||
///
|
||||
class WXDLLEXPORT wxCDAudioWin : public wxCDAudio {
|
||||
DECLARE_DYNAMIC_CLASS(wxCDAudioWin)
|
||||
protected:
|
||||
struct CDAW_Internal *m_internal;
|
||||
wxCDtime *m_trksize, *m_trkpos;
|
||||
CDtoc *m_toc;
|
||||
bool m_ok;
|
||||
public:
|
||||
///
|
||||
wxCDAudioWin(void);
|
||||
///
|
||||
wxCDAudioWin(const char *dev_name);
|
||||
///
|
||||
virtual ~wxCDAudioWin(void);
|
||||
|
||||
///
|
||||
virtual bool Play(const wxCDtime& beg_time, const wxCDtime& end_time);
|
||||
///
|
||||
virtual bool Pause(void);
|
||||
///
|
||||
virtual bool Resume(void);
|
||||
///
|
||||
virtual CDstatus GetStatus(void);
|
||||
///
|
||||
virtual wxCDtime GetTime(void);
|
||||
///
|
||||
virtual const CDtoc& GetToc(void);
|
||||
///
|
||||
virtual inline bool Ok(void) const { return m_ok; }
|
||||
protected:
|
||||
void PrepareToc();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,39 +0,0 @@
|
||||
#define DEFINE_CONV(name, input_type, output_type, convert) \
|
||||
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; \
|
||||
register output_type *t_buf_out = (output_type *)buf_out; \
|
||||
\
|
||||
while (len > 0) { \
|
||||
src = *t_buf_in++; \
|
||||
*t_buf_out++ = convert; \
|
||||
len -= sizeof(input_type); \
|
||||
} \
|
||||
}
|
||||
|
||||
// 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(8_16_swap, wxUint8, wxUint16, (src))
|
||||
DEFINE_CONV(8_16_sign, wxUint8, wxUint16, (((wxUint16)(src ^ 0x80)) << 8))
|
||||
DEFINE_CONV(8_16_sign_swap, wxUint8, wxUint16, (src ^ 0x80))
|
||||
|
||||
DEFINE_CONV(16_8, wxUint16, wxUint8, (wxUint8)(src >> 8))
|
||||
DEFINE_CONV(16_8_sign, wxUint16, wxUint8, (wxUint8)((src >> 8) ^ 0x80))
|
||||
DEFINE_CONV(16_swap_8, wxUint16, wxUint8, (wxUint8)(src & 0xff))
|
||||
DEFINE_CONV(16_swap_8_sign, wxUint16, wxUint8, (wxUint8)((src & 0xff) ^ 0x80))
|
||||
|
||||
//DEFINE_CONV(24_8, wxUint32, wxUint8, (wxUint8)(src >> 16))
|
||||
//DEFINE_CONV(24_8_sig, wxUint32, wxUint8, (wxUint8)((src >> 16) ^ 0x80))
|
||||
|
||||
//DEFINE_CONV(32_8, wxUint32, wxUint8, (wxUint8)(src >> 24))
|
||||
|
||||
DEFINE_CONV(16_sign, wxUint16, wxUint16, (src ^ 0x8000))
|
||||
DEFINE_CONV(16_swap, wxUint16, wxUint16, (((src & 0xff) << 8) | ((src >> 8) & 0xff)))
|
||||
// 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))
|
@@ -1,285 +0,0 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
/*
|
||||
* g711.c
|
||||
*
|
||||
* u-law, A-law and linear PCM conversions.
|
||||
*/
|
||||
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
|
||||
#define QUANT_MASK (0xf) /* Quantization field mask. */
|
||||
#define NSEGS (8) /* Number of A-law segments. */
|
||||
#define SEG_SHIFT (4) /* Left shift for segment number. */
|
||||
#define SEG_MASK (0x70) /* Segment field mask. */
|
||||
|
||||
static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF,
|
||||
0xFFF, 0x1FFF, 0x3FFF, 0x7FFF};
|
||||
|
||||
/* copy from CCITT G.711 specifications */
|
||||
unsigned char _u2a[128] = { /* u- to A-law conversions */
|
||||
1, 1, 2, 2, 3, 3, 4, 4,
|
||||
5, 5, 6, 6, 7, 7, 8, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 18, 19, 20, 21, 22, 23, 24,
|
||||
25, 27, 29, 31, 33, 34, 35, 36,
|
||||
37, 38, 39, 40, 41, 42, 43, 44,
|
||||
46, 48, 49, 50, 51, 52, 53, 54,
|
||||
55, 56, 57, 58, 59, 60, 61, 62,
|
||||
64, 65, 66, 67, 68, 69, 70, 71,
|
||||
72, 73, 74, 75, 76, 77, 78, 79,
|
||||
81, 82, 83, 84, 85, 86, 87, 88,
|
||||
89, 90, 91, 92, 93, 94, 95, 96,
|
||||
97, 98, 99, 100, 101, 102, 103, 104,
|
||||
105, 106, 107, 108, 109, 110, 111, 112,
|
||||
113, 114, 115, 116, 117, 118, 119, 120,
|
||||
121, 122, 123, 124, 125, 126, 127, 128};
|
||||
|
||||
unsigned char _a2u[128] = { /* A- to u-law conversions */
|
||||
1, 3, 5, 7, 9, 11, 13, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31,
|
||||
32, 32, 33, 33, 34, 34, 35, 35,
|
||||
36, 37, 38, 39, 40, 41, 42, 43,
|
||||
44, 45, 46, 47, 48, 48, 49, 49,
|
||||
50, 51, 52, 53, 54, 55, 56, 57,
|
||||
58, 59, 60, 61, 62, 63, 64, 64,
|
||||
65, 66, 67, 68, 69, 70, 71, 72,
|
||||
73, 74, 75, 76, 77, 78, 79, 79,
|
||||
80, 81, 82, 83, 84, 85, 86, 87,
|
||||
88, 89, 90, 91, 92, 93, 94, 95,
|
||||
96, 97, 98, 99, 100, 101, 102, 103,
|
||||
104, 105, 106, 107, 108, 109, 110, 111,
|
||||
112, 113, 114, 115, 116, 117, 118, 119,
|
||||
120, 121, 122, 123, 124, 125, 126, 127};
|
||||
|
||||
static int
|
||||
search(
|
||||
int val,
|
||||
short *table,
|
||||
int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
if (val <= *table++)
|
||||
return (i);
|
||||
}
|
||||
return (size);
|
||||
}
|
||||
|
||||
/*
|
||||
* linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law
|
||||
*
|
||||
* linear2alaw() accepts an 16-bit integer and encodes it as A-law data.
|
||||
*
|
||||
* Linear Input Code Compressed Code
|
||||
* ------------------------ ---------------
|
||||
* 0000000wxyza 000wxyz
|
||||
* 0000001wxyza 001wxyz
|
||||
* 000001wxyzab 010wxyz
|
||||
* 00001wxyzabc 011wxyz
|
||||
* 0001wxyzabcd 100wxyz
|
||||
* 001wxyzabcde 101wxyz
|
||||
* 01wxyzabcdef 110wxyz
|
||||
* 1wxyzabcdefg 111wxyz
|
||||
*
|
||||
* For further information see John C. Bellamy's Digital Telephony, 1982,
|
||||
* John Wiley & Sons, pps 98-111 and 472-476.
|
||||
*/
|
||||
unsigned char
|
||||
linear2alaw(
|
||||
int pcm_val) /* 2's complement (16-bit range) */
|
||||
{
|
||||
int mask;
|
||||
int seg;
|
||||
unsigned char aval;
|
||||
|
||||
if (pcm_val >= 0) {
|
||||
mask = 0xD5; /* sign (7th) bit = 1 */
|
||||
} else {
|
||||
mask = 0x55; /* sign bit = 0 */
|
||||
pcm_val = -pcm_val - 8;
|
||||
}
|
||||
|
||||
/* Convert the scaled magnitude to segment number. */
|
||||
seg = search(pcm_val, seg_end, 8);
|
||||
|
||||
/* Combine the sign, segment, and quantization bits. */
|
||||
|
||||
if (seg >= 8) /* out of range, return maximum value. */
|
||||
return (0x7F ^ mask);
|
||||
else {
|
||||
aval = seg << SEG_SHIFT;
|
||||
if (seg < 2)
|
||||
aval |= (pcm_val >> 4) & QUANT_MASK;
|
||||
else
|
||||
aval |= (pcm_val >> (seg + 3)) & QUANT_MASK;
|
||||
return (aval ^ mask);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* alaw2linear() - Convert an A-law value to 16-bit linear PCM
|
||||
*
|
||||
*/
|
||||
int
|
||||
alaw2linear(
|
||||
unsigned char a_val)
|
||||
{
|
||||
int t;
|
||||
int seg;
|
||||
|
||||
a_val ^= 0x55;
|
||||
|
||||
t = (a_val & QUANT_MASK) << 4;
|
||||
seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
|
||||
switch (seg) {
|
||||
case 0:
|
||||
t += 8;
|
||||
break;
|
||||
case 1:
|
||||
t += 0x108;
|
||||
break;
|
||||
default:
|
||||
t += 0x108;
|
||||
t <<= seg - 1;
|
||||
}
|
||||
return ((a_val & SIGN_BIT) ? t : -t);
|
||||
}
|
||||
|
||||
#define BIAS (0x84) /* Bias for linear code. */
|
||||
|
||||
/*
|
||||
* linear2ulaw() - Convert a linear PCM value to u-law
|
||||
*
|
||||
* In order to simplify the encoding process, the original linear magnitude
|
||||
* is biased by adding 33 which shifts the encoding range from (0 - 8158) to
|
||||
* (33 - 8191). The result can be seen in the following encoding table:
|
||||
*
|
||||
* Biased Linear Input Code Compressed Code
|
||||
* ------------------------ ---------------
|
||||
* 00000001wxyza 000wxyz
|
||||
* 0000001wxyzab 001wxyz
|
||||
* 000001wxyzabc 010wxyz
|
||||
* 00001wxyzabcd 011wxyz
|
||||
* 0001wxyzabcde 100wxyz
|
||||
* 001wxyzabcdef 101wxyz
|
||||
* 01wxyzabcdefg 110wxyz
|
||||
* 1wxyzabcdefgh 111wxyz
|
||||
*
|
||||
* Each biased linear code has a leading 1 which identifies the segment
|
||||
* number. The value of the segment number is equal to 7 minus the number
|
||||
* of leading 0's. The quantization interval is directly available as the
|
||||
* four bits wxyz. * The trailing bits (a - h) are ignored.
|
||||
*
|
||||
* Ordinarily the complement of the resulting code word is used for
|
||||
* transmission, and so the code word is complemented before it is returned.
|
||||
*
|
||||
* For further information see John C. Bellamy's Digital Telephony, 1982,
|
||||
* John Wiley & Sons, pps 98-111 and 472-476.
|
||||
*/
|
||||
unsigned char
|
||||
linear2ulaw(
|
||||
int pcm_val) /* 2's complement (16-bit range) */
|
||||
{
|
||||
int mask;
|
||||
int seg;
|
||||
unsigned char uval;
|
||||
|
||||
/* Get the sign and the magnitude of the value. */
|
||||
if (pcm_val < 0) {
|
||||
pcm_val = BIAS - pcm_val;
|
||||
mask = 0x7F;
|
||||
} else {
|
||||
pcm_val += BIAS;
|
||||
mask = 0xFF;
|
||||
}
|
||||
|
||||
/* Convert the scaled magnitude to segment number. */
|
||||
seg = search(pcm_val, seg_end, 8);
|
||||
|
||||
/*
|
||||
* Combine the sign, segment, quantization bits;
|
||||
* and complement the code word.
|
||||
*/
|
||||
if (seg >= 8) /* out of range, return maximum value. */
|
||||
return (0x7F ^ mask);
|
||||
else {
|
||||
uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
|
||||
return (uval ^ mask);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* ulaw2linear() - Convert a u-law value to 16-bit linear PCM
|
||||
*
|
||||
* First, a biased linear code is derived from the code word. An unbiased
|
||||
* output can then be obtained by subtracting 33 from the biased code.
|
||||
*
|
||||
* Note that this function expects to be passed the complement of the
|
||||
* original code word. This is in keeping with ISDN conventions.
|
||||
*/
|
||||
int
|
||||
ulaw2linear(
|
||||
unsigned char u_val)
|
||||
{
|
||||
int t;
|
||||
|
||||
/* Complement to obtain normal u-law value. */
|
||||
u_val = ~u_val;
|
||||
|
||||
/*
|
||||
* Extract and bias the quantization bits. Then
|
||||
* shift up by the segment number and subtract out the bias.
|
||||
*/
|
||||
t = ((u_val & QUANT_MASK) << 3) + BIAS;
|
||||
t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
|
||||
|
||||
return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
|
||||
}
|
||||
|
||||
/* A-law to u-law conversion */
|
||||
unsigned char
|
||||
alaw2ulaw(
|
||||
unsigned char aval)
|
||||
{
|
||||
aval &= 0xff;
|
||||
return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) :
|
||||
(0x7F ^ _a2u[aval ^ 0x55]));
|
||||
}
|
||||
|
||||
/* u-law to A-law conversion */
|
||||
unsigned char
|
||||
ulaw2alaw(
|
||||
unsigned char uval)
|
||||
{
|
||||
uval &= 0xff;
|
||||
return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) :
|
||||
(0x55 ^ (_u2a[0x7F ^ uval] - 1)));
|
||||
}
|
@@ -1,175 +0,0 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
/*
|
||||
* g721.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* g721_encoder(), g721_decoder()
|
||||
*
|
||||
* These routines comprise an implementation of the CCITT G.721 ADPCM
|
||||
* coding algorithm. Essentially, this implementation is identical to
|
||||
* the bit level description except for a few deviations which
|
||||
* take advantage of work station attributes, such as hardware 2's
|
||||
* complement arithmetic and large memory. Specifically, certain time
|
||||
* consuming operations such as multiplications are replaced
|
||||
* with lookup tables and software 2's complement operations are
|
||||
* replaced with hardware 2's complement.
|
||||
*
|
||||
* The deviation from the bit level specification (lookup tables)
|
||||
* preserves the bit level performance specifications.
|
||||
*
|
||||
* As outlined in the G.721 Recommendation, the algorithm is broken
|
||||
* down into modules. Each section of code below is preceded by
|
||||
* the name of the module which it is implementing.
|
||||
*
|
||||
*/
|
||||
#include "g72x.h"
|
||||
|
||||
static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400};
|
||||
/*
|
||||
* Maps G.721 code word to reconstructed scale factor normalized log
|
||||
* magnitude values.
|
||||
*/
|
||||
static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425,
|
||||
425, 373, 323, 273, 213, 135, 4, -2048};
|
||||
|
||||
/* Maps G.721 code word to log of scale factor multiplier. */
|
||||
static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122,
|
||||
1122, 355, 198, 112, 64, 41, 18, -12};
|
||||
/*
|
||||
* Maps G.721 code words to a set of values whose long and short
|
||||
* term averages are computed and then compared to give an indication
|
||||
* how stationary (steady state) the signal is.
|
||||
*/
|
||||
static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00,
|
||||
0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0};
|
||||
|
||||
/*
|
||||
* g721_encoder()
|
||||
*
|
||||
* Encodes the input vale of linear PCM, A-law or u-law data sl and returns
|
||||
* the resulting code. -1 is returned for unknown input coding value.
|
||||
*/
|
||||
int
|
||||
g721_encoder(
|
||||
int sl,
|
||||
int in_coding,
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
short sezi, se, sez; /* ACCUM */
|
||||
short d; /* SUBTA */
|
||||
short sr; /* ADDB */
|
||||
short y; /* MIX */
|
||||
short dqsez; /* ADDC */
|
||||
short dq, i;
|
||||
|
||||
switch (in_coding) { /* linearize input sample to 14-bit PCM */
|
||||
case AUDIO_ENCODING_ALAW:
|
||||
sl = alaw2linear(sl) >> 2;
|
||||
break;
|
||||
case AUDIO_ENCODING_ULAW:
|
||||
sl = ulaw2linear(sl) >> 2;
|
||||
break;
|
||||
case AUDIO_ENCODING_LINEAR:
|
||||
sl = ((short)sl) >> 2; /* 14-bit dynamic range */
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */
|
||||
|
||||
d = sl - se; /* estimation difference */
|
||||
|
||||
/* quantize the prediction difference */
|
||||
y = step_size(state_ptr); /* quantizer step size */
|
||||
i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */
|
||||
|
||||
dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */
|
||||
|
||||
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */
|
||||
|
||||
dqsez = sr + sez - se; /* pole prediction diff. */
|
||||
|
||||
update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* g721_decoder()
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Decodes a 4-bit code of G.721 encoded data of i and
|
||||
* returns the resulting linear PCM, A-law or u-law value.
|
||||
* return -1 for unknown out_coding value.
|
||||
*/
|
||||
int
|
||||
g721_decoder(
|
||||
int i,
|
||||
int out_coding,
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
short sezi, sei, sez, se; /* ACCUM */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dq;
|
||||
short dqsez;
|
||||
|
||||
i &= 0x0f; /* mask to get proper bits */
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
y = step_size(state_ptr); /* dynamic quantizer step size */
|
||||
|
||||
dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */
|
||||
|
||||
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */
|
||||
|
||||
dqsez = sr - se + sez; /* pole prediction diff. */
|
||||
|
||||
update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
switch (out_coding) {
|
||||
case AUDIO_ENCODING_ALAW:
|
||||
return (tandem_adjust_alaw(sr, se, y, i, 8, qtab_721));
|
||||
case AUDIO_ENCODING_ULAW:
|
||||
return (tandem_adjust_ulaw(sr, se, y, i, 8, qtab_721));
|
||||
case AUDIO_ENCODING_LINEAR:
|
||||
return (sr << 2); /* sr was 14-bit dynamic range */
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
@@ -1,159 +0,0 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* g723_24.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* g723_24_encoder(), g723_24_decoder()
|
||||
*
|
||||
* These routines comprise an implementation of the CCITT G.723 24 Kbps
|
||||
* ADPCM coding algorithm. Essentially, this implementation is identical to
|
||||
* the bit level description except for a few deviations which take advantage
|
||||
* of workstation attributes, such as hardware 2's complement arithmetic.
|
||||
*
|
||||
*/
|
||||
#include <wx/wxprec.h>
|
||||
#include "g72x.h"
|
||||
|
||||
/*
|
||||
* Maps G.723_24 code word to reconstructed scale factor normalized log
|
||||
* magnitude values.
|
||||
*/
|
||||
static short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048};
|
||||
|
||||
/* Maps G.723_24 code word to log of scale factor multiplier. */
|
||||
static short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128};
|
||||
|
||||
/*
|
||||
* Maps G.723_24 code words to a set of values whose long and short
|
||||
* term averages are computed and then compared to give an indication
|
||||
* how stationary (steady state) the signal is.
|
||||
*/
|
||||
static short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0};
|
||||
|
||||
static short qtab_723_24[3] = {8, 218, 331};
|
||||
|
||||
/*
|
||||
* g723_24_encoder()
|
||||
*
|
||||
* Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code.
|
||||
* Returns -1 if invalid input coding value.
|
||||
*/
|
||||
int
|
||||
g723_24_encoder(
|
||||
int sl,
|
||||
int in_coding,
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
short sei, sezi, se, sez; /* ACCUM */
|
||||
short d; /* SUBTA */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dqsez; /* ADDC */
|
||||
short dq, i;
|
||||
|
||||
switch (in_coding) { /* linearize input sample to 14-bit PCM */
|
||||
case AUDIO_ENCODING_ALAW:
|
||||
sl = alaw2linear(sl) >> 2;
|
||||
break;
|
||||
case AUDIO_ENCODING_ULAW:
|
||||
sl = ulaw2linear(sl) >> 2;
|
||||
break;
|
||||
case AUDIO_ENCODING_LINEAR:
|
||||
sl = ((short)sl) >> 2; /* sl of 14-bit dynamic range */
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
d = sl - se; /* d = estimation diff. */
|
||||
|
||||
/* quantize prediction difference d */
|
||||
y = step_size(state_ptr); /* quantizer step size */
|
||||
i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */
|
||||
dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */
|
||||
|
||||
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */
|
||||
|
||||
dqsez = sr + sez - se; /* pole prediction diff. */
|
||||
|
||||
update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* g723_24_decoder()
|
||||
*
|
||||
* Decodes a 3-bit CCITT G.723_24 ADPCM code and returns
|
||||
* the resulting 16-bit linear PCM, A-law or u-law sample value.
|
||||
* -1 is returned if the output coding is unknown.
|
||||
*/
|
||||
int
|
||||
g723_24_decoder(
|
||||
int i,
|
||||
int out_coding,
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
short sezi, sei, sez, se; /* ACCUM */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dq;
|
||||
short dqsez;
|
||||
|
||||
i &= 0x07; /* mask to get proper bits */
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
y = step_size(state_ptr); /* adaptive quantizer step size */
|
||||
dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */
|
||||
|
||||
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */
|
||||
|
||||
dqsez = sr - se + sez; /* pole prediction diff. */
|
||||
|
||||
update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
switch (out_coding) {
|
||||
case AUDIO_ENCODING_ALAW:
|
||||
return (tandem_adjust_alaw(sr, se, y, i, 4, qtab_723_24));
|
||||
case AUDIO_ENCODING_ULAW:
|
||||
return (tandem_adjust_ulaw(sr, se, y, i, 4, qtab_723_24));
|
||||
case AUDIO_ENCODING_LINEAR:
|
||||
return (sr << 2); /* sr was of 14-bit dynamic range */
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
@@ -1,179 +0,0 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* g723_40.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* g723_40_encoder(), g723_40_decoder()
|
||||
*
|
||||
* These routines comprise an implementation of the CCITT G.723 40Kbps
|
||||
* ADPCM coding algorithm. Essentially, this implementation is identical to
|
||||
* the bit level description except for a few deviations which
|
||||
* take advantage of workstation attributes, such as hardware 2's
|
||||
* complement arithmetic.
|
||||
*
|
||||
* The deviation from the bit level specification (lookup tables),
|
||||
* preserves the bit level performance specifications.
|
||||
*
|
||||
* As outlined in the G.723 Recommendation, the algorithm is broken
|
||||
* down into modules. Each section of code below is preceded by
|
||||
* the name of the module which it is implementing.
|
||||
*
|
||||
*/
|
||||
#include <wx/wxprec.h>
|
||||
#include "g72x.h"
|
||||
|
||||
/*
|
||||
* Maps G.723_40 code word to ructeconstructed scale factor normalized log
|
||||
* magnitude values.
|
||||
*/
|
||||
static short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318,
|
||||
358, 395, 429, 459, 488, 514, 539, 566,
|
||||
566, 539, 514, 488, 459, 429, 395, 358,
|
||||
318, 274, 224, 169, 104, 28, -66, -2048};
|
||||
|
||||
/* Maps G.723_40 code word to log of scale factor multiplier. */
|
||||
static short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200,
|
||||
4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272,
|
||||
22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512,
|
||||
3200, 1856, 1312, 1280, 1248, 768, 448, 448};
|
||||
|
||||
/*
|
||||
* Maps G.723_40 code words to a set of values whose long and short
|
||||
* term averages are computed and then compared to give an indication
|
||||
* how stationary (steady state) the signal is.
|
||||
*/
|
||||
static short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200,
|
||||
0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00,
|
||||
0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200,
|
||||
0x200, 0x200, 0x200, 0, 0, 0, 0, 0};
|
||||
|
||||
static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339,
|
||||
378, 413, 445, 475, 502, 528, 553};
|
||||
|
||||
/*
|
||||
* g723_40_encoder()
|
||||
*
|
||||
* Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens
|
||||
* the resulting 5-bit CCITT G.723 40Kbps code.
|
||||
* Returns -1 if the input coding value is invalid.
|
||||
*/
|
||||
int
|
||||
g723_40_encoder(
|
||||
int sl,
|
||||
int in_coding,
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
short sei, sezi, se, sez; /* ACCUM */
|
||||
short d; /* SUBTA */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dqsez; /* ADDC */
|
||||
short dq, i;
|
||||
|
||||
switch (in_coding) { /* linearize input sample to 14-bit PCM */
|
||||
case AUDIO_ENCODING_ALAW:
|
||||
sl = alaw2linear(sl) >> 2;
|
||||
break;
|
||||
case AUDIO_ENCODING_ULAW:
|
||||
sl = ulaw2linear(sl) >> 2;
|
||||
break;
|
||||
case AUDIO_ENCODING_LINEAR:
|
||||
sl = ((short) sl) >> 2; /* sl of 14-bit dynamic range */
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
d = sl - se; /* d = estimation difference */
|
||||
|
||||
/* quantize prediction difference */
|
||||
y = step_size(state_ptr); /* adaptive quantizer step size */
|
||||
i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */
|
||||
|
||||
dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */
|
||||
|
||||
sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */
|
||||
|
||||
dqsez = sr + sez - se; /* dqsez = pole prediction diff. */
|
||||
|
||||
update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* g723_40_decoder()
|
||||
*
|
||||
* Decodes a 5-bit CCITT G.723 40Kbps code and returns
|
||||
* the resulting 16-bit linear PCM, A-law or u-law sample value.
|
||||
* -1 is returned if the output coding is unknown.
|
||||
*/
|
||||
int
|
||||
g723_40_decoder(
|
||||
int i,
|
||||
int out_coding,
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
short sezi, sei, sez, se; /* ACCUM */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dq;
|
||||
short dqsez;
|
||||
|
||||
i &= 0x1f; /* mask to get proper bits */
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
y = step_size(state_ptr); /* adaptive quantizer step size */
|
||||
dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */
|
||||
|
||||
sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */
|
||||
|
||||
dqsez = sr - se + sez; /* pole prediction diff. */
|
||||
|
||||
update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
switch (out_coding) {
|
||||
case AUDIO_ENCODING_ALAW:
|
||||
return (tandem_adjust_alaw(sr, se, y, i, 0x10, qtab_723_40));
|
||||
case AUDIO_ENCODING_ULAW:
|
||||
return (tandem_adjust_ulaw(sr, se, y, i, 0x10, qtab_723_40));
|
||||
case AUDIO_ENCODING_LINEAR:
|
||||
return (sr << 2); /* sr was of 14-bit dynamic range */
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
@@ -1,608 +0,0 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* g72x.c
|
||||
*
|
||||
* Common routines for G.721 and G.723 conversions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "g72x.h"
|
||||
|
||||
static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
|
||||
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000};
|
||||
|
||||
/*
|
||||
* quan()
|
||||
*
|
||||
* quantizes the input val against the table of size short integers.
|
||||
* It returns i if table[i - 1] <= val < table[i].
|
||||
*
|
||||
* Using linear search for simple coding.
|
||||
*/
|
||||
static int
|
||||
quan(
|
||||
int val,
|
||||
short *table,
|
||||
int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
if (val < *table++)
|
||||
break;
|
||||
return (i);
|
||||
}
|
||||
|
||||
static char quan2_tab[65536];
|
||||
static short base2_tab[65536];
|
||||
static int init_tabs_done = 0;
|
||||
|
||||
inline char quan2 (unsigned short val)
|
||||
{
|
||||
return quan2_tab[val];
|
||||
}
|
||||
|
||||
inline short base2 (unsigned short val)
|
||||
{
|
||||
return base2_tab[val];
|
||||
}
|
||||
|
||||
static void init_quan2_tab (void)
|
||||
{
|
||||
long i;
|
||||
|
||||
for (i = 0; i < 65536; i++) {
|
||||
quan2_tab[i] = quan (i, power2, 15);
|
||||
};
|
||||
}
|
||||
|
||||
static void init_base2_tab (void)
|
||||
{
|
||||
long i;
|
||||
short exp;
|
||||
|
||||
for (i = 0; i < 65536; i++) {
|
||||
exp = quan2 (short (i));
|
||||
base2_tab[i] = short ((exp << 6) + ((i << 6) >> exp));
|
||||
};
|
||||
}
|
||||
|
||||
static void init_tabs (void)
|
||||
{
|
||||
if (init_tabs_done) return;
|
||||
|
||||
init_quan2_tab();
|
||||
init_base2_tab();
|
||||
|
||||
init_tabs_done = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* fmult()
|
||||
*
|
||||
* returns the integer product of the 14-bit integer "an" and
|
||||
* "floating point" representation (4-bit exponent, 6-bit mantessa) "srn".
|
||||
*/
|
||||
static int
|
||||
fmult(
|
||||
int an,
|
||||
int srn)
|
||||
{
|
||||
short anmag, anexp, anmant;
|
||||
short wanexp, wanmant;
|
||||
short retval;
|
||||
|
||||
anmag = (an > 0) ? an : ((-an) & 0x1FFF);
|
||||
anexp = quan2(anmag) - 6;
|
||||
anmant = (anmag == 0) ? 32 :
|
||||
(anexp >= 0) ? anmag >> anexp : anmag << -anexp;
|
||||
wanexp = anexp + ((srn >> 6) & 0xF) - 13;
|
||||
|
||||
wanmant = (anmant * (srn & 077) + 0x30) >> 4;
|
||||
retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) :
|
||||
(wanmant >> -wanexp);
|
||||
|
||||
return (((an ^ srn) < 0) ? -retval : retval);
|
||||
}
|
||||
|
||||
/*
|
||||
* g72x_init_state()
|
||||
*
|
||||
* This routine initializes and/or resets the g72x_state structure
|
||||
* pointed to by 'state_ptr'.
|
||||
* All the initial state values are specified in the CCITT G.721 document.
|
||||
*/
|
||||
void
|
||||
g72x_init_state(
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
int cnta;
|
||||
|
||||
init_tabs ();
|
||||
|
||||
state_ptr->yl = 34816;
|
||||
state_ptr->yu = 544;
|
||||
state_ptr->dms = 0;
|
||||
state_ptr->dml = 0;
|
||||
state_ptr->ap = 0;
|
||||
for (cnta = 0; cnta < 2; cnta++) {
|
||||
state_ptr->a[cnta] = 0;
|
||||
state_ptr->pk[cnta] = 0;
|
||||
state_ptr->sr[cnta] = 32;
|
||||
}
|
||||
for (cnta = 0; cnta < 6; cnta++) {
|
||||
state_ptr->b[cnta] = 0;
|
||||
state_ptr->dq[cnta] = 32;
|
||||
}
|
||||
state_ptr->td = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* predictor_zero()
|
||||
*
|
||||
* computes the estimated signal from 6-zero predictor.
|
||||
*
|
||||
*/
|
||||
int
|
||||
predictor_zero(
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
int i;
|
||||
int sezi;
|
||||
|
||||
sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]);
|
||||
for (i = 1; i < 6; i++) /* ACCUM */
|
||||
sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
|
||||
return (sezi);
|
||||
}
|
||||
/*
|
||||
* predictor_pole()
|
||||
*
|
||||
* computes the estimated signal from 2-pole predictor.
|
||||
*
|
||||
*/
|
||||
int
|
||||
predictor_pole(
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
|
||||
fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
|
||||
}
|
||||
/*
|
||||
* step_size()
|
||||
*
|
||||
* computes the quantization step size of the adaptive quantizer.
|
||||
*
|
||||
*/
|
||||
int
|
||||
step_size(
|
||||
struct g72x_state *state_ptr)
|
||||
{
|
||||
int y;
|
||||
int dif;
|
||||
int al;
|
||||
|
||||
if (state_ptr->ap >= 256)
|
||||
return (state_ptr->yu);
|
||||
else {
|
||||
y = state_ptr->yl >> 6;
|
||||
dif = state_ptr->yu - y;
|
||||
al = state_ptr->ap >> 2;
|
||||
if (dif > 0)
|
||||
y += (dif * al) >> 6;
|
||||
else if (dif < 0)
|
||||
y += (dif * al + 0x3F) >> 6;
|
||||
return (y);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* quantize()
|
||||
*
|
||||
* Given a raw sample, 'd', of the difference signal and a
|
||||
* quantization step size scale factor, 'y', this routine returns the
|
||||
* ADPCM codeword to which that sample gets quantized. The step
|
||||
* size scale factor division operation is done in the log base 2 domain
|
||||
* as a subtraction.
|
||||
*/
|
||||
int
|
||||
quantize(
|
||||
int d, /* Raw difference signal sample */
|
||||
int y, /* Step size multiplier */
|
||||
short *table, /* quantization table */
|
||||
int size) /* table size of short integers */
|
||||
{
|
||||
short dqm; /* Magnitude of 'd' */
|
||||
short exp; /* Integer part of base 2 log of 'd' */
|
||||
short mant; /* Fractional part of base 2 log */
|
||||
short dl; /* Log of magnitude of 'd' */
|
||||
short dln; /* Step size scale factor normalized log */
|
||||
int i;
|
||||
|
||||
/*
|
||||
* LOG
|
||||
*
|
||||
* Compute base 2 log of 'd', and store in 'dl'.
|
||||
*/
|
||||
dqm = abs(d);
|
||||
exp = quan2(dqm >> 1);
|
||||
mant = ((dqm << 7) >> exp) & 0x7F; /* Fractional portion. */
|
||||
dl = (exp << 7) + mant;
|
||||
|
||||
/*
|
||||
* SUBTB
|
||||
*
|
||||
* "Divide" by step size multiplier.
|
||||
*/
|
||||
dln = dl - (y >> 2);
|
||||
|
||||
/*
|
||||
* QUAN
|
||||
*
|
||||
* Obtain codword i for 'd'.
|
||||
*/
|
||||
i = quan(dln, table, size);
|
||||
if (d < 0) /* take 1's complement of i */
|
||||
return ((size << 1) + 1 - i);
|
||||
else if (i == 0) /* take 1's complement of 0 */
|
||||
return ((size << 1) + 1); /* new in 1988 */
|
||||
else
|
||||
return (i);
|
||||
}
|
||||
/*
|
||||
* reconstruct()
|
||||
*
|
||||
* Returns reconstructed difference signal 'dq' obtained from
|
||||
* codeword 'i' and quantization step size scale factor 'y'.
|
||||
* Multiplication is performed in log base 2 domain as addition.
|
||||
*/
|
||||
int
|
||||
reconstruct(
|
||||
int sign, /* 0 for non-negative value */
|
||||
int dqln, /* G.72x codeword */
|
||||
int y) /* Step size multiplier */
|
||||
{
|
||||
short dql; /* Log of 'dq' magnitude */
|
||||
short dex; /* Integer part of log */
|
||||
short dqt;
|
||||
short dq; /* Reconstructed difference signal sample */
|
||||
|
||||
dql = dqln + (y >> 2); /* ADDA */
|
||||
|
||||
if (dql < 0) {
|
||||
return ((sign) ? -0x8000 : 0);
|
||||
} else { /* ANTILOG */
|
||||
dex = (dql >> 7) & 15;
|
||||
dqt = 128 + (dql & 127);
|
||||
dq = (dqt << 7) >> (14 - dex);
|
||||
return ((sign) ? (dq - 0x8000) : dq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* update()
|
||||
*
|
||||
* updates the state variables for each output code
|
||||
*/
|
||||
void
|
||||
update(
|
||||
int code_size, /* distinguish 723_40 with others */
|
||||
int y, /* quantizer step size */
|
||||
int wi, /* scale factor multiplier */
|
||||
int fi, /* for long/short term energies */
|
||||
int dq, /* quantized prediction difference */
|
||||
int sr, /* reconstructed signal */
|
||||
int dqsez, /* difference from 2-pole predictor */
|
||||
struct g72x_state *state_ptr) /* coder state pointer */
|
||||
{
|
||||
int cnt;
|
||||
short mag; /* Adaptive predictor, FLOAT A */
|
||||
short a2p; /* LIMC */
|
||||
short a1ul; /* UPA1 */
|
||||
short pks1; /* UPA2 */
|
||||
short fa1;
|
||||
char tr; /* tone/transition detector */
|
||||
short ylint, thr2, dqthr;
|
||||
short ylfrac, thr1;
|
||||
short pk0;
|
||||
|
||||
pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */
|
||||
|
||||
mag = dq & 0x7FFF; /* prediction difference magnitude */
|
||||
/* TRANS */
|
||||
ylint = short (state_ptr->yl >> 15); /* exponent part of yl */
|
||||
ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */
|
||||
thr1 = (32 + ylfrac) << ylint; /* threshold */
|
||||
thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */
|
||||
dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */
|
||||
if (state_ptr->td == 0) /* signal supposed voice */
|
||||
tr = 0;
|
||||
else if (mag <= dqthr) /* supposed data, but small mag */
|
||||
tr = 0; /* treated as voice */
|
||||
else /* signal is data (modem) */
|
||||
tr = 1;
|
||||
|
||||
/*
|
||||
* Quantizer scale factor adaptation.
|
||||
*/
|
||||
|
||||
/* FUNCTW & FILTD & DELAY */
|
||||
/* update non-steady state step size multiplier */
|
||||
state_ptr->yu = y + ((wi - y) >> 5);
|
||||
|
||||
/* LIMB */
|
||||
if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */
|
||||
state_ptr->yu = 544;
|
||||
else if (state_ptr->yu > 5120)
|
||||
state_ptr->yu = 5120;
|
||||
|
||||
/* FILTE & DELAY */
|
||||
/* update steady state step size multiplier */
|
||||
state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);
|
||||
|
||||
/*
|
||||
* Adaptive predictor coefficients.
|
||||
*/
|
||||
if (tr == 1) { /* reset a's and b's for modem signal */
|
||||
state_ptr->a[0] = 0;
|
||||
state_ptr->a[1] = 0;
|
||||
state_ptr->b[0] = 0;
|
||||
state_ptr->b[1] = 0;
|
||||
state_ptr->b[2] = 0;
|
||||
state_ptr->b[3] = 0;
|
||||
state_ptr->b[4] = 0;
|
||||
state_ptr->b[5] = 0;
|
||||
|
||||
a2p = 0; /* eliminate Compiler Warnings */
|
||||
} else { /* update a's and b's */
|
||||
pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */
|
||||
|
||||
/* update predictor pole a[1] */
|
||||
a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
|
||||
if (dqsez != 0) {
|
||||
fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
|
||||
if (fa1 < -8191) /* a2p = function of fa1 */
|
||||
a2p -= 0x100;
|
||||
else if (fa1 > 8191)
|
||||
a2p += 0xFF;
|
||||
else
|
||||
a2p += fa1 >> 5;
|
||||
|
||||
if (pk0 ^ state_ptr->pk[1])
|
||||
/* LIMC */
|
||||
if (a2p <= -12160)
|
||||
a2p = -12288;
|
||||
else if (a2p >= 12416)
|
||||
a2p = 12288;
|
||||
else
|
||||
a2p -= 0x80;
|
||||
else if (a2p <= -12416)
|
||||
a2p = -12288;
|
||||
else if (a2p >= 12160)
|
||||
a2p = 12288;
|
||||
else
|
||||
a2p += 0x80;
|
||||
}
|
||||
|
||||
/* TRIGB & DELAY */
|
||||
state_ptr->a[1] = a2p;
|
||||
|
||||
/* UPA1 */
|
||||
/* update predictor pole a[0] */
|
||||
state_ptr->a[0] -= state_ptr->a[0] >> 8;
|
||||
if (dqsez != 0)
|
||||
if (pks1 == 0)
|
||||
state_ptr->a[0] += 192;
|
||||
else
|
||||
state_ptr->a[0] -= 192;
|
||||
|
||||
/* LIMD */
|
||||
a1ul = 15360 - a2p;
|
||||
if (state_ptr->a[0] < -a1ul)
|
||||
state_ptr->a[0] = -a1ul;
|
||||
else if (state_ptr->a[0] > a1ul)
|
||||
state_ptr->a[0] = a1ul;
|
||||
|
||||
/* UPB : update predictor zeros b[6] */
|
||||
for (cnt = 0; cnt < 6; cnt++) {
|
||||
if (code_size == 5) /* for 40Kbps G.723 */
|
||||
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;
|
||||
else /* for G.721 and 24Kbps G.723 */
|
||||
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
|
||||
if (dq & 0x7FFF) { /* XOR */
|
||||
if ((dq ^ state_ptr->dq[cnt]) >= 0)
|
||||
state_ptr->b[cnt] += 128;
|
||||
else
|
||||
state_ptr->b[cnt] -= 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (cnt = 5; cnt > 0; cnt--)
|
||||
state_ptr->dq[cnt] = state_ptr->dq[cnt-1];
|
||||
/* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */
|
||||
if (mag == 0) {
|
||||
state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20;
|
||||
} else {
|
||||
state_ptr->dq[0] = (dq >= 0) ?
|
||||
base2 (mag) : base2 (mag) - 0x400;
|
||||
}
|
||||
|
||||
state_ptr->sr[1] = state_ptr->sr[0];
|
||||
/* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */
|
||||
if (sr == 0) {
|
||||
state_ptr->sr[0] = 0x20;
|
||||
} else if (sr > 0) {
|
||||
state_ptr->sr[0] = base2(sr);
|
||||
} else if (sr > -32768) {
|
||||
mag = -sr;
|
||||
state_ptr->sr[0] = base2(mag) - 0x400;
|
||||
} else
|
||||
state_ptr->sr[0] = short (0xFC20);
|
||||
|
||||
/* DELAY A */
|
||||
state_ptr->pk[1] = state_ptr->pk[0];
|
||||
state_ptr->pk[0] = pk0;
|
||||
|
||||
/* TONE */
|
||||
if (tr == 1) /* this sample has been treated as data */
|
||||
state_ptr->td = 0; /* next one will be treated as voice */
|
||||
else if (a2p < -11776) /* small sample-to-sample correlation */
|
||||
state_ptr->td = 1; /* signal may be data */
|
||||
else /* signal is voice */
|
||||
state_ptr->td = 0;
|
||||
|
||||
/*
|
||||
* Adaptation speed control.
|
||||
*/
|
||||
state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */
|
||||
state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */
|
||||
|
||||
if (tr == 1)
|
||||
state_ptr->ap = 256;
|
||||
else if (y < 1536) /* SUBTC */
|
||||
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
|
||||
else if (state_ptr->td == 1)
|
||||
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
|
||||
else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
|
||||
(state_ptr->dml >> 3))
|
||||
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
|
||||
else
|
||||
state_ptr->ap += (-state_ptr->ap) >> 4;
|
||||
}
|
||||
|
||||
/*
|
||||
* tandem_adjust(sr, se, y, i, sign)
|
||||
*
|
||||
* At the end of ADPCM decoding, it simulates an encoder which may be receiving
|
||||
* the output of this decoder as a tandem process. If the output of the
|
||||
* simulated encoder differs from the input to this decoder, the decoder output
|
||||
* is adjusted by one level of A-law or u-law codes.
|
||||
*
|
||||
* Input:
|
||||
* sr decoder output linear PCM sample,
|
||||
* se predictor estimate sample,
|
||||
* y quantizer step size,
|
||||
* i decoder input code,
|
||||
* sign sign bit of code i
|
||||
*
|
||||
* Return:
|
||||
* adjusted A-law or u-law compressed sample.
|
||||
*/
|
||||
int
|
||||
tandem_adjust_alaw(
|
||||
int sr, /* decoder output linear PCM sample */
|
||||
int se, /* predictor estimate sample */
|
||||
int y, /* quantizer step size */
|
||||
int i, /* decoder input code */
|
||||
int sign,
|
||||
short *qtab)
|
||||
{
|
||||
unsigned char sp; /* A-law compressed 8-bit code */
|
||||
short dx; /* prediction error */
|
||||
char id; /* quantized prediction error */
|
||||
int sd; /* adjusted A-law decoded sample value */
|
||||
int im; /* biased magnitude of i */
|
||||
int imx; /* biased magnitude of id */
|
||||
|
||||
if (sr <= -32768)
|
||||
sr = -1;
|
||||
sp = linear2alaw((sr >> 1) << 3); /* short to A-law compression */
|
||||
dx = (alaw2linear(sp) >> 2) - se; /* 16-bit prediction error */
|
||||
id = quantize(dx, y, qtab, sign - 1);
|
||||
|
||||
if (id == i) { /* no adjustment on sp */
|
||||
return (sp);
|
||||
} else { /* sp adjustment needed */
|
||||
/* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
|
||||
im = i ^ sign; /* 2's complement to biased unsigned */
|
||||
imx = id ^ sign;
|
||||
|
||||
if (imx > im) { /* sp adjusted to next lower value */
|
||||
if (sp & 0x80) {
|
||||
sd = (sp == 0xD5) ? 0x55 :
|
||||
((sp ^ 0x55) - 1) ^ 0x55;
|
||||
} else {
|
||||
sd = (sp == 0x2A) ? 0x2A :
|
||||
((sp ^ 0x55) + 1) ^ 0x55;
|
||||
}
|
||||
} else { /* sp adjusted to next higher value */
|
||||
if (sp & 0x80)
|
||||
sd = (sp == 0xAA) ? 0xAA :
|
||||
((sp ^ 0x55) + 1) ^ 0x55;
|
||||
else
|
||||
sd = (sp == 0x55) ? 0xD5 :
|
||||
((sp ^ 0x55) - 1) ^ 0x55;
|
||||
}
|
||||
return (sd);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
tandem_adjust_ulaw(
|
||||
int sr, /* decoder output linear PCM sample */
|
||||
int se, /* predictor estimate sample */
|
||||
int y, /* quantizer step size */
|
||||
int i, /* decoder input code */
|
||||
int sign,
|
||||
short *qtab)
|
||||
{
|
||||
unsigned char sp; /* u-law compressed 8-bit code */
|
||||
short dx; /* prediction error */
|
||||
char id; /* quantized prediction error */
|
||||
int sd; /* adjusted u-law decoded sample value */
|
||||
int im; /* biased magnitude of i */
|
||||
int imx; /* biased magnitude of id */
|
||||
|
||||
if (sr <= -32768)
|
||||
sr = 0;
|
||||
sp = linear2ulaw(sr << 2); /* short to u-law compression */
|
||||
dx = (ulaw2linear(sp) >> 2) - se; /* 16-bit prediction error */
|
||||
id = quantize(dx, y, qtab, sign - 1);
|
||||
if (id == i) {
|
||||
return (sp);
|
||||
} else {
|
||||
/* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */
|
||||
im = i ^ sign; /* 2's complement to biased unsigned */
|
||||
imx = id ^ sign;
|
||||
if (imx > im) { /* sp adjusted to next lower value */
|
||||
if (sp & 0x80)
|
||||
sd = (sp == 0xFF) ? 0x7E : sp + 1;
|
||||
else
|
||||
sd = (sp == 0) ? 0 : sp - 1;
|
||||
|
||||
} else { /* sp adjusted to next higher value */
|
||||
if (sp & 0x80)
|
||||
sd = (sp == 0x80) ? 0x80 : sp - 1;
|
||||
else
|
||||
sd = (sp == 0x7F) ? 0xFE : sp + 1;
|
||||
}
|
||||
return (sd);
|
||||
}
|
||||
}
|
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* g72x.h
|
||||
*
|
||||
* Header file for CCITT conversion routines.
|
||||
*
|
||||
*/
|
||||
#ifndef _G72X_H
|
||||
#define _G72X_H
|
||||
|
||||
#define AUDIO_ENCODING_ULAW (1) /* ISDN u-law */
|
||||
#define AUDIO_ENCODING_ALAW (2) /* ISDN A-law */
|
||||
#define AUDIO_ENCODING_LINEAR (3) /* PCM 2's-complement (0-center) */
|
||||
|
||||
/*
|
||||
* The following is the definition of the state structure
|
||||
* used by the G.721/G.723 encoder and decoder to preserve their internal
|
||||
* state between successive calls. The meanings of the majority
|
||||
* of the state structure fields are explained in detail in the
|
||||
* CCITT Recommendation G.721. The field names are essentially indentical
|
||||
* to variable names in the bit level description of the coding algorithm
|
||||
* included in this Recommendation.
|
||||
*/
|
||||
struct g72x_state {
|
||||
long yl; /* Locked or steady state step size multiplier. */
|
||||
short yu; /* Unlocked or non-steady state step size multiplier. */
|
||||
short dms; /* Short term energy estimate. */
|
||||
short dml; /* Long term energy estimate. */
|
||||
short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */
|
||||
|
||||
short a[2]; /* Coefficients of pole portion of prediction filter. */
|
||||
short b[6]; /* Coefficients of zero portion of prediction filter. */
|
||||
short pk[2]; /*
|
||||
* Signs of previous two samples of a partially
|
||||
* reconstructed signal.
|
||||
*/
|
||||
short dq[6]; /*
|
||||
* Previous 6 samples of the quantized difference
|
||||
* signal represented in an internal floating point
|
||||
* format.
|
||||
*/
|
||||
short sr[2]; /*
|
||||
* Previous 2 samples of the quantized difference
|
||||
* signal represented in an internal floating point
|
||||
* format.
|
||||
*/
|
||||
char td; /* delayed tone detect, new in 1988 version */
|
||||
};
|
||||
|
||||
/* External function definitions. */
|
||||
|
||||
extern unsigned char linear2alaw (int pcm_val); /* 2's complement (16-bit range) */
|
||||
extern int alaw2linear (unsigned char a_val);
|
||||
extern unsigned char linear2ulaw (int pcm_val); /* 2's complement (16-bit range) */
|
||||
extern int ulaw2linear (unsigned char u_val);
|
||||
extern int predictor_zero (struct g72x_state *state_ptr);
|
||||
extern int predictor_pole (struct g72x_state *state_ptr);
|
||||
extern int step_size (struct g72x_state *state_ptr);
|
||||
extern int quantize (int d, int y, short *table, int size);
|
||||
extern int reconstruct (int sign, int dqln, int y);
|
||||
|
||||
extern void update
|
||||
( int code_size, int y, int wi, int fi, int dq
|
||||
, int sr, int dqsez, struct g72x_state *state_ptr);
|
||||
|
||||
int tandem_adjust_alaw
|
||||
(int sr, int se, int y, int i, int sign, short *qtab);
|
||||
|
||||
int tandem_adjust_ulaw
|
||||
(int sr, int se, int y, int i, int sign, short *qtab);
|
||||
|
||||
extern void g72x_init_state (struct g72x_state *);
|
||||
extern int g721_encoder(
|
||||
int sample,
|
||||
int in_coding,
|
||||
struct g72x_state *state_ptr);
|
||||
extern int g721_decoder(
|
||||
int code,
|
||||
int out_coding,
|
||||
struct g72x_state *state_ptr);
|
||||
extern int g723_24_encoder(
|
||||
int sample,
|
||||
int in_coding,
|
||||
struct g72x_state *state_ptr);
|
||||
extern int g723_24_decoder(
|
||||
int code,
|
||||
int out_coding,
|
||||
struct g72x_state *state_ptr);
|
||||
extern int g723_40_encoder(
|
||||
int sample,
|
||||
int in_coding,
|
||||
struct g72x_state *state_ptr);
|
||||
extern int g723_40_decoder(
|
||||
int code,
|
||||
int out_coding,
|
||||
struct g72x_state *state_ptr);
|
||||
|
||||
#endif /* !_G72X_H */
|
@@ -1,30 +0,0 @@
|
||||
#
|
||||
# File: Makefile
|
||||
# Author: Guilhem Lavaux
|
||||
# Created: 1998
|
||||
# Updated:
|
||||
# Copyright: (c) 1998 Julian Smart
|
||||
#
|
||||
# "%W% %G%"
|
||||
#
|
||||
# Makefile for wxMultiMedia (UNIX).
|
||||
|
||||
# updated mcf
|
||||
|
||||
WXWIN=../../..
|
||||
|
||||
top_srcdir = ../../..
|
||||
top_builddir = ../../..
|
||||
|
||||
VPATH= $(top_srcdir)/utils/wxMMedia2/lib
|
||||
|
||||
LIBTARGET=libwxmmedia2
|
||||
|
||||
OBJECTS=sndbase.o sndcodec.o sndpcm.o sndcpcm.o sndulaw.o sndfile.o \
|
||||
sndaiff.o sndwav.o sndwin.o \
|
||||
g711.o g721.o g723_24.o g723_40.o g72x.o \
|
||||
sndg72x.o cdbase.o \
|
||||
vidbase.o
|
||||
|
||||
# include $(top_builddir)/src/makelib.env
|
||||
include $(top_builddir)/src/makelib.g95
|
@@ -1,112 +0,0 @@
|
||||
#
|
||||
# File: makefile.nt
|
||||
# Author: Julian Smart
|
||||
# Created: 1993
|
||||
# Updated:
|
||||
# Copyright: (c) 1993, AIAI, University of Edinburgh
|
||||
#
|
||||
# "%W% %G%"
|
||||
#
|
||||
# Makefile : Builds GLCanvas class library (MS VC++).
|
||||
# Use FINAL=1 argument to nmake to build final version with no debugging
|
||||
# info
|
||||
|
||||
# Set WXDIR for your system
|
||||
WXDIR = $(WXWIN)
|
||||
MMDIR = $(WXDIR)\utils\wxMMedia2
|
||||
THISDIR = $(MMDIR)\lib
|
||||
EXTRALIBS=$(WXDIR)\lib\mmedia2.lib
|
||||
|
||||
LIBTARGET=$(WXDIR)\lib\mmedia2.lib
|
||||
OBJECTS = cdbase.obj cdwin.obj g711.obj g721.obj g723_24.obj sndg72x.obj \
|
||||
g723_40.obj g72x.obj sndbase.obj sndcodec.obj sndpcm.obj \
|
||||
sndcpcm.obj sndulaw.obj sndfile.obj sndwav.obj sndaiff.obj sndwin.obj \
|
||||
vidbase.obj vidwin.obj
|
||||
|
||||
!include $(WXDIR)\src\makelib.vc
|
||||
|
||||
cdbase.obj: cdbase.h cdbase.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
cdwin.obj: cdwin.h cdwin.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
g711.obj: g72x.h g711.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
g721.obj: g72x.h g721.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
g723_24.obj: g72x.h g723_24.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
g723_40.obj: g72x.h g723_40.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
sndbase.obj: sndbase.h sndbase.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
sndcodec.obj: sndcodec.h sndcodec.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
sndpcm.obj: sndpcm.h sndpcm.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
sndcpcm.obj: sndcpcm.h converter.def sndcpcm.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
sndulaw.obj: sndulaw.h g72x.h sndulaw.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
sndfile.obj: sndfile.h sndfile.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
sndwav.obj: sndwav.h sndwav.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
sndaiff.obj: sndaiff.h sndaiff.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
sndwin.obj: sndwin.h sndwin.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
vidbase.obj: vidbase.h vidbase.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
||||
vidwin.obj: vidwin.h vidwin.$(SRCSUFF)
|
||||
$(cc) @<<
|
||||
$(CPPFLAGS) /c /Tp $*.$(SRCSUFF)
|
||||
<<
|
||||
|
@@ -1,198 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndaiff.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "sndaiff.cpp"
|
||||
#endif
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
#include <wx/stream.h>
|
||||
#include <wx/datstrm.h>
|
||||
#include <wx/filefn.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndcodec.h"
|
||||
#include "sndfile.h"
|
||||
#include "sndpcm.h"
|
||||
#include "sndaiff.h"
|
||||
|
||||
#define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
|
||||
|
||||
#define FORM_SIGNATURE BUILD_SIGNATURE('F','O','R','M')
|
||||
#define AIFF_SIGNATURE BUILD_SIGNATURE('A','I','F','F')
|
||||
#define AIFC_SIGNATURE BUILD_SIGNATURE('A','I','F','C')
|
||||
#define COMM_SIGNATURE BUILD_SIGNATURE('C','O','M','M')
|
||||
#define SSND_SIGNATURE BUILD_SIGNATURE('S','S','N','D')
|
||||
|
||||
wxSoundAiff::wxSoundAiff(wxInputStream& stream, wxSoundStream& io_sound)
|
||||
: wxSoundFileStream(stream, io_sound)
|
||||
{
|
||||
m_base_offset = wxInvalidOffset;
|
||||
}
|
||||
|
||||
wxSoundAiff::wxSoundAiff(wxOutputStream& stream, wxSoundStream& io_sound)
|
||||
: wxSoundFileStream(stream, io_sound)
|
||||
{
|
||||
m_base_offset = wxInvalidOffset;
|
||||
}
|
||||
|
||||
wxSoundAiff::~wxSoundAiff()
|
||||
{
|
||||
}
|
||||
|
||||
wxString wxSoundAiff::GetCodecName() const
|
||||
{
|
||||
return "wxSoundAiff codec";
|
||||
}
|
||||
|
||||
bool wxSoundAiff::CanRead()
|
||||
{
|
||||
wxUint32 signature1, signature2, len;
|
||||
|
||||
if (m_input->Read(&signature1, 4).LastRead() != 4)
|
||||
return FALSE;
|
||||
|
||||
if (wxUINT32_SWAP_ON_BE(signature1) != FORM_SIGNATURE) {
|
||||
m_input->Ungetch(&signature1, 4);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_input->Read(&len, 4);
|
||||
if (m_input->LastRead() != 4) {
|
||||
m_input->Ungetch(&len, m_input->LastRead());
|
||||
m_input->Ungetch(&signature1, 4);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_input->Read(&signature2, 4).LastRead() != 4) {
|
||||
m_input->Ungetch(&signature2, m_input->LastRead());
|
||||
m_input->Ungetch(&len, 4);
|
||||
m_input->Ungetch(&signature1, 4);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_input->Ungetch(&signature2, 4);
|
||||
m_input->Ungetch(&len, 4);
|
||||
m_input->Ungetch(&signature1, 4);
|
||||
|
||||
if (
|
||||
wxUINT32_SWAP_ON_BE(signature2) != AIFF_SIGNATURE &&
|
||||
wxUINT32_SWAP_ON_BE(signature2) != AIFC_SIGNATURE)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
|
||||
|
||||
bool wxSoundAiff::PrepareToPlay()
|
||||
{
|
||||
wxDataInputStream data(*m_input);
|
||||
wxUint32 signature, len, ssnd;
|
||||
bool end_headers;
|
||||
|
||||
if (!m_input) {
|
||||
m_snderror = wxSOUND_INVSTRM;
|
||||
return FALSE;
|
||||
}
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
|
||||
data.BigEndianOrdered(TRUE);
|
||||
|
||||
FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
|
||||
FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != FORM_SIGNATURE, wxSOUND_INVSTRM);
|
||||
// "FORM"
|
||||
|
||||
len = data.Read32();
|
||||
FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
|
||||
// dummy len
|
||||
|
||||
FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
|
||||
FAIL_WITH(
|
||||
wxUINT32_SWAP_ON_BE(signature) != AIFF_SIGNATURE &&
|
||||
wxUINT32_SWAP_ON_BE(signature) != AIFC_SIGNATURE, wxSOUND_INVSTRM);
|
||||
// "AIFF" / "AIFC"
|
||||
|
||||
end_headers = FALSE;
|
||||
while (!end_headers) {
|
||||
FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
|
||||
|
||||
len = data.Read32();
|
||||
FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
|
||||
|
||||
switch (wxUINT32_SWAP_ON_BE(signature)) {
|
||||
case COMM_SIGNATURE: { // "COMM"
|
||||
wxUint16 channels, bps;
|
||||
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);
|
||||
sndformat.Signed(FALSE);
|
||||
sndformat.SetOrder(wxBIG_ENDIAN);
|
||||
|
||||
if (!SetSoundFormat(sndformat))
|
||||
return FALSE;
|
||||
// We pass all data left
|
||||
m_input->SeekI(len-18, wxFromCurrent);
|
||||
break;
|
||||
}
|
||||
case SSND_SIGNATURE: { // "SSND"
|
||||
data >> ssnd;
|
||||
// m_input->SeekI(4, wxFromCurrent); // Pass an INT32
|
||||
// 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;
|
||||
}
|
||||
default:
|
||||
m_input->SeekI(len, wxFromCurrent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundAiff::PrepareToRecord(wxUint32 time)
|
||||
{
|
||||
// TODO
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool wxSoundAiff::FinishRecording()
|
||||
{
|
||||
// TODO
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
wxUint32 wxSoundAiff::GetData(void *buffer, wxUint32 len)
|
||||
{
|
||||
return m_input->Read(buffer, len).LastRead();
|
||||
}
|
||||
|
||||
wxUint32 wxSoundAiff::PutData(const void *buffer, wxUint32 len)
|
||||
{
|
||||
return m_output->Write(buffer, len).LastWrite();
|
||||
}
|
@@ -1,45 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndaiff.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDAIFF_H
|
||||
#define _WX_SNDAIFF_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "sndaiff.h"
|
||||
#endif
|
||||
|
||||
#include <wx/stream.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndcodec.h"
|
||||
#include "sndfile.h"
|
||||
|
||||
//
|
||||
// AIFF codec
|
||||
//
|
||||
|
||||
class wxSoundAiff: public wxSoundFileStream {
|
||||
public:
|
||||
wxSoundAiff(wxInputStream& stream, wxSoundStream& io_sound);
|
||||
wxSoundAiff(wxOutputStream& stream, wxSoundStream& io_sound);
|
||||
~wxSoundAiff();
|
||||
|
||||
bool CanRead();
|
||||
wxString GetCodecName() const;
|
||||
|
||||
protected:
|
||||
bool PrepareToPlay();
|
||||
bool PrepareToRecord(wxUint32 time);
|
||||
bool FinishRecording();
|
||||
bool RepositionStream(wxUint32 position);
|
||||
|
||||
wxUint32 GetData(void *buffer, wxUint32 len);
|
||||
wxUint32 PutData(const void *buffer, wxUint32 len);
|
||||
protected:
|
||||
off_t m_base_offset;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,134 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndbase.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "sndbase.cpp"
|
||||
#endif
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
#include "sndbase.h"
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// wxSoundFormatBase
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
wxSoundFormatBase::wxSoundFormatBase()
|
||||
{
|
||||
}
|
||||
|
||||
wxSoundFormatBase::~wxSoundFormatBase()
|
||||
{
|
||||
}
|
||||
|
||||
wxSoundFormatBase *wxSoundFormatBase::Clone() const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool wxSoundFormatBase::operator!=(const wxSoundFormatBase& frmt2) const
|
||||
{
|
||||
return (GetType() != frmt2.GetType());
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// wxSoundStream
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
wxSoundStream::wxSoundStream()
|
||||
{
|
||||
int i;
|
||||
|
||||
// Reset all variables to their neutral value.
|
||||
m_sndformat = NULL;
|
||||
m_handler = NULL;
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
m_lastcount = 0;
|
||||
for (i=0;i<2;i++)
|
||||
m_callback[i] = NULL;
|
||||
}
|
||||
|
||||
wxSoundStream::~wxSoundStream()
|
||||
{
|
||||
if (m_sndformat)
|
||||
delete m_sndformat;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// SetSoundFormat(const wxSoundFormatBase& format) is one of the most
|
||||
// important function of the wxSoundStream class. It prepares the stream to
|
||||
// receive or send the data in a strict format. Normally, the sound stream
|
||||
// should be ready to accept any format it is asked to manage but in certain
|
||||
// cases, it really cannot: in that case it returns FALSE. To have more
|
||||
// details in the functionnalities of SetSoundFormat see
|
||||
// wxSoundRouterStream::SetSoundFormat()
|
||||
// --------------------------------------------------------------------------
|
||||
bool wxSoundStream::SetSoundFormat(const wxSoundFormatBase& format)
|
||||
{
|
||||
// delete the previous prepared format
|
||||
if (m_sndformat)
|
||||
delete m_sndformat;
|
||||
|
||||
// create a new one by cloning the format passed in parameter
|
||||
m_sndformat = format.Clone();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Register(int evt, ...) registers the callback for a specified async event.
|
||||
// Warning ! Only one callback by event is supported. It means that if you
|
||||
// call twice this function the previous registered callback is absolutely
|
||||
// ignored.
|
||||
// --------------------------------------------------------------------------
|
||||
void wxSoundStream::SetCallback(int evt, wxSoundCallback cbk, void *cdata)
|
||||
{
|
||||
int c;
|
||||
|
||||
switch (evt) {
|
||||
case wxSOUND_INPUT:
|
||||
c = 0;
|
||||
break;
|
||||
case wxSOUND_OUTPUT:
|
||||
c = 1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
m_callback[c] = cbk;
|
||||
m_cdata[c] = cdata;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// OnSoundEvent(int evt) is called either when the driver is ready to receive
|
||||
// a new block to play or when the driver has a new recorded buffer. You
|
||||
// must be careful here and try not to spend a lot of time: this is a
|
||||
// real-time call. In the case, an "event handler" was specified previously,
|
||||
// it called him before everything.
|
||||
// --------------------------------------------------------------------------
|
||||
void wxSoundStream::OnSoundEvent(int evt)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (m_handler) {
|
||||
m_handler->OnSoundEvent(evt);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (evt) {
|
||||
case wxSOUND_INPUT:
|
||||
c = 0;
|
||||
break;
|
||||
case wxSOUND_OUTPUT:
|
||||
c = 1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
if (m_callback[c])
|
||||
m_callback[c](this, evt, m_cdata[c]);
|
||||
}
|
@@ -1,168 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndbase.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDBASE_H
|
||||
#define _WX_SNDBASE_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "sndbase.h"
|
||||
#endif
|
||||
|
||||
#include <wx/defs.h>
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// DEFINITIONS
|
||||
|
||||
// ---------------------
|
||||
// Sound streaming mode:
|
||||
// - wxSOUND_INPUT: simple recording mode
|
||||
// - wxSOUND_OUTPUT: simple playing mode
|
||||
// - wxSOUND_DUPLEX: full duplex record/play at the same time
|
||||
// ---------------------
|
||||
enum {
|
||||
wxSOUND_INPUT = 1,
|
||||
wxSOUND_OUTPUT = 2,
|
||||
wxSOUND_DUPLEX = wxSOUND_INPUT | wxSOUND_OUTPUT,
|
||||
};
|
||||
|
||||
// ---------------------
|
||||
// wxSoundFormatType: it specifies the format family of the sound data
|
||||
// which will be passed to the stream.
|
||||
// ---------------------
|
||||
typedef enum {
|
||||
wxSOUND_NOFORMAT,
|
||||
wxSOUND_PCM,
|
||||
wxSOUND_ULAW,
|
||||
wxSOUND_G72X,
|
||||
wxSOUND_MSADPCM
|
||||
} wxSoundFormatType;
|
||||
|
||||
// ---------------------
|
||||
// wxSoundError:
|
||||
// - wxSOUND_NOERR: No error occured
|
||||
// - wxSOUND_IOERR: an input/output error occured, it may concern either
|
||||
// a driver or a file
|
||||
// - wxSOUND_INVFRMT: the sound format passed to the function is invalid.
|
||||
// Generally, it means that you passed out of range values
|
||||
// to the codec stream or you don't pass the right sound
|
||||
// format object to the right sound codec stream.
|
||||
// - wxSOUND_INVDEV: Invalid device. Generally, it means that the sound stream
|
||||
// didn't manage to open the device driver due to an invalid// parameter or to the fact that sound is not supported on
|
||||
// this computer.
|
||||
// - wxSOUND_NOEXACT: No exact matching sound codec has been found for
|
||||
// this sound format. It means that the sound driver didn't
|
||||
// manage to setup the sound card with the specified
|
||||
// values.
|
||||
// - wxSOUND_NOCODEC: No matching codec has been found. Generally, it
|
||||
// may happen when you call
|
||||
// wxSoundRouterStream::SetSoundFormat().
|
||||
// - wxSOUND_MEMERR: Not enough memory.
|
||||
// ---------------------
|
||||
typedef enum {
|
||||
wxSOUND_NOERROR,
|
||||
wxSOUND_IOERROR,
|
||||
wxSOUND_INVFRMT,
|
||||
wxSOUND_INVDEV,
|
||||
wxSOUND_NOEXACT,
|
||||
wxSOUND_INVSTRM,
|
||||
wxSOUND_NOCODEC,
|
||||
wxSOUND_MEMERROR
|
||||
} wxSoundError;
|
||||
|
||||
class WXDLLEXPORT wxSoundStream;
|
||||
|
||||
// ---------------------
|
||||
// wxSoundCallback(stream, evt, cdata): C callback for sound event.
|
||||
// - stream: current wxSoundStream
|
||||
// - evt: the sound event which has occured, it may be wxSOUND_INPUT,
|
||||
// wxSOUND_OUTPUT or wxSOUND_DUPLEX
|
||||
// - cdata: User callback data
|
||||
// ---------------------
|
||||
typedef void (*wxSoundCallback)(wxSoundStream *stream, int evt,
|
||||
void *cdata);
|
||||
|
||||
//
|
||||
// Base class for sound format specification
|
||||
//
|
||||
|
||||
class WXDLLEXPORT wxSoundFormatBase {
|
||||
public:
|
||||
wxSoundFormatBase();
|
||||
virtual ~wxSoundFormatBase();
|
||||
|
||||
// It returns a "standard" format type.
|
||||
virtual wxSoundFormatType GetType() const { return wxSOUND_NOFORMAT; }
|
||||
// It clones the current format.
|
||||
virtual wxSoundFormatBase *Clone() const;
|
||||
|
||||
virtual wxUint32 GetTimeFromBytes(wxUint32 bytes) const = 0;
|
||||
virtual wxUint32 GetBytesFromTime(wxUint32 time) const = 0;
|
||||
|
||||
virtual bool operator !=(const wxSoundFormatBase& frmt2) const;
|
||||
};
|
||||
|
||||
//
|
||||
// Base class for sound streams
|
||||
//
|
||||
|
||||
class wxSoundStream {
|
||||
public:
|
||||
wxSoundStream();
|
||||
virtual ~wxSoundStream();
|
||||
|
||||
// Reads "len" bytes from the sound stream.
|
||||
virtual wxSoundStream& Read(void *buffer, wxUint32 len) = 0;
|
||||
// Writes "len" byte to the sound stream.
|
||||
virtual wxSoundStream& Write(const void *buffer, wxUint32 len) = 0;
|
||||
// Returns the best size for IO calls
|
||||
virtual wxUint32 GetBestSize() const { return 1024; }
|
||||
|
||||
// SetSoundFormat returns TRUE when the format can be handled.
|
||||
virtual bool SetSoundFormat(const wxSoundFormatBase& format);
|
||||
|
||||
// GetSoundFormat returns the current sound format.
|
||||
wxSoundFormatBase& GetSoundFormat() const { return *m_sndformat; }
|
||||
|
||||
// Register a callback for a specified async event.
|
||||
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.
|
||||
virtual bool StartProduction(int evt) = 0;
|
||||
// Stops the async notifier.
|
||||
virtual bool StopProduction() = 0;
|
||||
// Sets the event handler: if it is non-null, all events are routed to it.
|
||||
void SetEventHandler(wxSoundStream *handler) { m_handler = handler; }
|
||||
|
||||
wxSoundError GetError() const { return m_snderror; }
|
||||
wxUint32 GetLastAccess() const { return m_lastcount; }
|
||||
|
||||
// This is only useful for device (I think).
|
||||
virtual bool QueueFilled() const { return TRUE; }
|
||||
|
||||
protected:
|
||||
// Current sound format
|
||||
wxSoundFormatBase *m_sndformat;
|
||||
|
||||
// Last error
|
||||
wxSoundError m_snderror;
|
||||
|
||||
// Last access
|
||||
wxUint32 m_lastcount;
|
||||
|
||||
// Event handler
|
||||
wxSoundStream *m_handler;
|
||||
|
||||
wxSoundCallback m_callback[2];
|
||||
void *m_cdata[2];
|
||||
|
||||
protected:
|
||||
// Handles event
|
||||
virtual void OnSoundEvent(int evt);
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,38 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndcodec.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "sndcodec.cpp"
|
||||
#endif
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndcodec.h"
|
||||
|
||||
wxSoundStreamCodec::wxSoundStreamCodec(wxSoundStream& snd_io)
|
||||
: m_sndio(&snd_io)
|
||||
{
|
||||
}
|
||||
|
||||
wxSoundStreamCodec::~wxSoundStreamCodec()
|
||||
{
|
||||
}
|
||||
|
||||
bool wxSoundStreamCodec::StartProduction(int evt)
|
||||
{
|
||||
return m_sndio->StartProduction(evt);
|
||||
}
|
||||
|
||||
bool wxSoundStreamCodec::StopProduction()
|
||||
{
|
||||
return m_sndio->StopProduction();
|
||||
}
|
||||
|
||||
wxUint32 wxSoundStreamCodec::GetBestSize() const
|
||||
{
|
||||
return m_sndio->GetBestSize();
|
||||
}
|
@@ -1,31 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndcodec.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDCODEC_H
|
||||
#define _WX_SNDCODEC_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "sndcodec.h"
|
||||
#endif
|
||||
|
||||
#include "sndbase.h"
|
||||
|
||||
class wxSoundStreamCodec: public wxSoundStream {
|
||||
public:
|
||||
wxSoundStreamCodec(wxSoundStream& snd_io);
|
||||
~wxSoundStreamCodec();
|
||||
|
||||
bool StartProduction(int evt);
|
||||
bool StopProduction();
|
||||
|
||||
wxUint32 GetBestSize() const;
|
||||
|
||||
protected:
|
||||
wxSoundStream *m_sndio;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,389 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndcpcm.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#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)
|
||||
{
|
||||
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
|
||||
// -----------------------------------------------------------------------
|
||||
// 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 */
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 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
|
||||
// is not aligned on 2, you may crash (See converter.def).
|
||||
//
|
||||
|
||||
wxSoundStream& wxSoundStreamPcm::Read(void *buffer, wxUint32 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
wxSoundStream& wxSoundStreamPcm::Write(const void *buffer, wxUint32 len)
|
||||
{
|
||||
wxUint32 out_bufsize;
|
||||
|
||||
if (!m_function_out) {
|
||||
m_sndio->Write(buffer, len);
|
||||
m_lastcount = m_sndio->GetLastAccess();
|
||||
m_snderror = m_sndio->GetError();
|
||||
return *this;
|
||||
}
|
||||
|
||||
out_bufsize = GetWriteSize(len);
|
||||
|
||||
if (len <= m_best_size) {
|
||||
out_bufsize = GetWriteSize(len);
|
||||
|
||||
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 = (wxUint32)(m_sndio->GetLastAccess() / m_multiplier_out);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool wxSoundStreamPcm::SetSoundFormat(const wxSoundFormatBase& format)
|
||||
{
|
||||
wxSoundFormatBase *new_format;
|
||||
wxSoundFormatPcm *pcm_format, *pcm_format2;
|
||||
|
||||
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;
|
||||
|
||||
#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 wxBIG_ENDIAN
|
||||
#else
|
||||
#define OTHER_ORDER wxLITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
if (m_prebuffer)
|
||||
delete[] m_prebuffer;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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
|
@@ -1,53 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndcpcm.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDCPCM_H
|
||||
#define _WX_SNDCPCM_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "sndcpcm.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include "sndcodec.h"
|
||||
|
||||
//
|
||||
// PCM converter class
|
||||
//
|
||||
|
||||
class wxSoundStreamPcm: public wxSoundStreamCodec {
|
||||
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
|
@@ -1,273 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndesd.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "sndesd.cpp"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <wx/defs.h>
|
||||
#include <wx/string.h>
|
||||
#include <esd.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndesd.h"
|
||||
#include "sndpcm.h"
|
||||
#ifdef __WXGTK__
|
||||
#include <gdk/gdk.h>
|
||||
#endif
|
||||
|
||||
#define MY_ESD_NAME "wxWindows/wxSoundStreamESD"
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
// wxSoundStreamESD: ESD sound driver
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Constructors/Destructors
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
wxSoundStreamESD::wxSoundStreamESD(const wxString& hostname)
|
||||
{
|
||||
wxSoundFormatPcm pcm_default;
|
||||
|
||||
// First, we make some basic test: is there ESD on this computer ?
|
||||
|
||||
if (hostname.IsNull())
|
||||
m_fd_output = esd_play_stream(ESD_PLAY | ESD_STREAM, 22050,
|
||||
hostname.mb_str(), MY_ESD_NAME);
|
||||
else
|
||||
m_fd_output = esd_play_stream(ESD_PLAY | ESD_STREAM, 22050,
|
||||
NULL, MY_ESD_NAME);
|
||||
if (m_fd_output == -1) {
|
||||
// Answer: no. We return with an error.
|
||||
m_snderror = wxSOUND_INVDEV;
|
||||
return;
|
||||
}
|
||||
|
||||
// Close this unuseful stream.
|
||||
esd_close(m_fd_output);
|
||||
|
||||
m_hostname = hostname;
|
||||
|
||||
// Set the default audio format
|
||||
SetSoundFormat(pcm_default);
|
||||
|
||||
// Initialize some variable
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
m_esd_stop = TRUE;
|
||||
m_q_filled = TRUE;
|
||||
m_fd_output= -1;
|
||||
}
|
||||
|
||||
wxSoundStreamESD::~wxSoundStreamESD()
|
||||
{
|
||||
// Close all remaining streams
|
||||
if (m_fd_output > 0)
|
||||
esd_close(m_fd_output);
|
||||
if (m_fd_input > 0)
|
||||
esd_close(m_fd_input);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Read several samples
|
||||
// --------------------------------------------------------------------------------------------
|
||||
wxSoundStream& wxSoundStreamESD::Read(void *buffer, wxUint32 len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
m_lastcount = (wxUint32)ret = read(m_fd_input, buffer, len);
|
||||
|
||||
if (ret < 0)
|
||||
m_snderror = wxSOUND_IOERROR;
|
||||
else
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// Write several samples
|
||||
// --------------------------------------------------------------------------------------------
|
||||
wxSoundStream& wxSoundStreamESD::Write(const void *buffer, wxUint32 len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
m_lastcount = (wxUint32)ret = write(m_fd_output, buffer, len);
|
||||
|
||||
if (ret < 0)
|
||||
m_snderror = wxSOUND_IOERROR;
|
||||
else
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
|
||||
m_q_filled = TRUE;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// SetSoundFormat(): this function specifies which format we want and which format is available
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
bool wxSoundStreamESD::SetSoundFormat(const wxSoundFormatBase& format)
|
||||
{
|
||||
wxSoundFormatPcm *pcm_format;
|
||||
|
||||
if (format.GetType() != wxSOUND_PCM) {
|
||||
m_snderror = wxSOUND_INVFRMT;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_fd_input == -1 && m_fd_output == -1) {
|
||||
m_snderror = wxSOUND_INVDEV;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_sndformat)
|
||||
delete m_sndformat;
|
||||
|
||||
m_sndformat = format.Clone();
|
||||
if (!m_sndformat) {
|
||||
m_snderror = wxSOUND_MEMERROR;
|
||||
return FALSE;
|
||||
}
|
||||
pcm_format = (wxSoundFormatPcm *)m_sndformat;
|
||||
|
||||
// Detect the best format
|
||||
DetectBest(pcm_format);
|
||||
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
if (*pcm_format != format) {
|
||||
m_snderror = wxSOUND_NOEXACT;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// _wxSound_OSS_CBack (internal): it is called when the driver (ESD) is ready for a next
|
||||
// buffer.
|
||||
// --------------------------------------------------------------------------------------------
|
||||
#ifdef __WXGTK__
|
||||
static void _wxSound_OSS_CBack(gpointer data, int source,
|
||||
GdkInputCondition condition)
|
||||
{
|
||||
wxSoundStreamESD *esd = (wxSoundStreamESD *)data;
|
||||
|
||||
switch (condition) {
|
||||
case GDK_INPUT_READ:
|
||||
esd->WakeUpEvt(wxSOUND_INPUT);
|
||||
break;
|
||||
case GDK_INPUT_WRITE:
|
||||
esd->WakeUpEvt(wxSOUND_OUTPUT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// WakeUpEvt() (internal): it is called by _wxSound_OSS_CBack to bypass the C++ protection
|
||||
// --------------------------------------------------------------------------------------------
|
||||
void wxSoundStreamESD::WakeUpEvt(int evt)
|
||||
{
|
||||
m_q_filled = FALSE;
|
||||
OnSoundEvent(evt);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
// StartProduction(): see wxSoundStream
|
||||
// --------------------------------------------------------------------------------------------
|
||||
bool wxSoundStreamESD::StartProduction(int evt)
|
||||
{
|
||||
wxSoundFormatPcm *pcm;
|
||||
int flag = 0;
|
||||
|
||||
if (!m_esd_stop)
|
||||
StopProduction();
|
||||
|
||||
pcm = (wxSoundFormatPcm *)m_sndformat;
|
||||
|
||||
flag |= (pcm->GetBPS() == 16) ? ESD_BITS16 : ESD_BITS8;
|
||||
flag |= (pcm->GetChannels() == 2) ? ESD_STEREO : ESD_MONO;
|
||||
|
||||
if ((evt & wxSOUND_OUTPUT) != 0) {
|
||||
flag |= ESD_PLAY | ESD_STREAM;
|
||||
m_fd_output = esd_play_stream(flag, pcm->GetSampleRate(), NULL,
|
||||
MY_ESD_NAME);
|
||||
}
|
||||
|
||||
if ((evt & wxSOUND_INPUT) != 0) {
|
||||
flag |= ESD_RECORD | ESD_STREAM;
|
||||
m_fd_input = esd_record_stream(flag, pcm->GetSampleRate(), NULL,
|
||||
MY_ESD_NAME);
|
||||
}
|
||||
|
||||
#ifdef __WXGTK__
|
||||
if ((evt & wxSOUND_OUTPUT) != 0) {
|
||||
m_tag_output = gdk_input_add(m_fd_output, GDK_INPUT_WRITE, _wxSound_OSS_CBack, (gpointer)this);
|
||||
}
|
||||
if ((evt & wxSOUND_INPUT) != 0) {
|
||||
m_tag_input = gdk_input_add(m_fd_input, GDK_INPUT_READ, _wxSound_OSS_CBack, (gpointer)this);
|
||||
}
|
||||
#endif
|
||||
|
||||
m_esd_stop = FALSE;
|
||||
m_q_filled = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundStreamESD::StopProduction()
|
||||
{
|
||||
if (m_esd_stop)
|
||||
return FALSE;
|
||||
|
||||
if (m_fd_input != -1) {
|
||||
esd_close(m_fd_input);
|
||||
#ifdef __WXGTK__
|
||||
gdk_input_remove(m_tag_input);
|
||||
#endif
|
||||
}
|
||||
if (m_fd_output != -1) {
|
||||
esd_close(m_fd_output);
|
||||
#ifdef __WXGTK__
|
||||
gdk_input_remove(m_tag_output);
|
||||
#endif
|
||||
}
|
||||
|
||||
m_fd_input = -1;
|
||||
m_fd_output= -1;
|
||||
m_esd_stop = TRUE;
|
||||
m_q_filled = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect the closest format (The best).
|
||||
//
|
||||
void wxSoundStreamESD::DetectBest(wxSoundFormatPcm *pcm)
|
||||
{
|
||||
wxSoundFormatPcm best_pcm;
|
||||
|
||||
// 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());
|
||||
|
||||
// It supports 16 bits
|
||||
if (pcm->GetBPS() == 16)
|
||||
best_pcm.SetBPS(16);
|
||||
|
||||
best_pcm.SetOrder(wxLITTLE_ENDIAN);
|
||||
best_pcm.Signed(TRUE);
|
||||
|
||||
// Finally recopy the new format
|
||||
*pcm = best_pcm;
|
||||
}
|
@@ -1,51 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndesd.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDESD_H
|
||||
#define _WX_SNDESD_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "sndesd.h"
|
||||
#endif
|
||||
|
||||
#include <wx/string.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndpcm.h"
|
||||
|
||||
//
|
||||
// ESD output class
|
||||
//
|
||||
|
||||
class wxSoundStreamESD : public wxSoundStream {
|
||||
public:
|
||||
wxSoundStreamESD(const wxString& hostname = _T("localhost"));
|
||||
~wxSoundStreamESD();
|
||||
|
||||
wxSoundStream& Read(void *buffer, wxUint32 len);
|
||||
wxSoundStream& Write(const void *buffer, wxUint32 len);
|
||||
|
||||
bool SetSoundFormat(const wxSoundFormatBase& format);
|
||||
|
||||
bool StartProduction(int evt);
|
||||
bool StopProduction();
|
||||
|
||||
// You should not call this.
|
||||
void WakeUpEvt(int evt);
|
||||
|
||||
bool QueueFilled() const { return m_q_filled; }
|
||||
protected:
|
||||
int m_fd_input, m_fd_output;
|
||||
int m_tag_input, m_tag_output;
|
||||
bool m_esd_stop;
|
||||
wxString m_hostname;
|
||||
bool m_q_filled;
|
||||
|
||||
private:
|
||||
void DetectBest(wxSoundFormatPcm *pcm);
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,407 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndfile.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/stream.h>
|
||||
#endif
|
||||
|
||||
#include "sndbase.h"
|
||||
#include "sndcodec.h"
|
||||
#include "sndfile.h"
|
||||
#include "sndcpcm.h"
|
||||
#include "sndulaw.h"
|
||||
#include "sndg72x.h"
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Sound codec router
|
||||
// A very important class: it ensures that everybody is satisfied.
|
||||
// It is supposed to create as many codec as it is necessary to transform
|
||||
// a signal in a specific format in an another.
|
||||
// --------------------------------------------------------------------------
|
||||
wxSoundRouterStream::wxSoundRouterStream(wxSoundStream& sndio)
|
||||
: wxSoundStreamCodec(sndio)
|
||||
{
|
||||
m_router = NULL;
|
||||
}
|
||||
|
||||
wxSoundRouterStream::~wxSoundRouterStream()
|
||||
{
|
||||
if (m_router)
|
||||
delete m_router;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Read(void *buffer, wxUint32 len): It reads data synchronously. See sndbase.h
|
||||
// for possible errors and behaviours ...
|
||||
// --------------------------------------------------------------------------
|
||||
wxSoundStream& wxSoundRouterStream::Read(void *buffer, wxUint32 len)
|
||||
{
|
||||
if (m_router) {
|
||||
m_router->Read(buffer, len);
|
||||
m_snderror = m_router->GetError();
|
||||
m_lastcount = m_router->GetLastAccess();
|
||||
} else {
|
||||
m_sndio->Read(buffer, len);
|
||||
m_snderror = m_sndio->GetError();
|
||||
m_lastcount = m_sndio->GetLastAccess();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Write(const void *buffer, wxUint32 len): It writes data synchronously
|
||||
// --------------------------------------------------------------------------
|
||||
wxSoundStream& wxSoundRouterStream::Write(const void *buffer, wxUint32 len)
|
||||
{
|
||||
if (m_router) {
|
||||
m_router->Write(buffer, len);
|
||||
m_snderror = m_router->GetError();
|
||||
m_lastcount = m_router->GetLastAccess();
|
||||
} else {
|
||||
m_sndio->Write(buffer, len);
|
||||
m_snderror = m_sndio->GetError();
|
||||
m_lastcount = m_sndio->GetLastAccess();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// SetSoundFormat(const wxSoundFormatBase& format) first tries to setup the
|
||||
// sound driver using the specified format. If this fails, it uses personnal
|
||||
// codec converters: for the moment there is a PCM converter (PCM to PCM:
|
||||
// with optional resampling, ...), an ULAW converter (ULAW to PCM), a G72X
|
||||
// converter (G72X to PCM). If nothing works, it returns FALSE.
|
||||
// --------------------------------------------------------------------------
|
||||
bool wxSoundRouterStream::SetSoundFormat(const wxSoundFormatBase& format)
|
||||
{
|
||||
if (m_router)
|
||||
delete m_router;
|
||||
|
||||
// First, we try to setup the sound device
|
||||
if (m_sndio->SetSoundFormat(format)) {
|
||||
// We are lucky, it is working.
|
||||
wxSoundStream::SetSoundFormat(m_sndio->GetSoundFormat());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
switch(format.GetType()) {
|
||||
case wxSOUND_NOFORMAT:
|
||||
return FALSE;
|
||||
case wxSOUND_PCM:
|
||||
m_router = new wxSoundStreamPcm(*m_sndio);
|
||||
m_router->SetSoundFormat(format);
|
||||
break;
|
||||
case wxSOUND_ULAW:
|
||||
m_router = new wxSoundStreamUlaw(*m_sndio);
|
||||
m_router->SetSoundFormat(format);
|
||||
break;
|
||||
case wxSOUND_G72X:
|
||||
m_router = new wxSoundStreamG72X(*m_sndio);
|
||||
m_router->SetSoundFormat(format);
|
||||
break;
|
||||
}
|
||||
wxSoundStream::SetSoundFormat(m_router->GetSoundFormat());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// GetBestSize() returns the specific best buffer size a sound driver
|
||||
// can manage. It means that it will be easier for it to manage the buffer
|
||||
// and so it will be faster and in some case more accurate for real-time event.
|
||||
// --------------------------------------------------------------------------
|
||||
wxUint32 wxSoundRouterStream::GetBestSize() const
|
||||
{
|
||||
if (m_router)
|
||||
return m_router->GetBestSize();
|
||||
else
|
||||
return m_sndio->GetBestSize();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// StartProduction(int evt). See sndbase.h
|
||||
// --------------------------------------------------------------------------
|
||||
bool wxSoundRouterStream::StartProduction(int evt)
|
||||
{
|
||||
if (!m_router) {
|
||||
if (m_sndio->StartProduction(evt))
|
||||
return TRUE;
|
||||
|
||||
m_snderror = m_sndio->GetError();
|
||||
m_lastcount = m_sndio->GetLastAccess();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_router->StartProduction(evt))
|
||||
return TRUE;
|
||||
|
||||
m_snderror = m_router->GetError();
|
||||
m_lastcount = m_router->GetLastAccess();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// StopProduction(). See sndbase.h
|
||||
// --------------------------------------------------------------------------
|
||||
bool wxSoundRouterStream::StopProduction()
|
||||
{
|
||||
if (!m_router) {
|
||||
if (m_sndio->StopProduction())
|
||||
return TRUE;
|
||||
|
||||
m_snderror = m_sndio->GetError();
|
||||
m_lastcount = m_sndio->GetLastAccess();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_router->StopProduction())
|
||||
return TRUE;
|
||||
|
||||
m_snderror = m_router->GetError();
|
||||
m_lastcount = m_router->GetLastAccess();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// wxSoundFileStream: generic reader
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
wxSoundFileStream::wxSoundFileStream(wxInputStream& stream,
|
||||
wxSoundStream& io_sound)
|
||||
: m_codec(io_sound), m_sndio(&io_sound),
|
||||
m_input(&stream), m_output(NULL), m_state(wxSOUND_FILE_STOPPED)
|
||||
{
|
||||
m_length = 0;
|
||||
m_bytes_left = 0;
|
||||
m_prepared = FALSE;
|
||||
}
|
||||
|
||||
wxSoundFileStream::wxSoundFileStream(wxOutputStream& stream,
|
||||
wxSoundStream& io_sound)
|
||||
: m_codec(io_sound), m_sndio(&io_sound),
|
||||
m_input(NULL), m_output(&stream), m_state(wxSOUND_FILE_STOPPED)
|
||||
{
|
||||
m_length = 0;
|
||||
m_bytes_left = 0;
|
||||
m_prepared = FALSE;
|
||||
}
|
||||
|
||||
wxSoundFileStream::~wxSoundFileStream()
|
||||
{
|
||||
if (m_state != wxSOUND_FILE_STOPPED)
|
||||
Stop();
|
||||
}
|
||||
|
||||
bool wxSoundFileStream::Play()
|
||||
{
|
||||
if (m_state != wxSOUND_FILE_STOPPED)
|
||||
return FALSE;
|
||||
|
||||
if (!m_prepared)
|
||||
if (!PrepareToPlay())
|
||||
return FALSE;
|
||||
|
||||
m_state = wxSOUND_FILE_PLAYING;
|
||||
|
||||
if (!StartProduction(wxSOUND_OUTPUT))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundFileStream::Record(wxUint32 time)
|
||||
{
|
||||
if (m_state != wxSOUND_FILE_STOPPED)
|
||||
return FALSE;
|
||||
|
||||
if (!PrepareToRecord(time))
|
||||
return FALSE;
|
||||
|
||||
FinishPreparation(m_sndformat->GetBytesFromTime(time));
|
||||
|
||||
m_state = wxSOUND_FILE_RECORDING;
|
||||
if (!StartProduction(wxSOUND_INPUT))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundFileStream::Stop()
|
||||
{
|
||||
if (m_state == wxSOUND_FILE_STOPPED)
|
||||
return FALSE;
|
||||
|
||||
if (!StopProduction())
|
||||
return FALSE;
|
||||
|
||||
m_prepared = FALSE;
|
||||
|
||||
if (m_state == wxSOUND_FILE_RECORDING)
|
||||
if (!FinishRecording()) {
|
||||
m_state = wxSOUND_FILE_STOPPED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_input)
|
||||
m_input->SeekI(0, wxFromStart);
|
||||
|
||||
if (m_output)
|
||||
m_output->SeekO(0, wxFromStart);
|
||||
|
||||
m_state = wxSOUND_FILE_STOPPED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundFileStream::Pause()
|
||||
{
|
||||
if (m_state == wxSOUND_FILE_PAUSED || m_state == wxSOUND_FILE_STOPPED)
|
||||
return FALSE;
|
||||
|
||||
if (!StopProduction())
|
||||
return FALSE;
|
||||
|
||||
m_oldstate = m_state;
|
||||
m_state = wxSOUND_FILE_PAUSED;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundFileStream::Resume()
|
||||
{
|
||||
if (m_state == wxSOUND_FILE_PLAYING || m_state == wxSOUND_FILE_RECORDING ||
|
||||
m_state == wxSOUND_FILE_STOPPED)
|
||||
return FALSE;
|
||||
|
||||
if (!StartProduction( (m_oldstate == wxSOUND_FILE_PLAYING) ?
|
||||
wxSOUND_OUTPUT : wxSOUND_INPUT))
|
||||
return FALSE;
|
||||
|
||||
m_state = m_oldstate;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
wxSoundStream& wxSoundFileStream::Read(void *buffer, wxUint32 len)
|
||||
{
|
||||
m_lastcount = GetData(buffer, len);
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxSoundStream& wxSoundFileStream::Write(const void *buffer, wxUint32 len)
|
||||
{
|
||||
m_lastcount = PutData(buffer, len);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool wxSoundFileStream::StartProduction(int evt)
|
||||
{
|
||||
m_sndio->SetEventHandler(this);
|
||||
|
||||
if (!m_codec.StartProduction(evt))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundFileStream::StopProduction()
|
||||
{
|
||||
return m_codec.StopProduction();
|
||||
}
|
||||
|
||||
void wxSoundFileStream::FinishPreparation(wxUint32 len)
|
||||
{
|
||||
m_bytes_left = m_length = len;
|
||||
m_prepared = TRUE;
|
||||
}
|
||||
|
||||
wxString wxSoundFileStream::GetCodecName() const
|
||||
{
|
||||
return wxString(wxT("wxSoundFileStream base codec"));
|
||||
}
|
||||
|
||||
wxUint32 wxSoundFileStream::GetLength()
|
||||
{
|
||||
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_NOERROR)
|
||||
PrepareToPlay();
|
||||
|
||||
return m_length-m_bytes_left;
|
||||
}
|
||||
|
||||
wxUint32 wxSoundFileStream::SetPosition(wxUint32 new_position)
|
||||
{
|
||||
if (!m_prepared && m_input != NULL && GetError() == wxSOUND_NOERROR)
|
||||
PrepareToPlay();
|
||||
|
||||
if (!m_prepared)
|
||||
return 0;
|
||||
|
||||
if (!RepositionStream(new_position))
|
||||
return m_length-m_bytes_left;
|
||||
|
||||
if (new_position >= m_length) {
|
||||
m_bytes_left = 0;
|
||||
return m_length;
|
||||
}
|
||||
|
||||
m_bytes_left = m_length-new_position;
|
||||
return new_position;
|
||||
}
|
||||
|
||||
void wxSoundFileStream::OnSoundEvent(int evt)
|
||||
{
|
||||
wxUint32 len = m_codec.GetBestSize();
|
||||
char *buffer;
|
||||
|
||||
buffer = new char[len];
|
||||
wxSoundStream::OnSoundEvent(evt);
|
||||
|
||||
while (!m_sndio->QueueFilled()) {
|
||||
switch(evt) {
|
||||
case wxSOUND_INPUT:
|
||||
if (len > m_bytes_left)
|
||||
len = m_bytes_left;
|
||||
|
||||
len = m_codec.Read(buffer, len).GetLastAccess();
|
||||
PutData(buffer, len);
|
||||
m_bytes_left -= len;
|
||||
if (m_bytes_left == 0) {
|
||||
Stop();
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case wxSOUND_OUTPUT:
|
||||
if (len > m_bytes_left)
|
||||
len = m_bytes_left;
|
||||
|
||||
len = GetData(buffer, len);
|
||||
m_bytes_left -= len;
|
||||
if (m_bytes_left == 0) {
|
||||
Stop();
|
||||
delete[] buffer;
|
||||
return;
|
||||
}
|
||||
m_codec.Write(buffer, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
bool wxSoundFileStream::SetSoundFormat(const wxSoundFormatBase& format)
|
||||
{
|
||||
wxSoundStream::SetSoundFormat(format);
|
||||
return m_codec.SetSoundFormat(format);
|
||||
}
|
@@ -1,126 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndfile.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDFILE_H
|
||||
#define _WX_SNDFILE_H
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include <wx/stream.h>
|
||||
#include <stdlib.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndcodec.h"
|
||||
|
||||
#define wxSOUND_INFINITE_TIME ((wxUint32)-1)
|
||||
|
||||
//
|
||||
// Codec router class
|
||||
//
|
||||
|
||||
class WXDLLEXPORT wxSoundRouterStream: public wxSoundStreamCodec {
|
||||
public:
|
||||
wxSoundRouterStream(wxSoundStream& sndio);
|
||||
~wxSoundRouterStream();
|
||||
|
||||
wxSoundStream& Read(void *buffer, wxUint32 len);
|
||||
wxSoundStream& Write(const void *buffer, wxUint32 len);
|
||||
|
||||
bool SetSoundFormat(const wxSoundFormatBase& format);
|
||||
|
||||
bool StartProduction(int evt);
|
||||
bool StopProduction();
|
||||
|
||||
wxUint32 GetBestSize() const;
|
||||
|
||||
protected:
|
||||
wxSoundStream *m_router;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
wxSOUND_FILE_STOPPED,
|
||||
wxSOUND_FILE_PAUSED,
|
||||
wxSOUND_FILE_PLAYING,
|
||||
wxSOUND_FILE_RECORDING
|
||||
} wxSoundFileState;
|
||||
|
||||
//
|
||||
// Base class for file coders/decoders
|
||||
//
|
||||
|
||||
class wxSoundFileStream: public wxSoundStream {
|
||||
public:
|
||||
wxSoundFileStream(wxInputStream& stream, wxSoundStream& io_sound);
|
||||
wxSoundFileStream(wxOutputStream& stream, wxSoundStream& io_sound);
|
||||
~wxSoundFileStream();
|
||||
|
||||
// Usual sound file calls (Play, Stop, ...)
|
||||
bool Play();
|
||||
bool Record(wxUint32 time);
|
||||
bool Stop();
|
||||
bool Pause();
|
||||
bool Resume();
|
||||
|
||||
// Functions which return the current state
|
||||
bool IsStopped() const { return m_state == wxSOUND_FILE_STOPPED; }
|
||||
bool IsPaused() const { return m_state == wxSOUND_FILE_PAUSED; }
|
||||
|
||||
// A user should not call these two functions.
|
||||
// Several things must be done before calling them.
|
||||
// Users should use Play(), ...
|
||||
bool StartProduction(int evt);
|
||||
bool StopProduction();
|
||||
|
||||
// These three functions deals with the length, the position in the sound file.
|
||||
// All the values are expressed in bytes. If you need the values expressed
|
||||
// in terms of time, you have to use GetSoundFormat().GetTimeFromBytes(...)
|
||||
wxUint32 GetLength();
|
||||
wxUint32 GetPosition();
|
||||
wxUint32 SetPosition(wxUint32 new_position);
|
||||
|
||||
// These two functions use the sound format specified by GetSoundFormat().
|
||||
// All samples must be encoded in that format.
|
||||
wxSoundStream& Read(void *buffer, wxUint32 len);
|
||||
wxSoundStream& Write(const void *buffer, wxUint32 len);
|
||||
|
||||
// This function set the sound format of the file. !! It must be used only
|
||||
// when you are in output mode (concerning the file) !! If you are in
|
||||
// input mode (concerning the file) you can't use this function to modify
|
||||
// the format of the samples returned by Read() !
|
||||
// For this action, you must use wxSoundRouterStream applied to wxSoundFileStream.
|
||||
bool SetSoundFormat(const wxSoundFormatBase& format);
|
||||
|
||||
// This function returns the Codec name. This is useful for those who want to build
|
||||
// a player (But also in some other case).
|
||||
virtual wxString GetCodecName() const;
|
||||
|
||||
// You should use this function to test whether this file codec can read
|
||||
// the stream you passed to it.
|
||||
virtual bool CanRead() { return FALSE; }
|
||||
|
||||
protected:
|
||||
wxSoundRouterStream m_codec;
|
||||
wxSoundStream *m_sndio;
|
||||
wxInputStream *m_input;
|
||||
wxOutputStream *m_output;
|
||||
|
||||
wxSoundFileState m_state, m_oldstate;
|
||||
wxUint32 m_length, m_bytes_left;
|
||||
bool m_prepared;
|
||||
|
||||
protected:
|
||||
virtual bool PrepareToPlay() = 0;
|
||||
virtual bool PrepareToRecord(wxUint32 time) = 0;
|
||||
virtual bool FinishRecording() = 0;
|
||||
virtual bool RepositionStream(wxUint32 position) = 0;
|
||||
void FinishPreparation(wxUint32 len);
|
||||
|
||||
virtual wxUint32 GetData(void *buffer, wxUint32 len) = 0;
|
||||
virtual wxUint32 PutData(const void *buffer, wxUint32 len) = 0;
|
||||
|
||||
void OnSoundEvent(int evt);
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,304 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndg72x.cpp
|
||||
// Purpose:
|
||||
// Date: 08/26/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "sndg72x.cpp"
|
||||
#endif
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndfile.h"
|
||||
#include "sndpcm.h"
|
||||
#include "sndg72x.h"
|
||||
#include "g72x.h"
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// wxSoundFormatG72X
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
wxSoundFormatG72X::wxSoundFormatG72X()
|
||||
: m_srate(22050)
|
||||
{
|
||||
}
|
||||
|
||||
wxSoundFormatG72X::~wxSoundFormatG72X()
|
||||
{
|
||||
}
|
||||
|
||||
void wxSoundFormatG72X::SetSampleRate(wxUint32 srate)
|
||||
{
|
||||
m_srate = srate;
|
||||
}
|
||||
|
||||
wxUint32 wxSoundFormatG72X::GetSampleRate() const
|
||||
{
|
||||
return m_srate;
|
||||
}
|
||||
|
||||
void wxSoundFormatG72X::SetG72XType(wxSoundG72XType type)
|
||||
{
|
||||
m_g72x_type = type;
|
||||
}
|
||||
|
||||
wxSoundFormatBase *wxSoundFormatG72X::Clone() const
|
||||
{
|
||||
wxSoundFormatG72X *g72x = new wxSoundFormatG72X();
|
||||
|
||||
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) * 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 * 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);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// wxSoundStreamG72X
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
wxSoundStreamG72X::wxSoundStreamG72X(wxSoundStream& sndio)
|
||||
: wxSoundStreamCodec(sndio)
|
||||
{
|
||||
// PCM converter
|
||||
m_router = new wxSoundRouterStream(sndio);
|
||||
m_state = new g72state;
|
||||
g72x_init_state(m_state);
|
||||
}
|
||||
|
||||
wxSoundStreamG72X::~wxSoundStreamG72X()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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); // 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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndg72x.h
|
||||
// Purpose:
|
||||
// Date: 08/26/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDG72X_H
|
||||
#define _WX_SNDG72X_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "sndg72x.h"
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include "sndcodec.h"
|
||||
#include "sndbase.h"
|
||||
|
||||
typedef enum {
|
||||
wxSOUND_G721,
|
||||
wxSOUND_G723_24,
|
||||
wxSOUND_G723_40
|
||||
} wxSoundG72XType;
|
||||
|
||||
// This fixes a bug in Mingw95
|
||||
typedef struct g72x_state g72state;
|
||||
|
||||
//
|
||||
// G72X format
|
||||
//
|
||||
class WXDLLEXPORT wxSoundFormatG72X: public wxSoundFormatBase {
|
||||
public:
|
||||
wxSoundFormatG72X();
|
||||
~wxSoundFormatG72X();
|
||||
|
||||
void SetG72XType(wxSoundG72XType type);
|
||||
wxSoundG72XType GetG72XType() const { return m_g72x_type; }
|
||||
|
||||
void SetSampleRate(wxUint32 srate);
|
||||
wxUint32 GetSampleRate() const;
|
||||
|
||||
wxSoundFormatType GetType() const { return wxSOUND_G72X; }
|
||||
wxSoundFormatBase *Clone() const;
|
||||
|
||||
wxUint32 GetTimeFromBytes(wxUint32 bytes) const;
|
||||
wxUint32 GetBytesFromTime(wxUint32 time) const;
|
||||
|
||||
bool operator !=(const wxSoundFormatBase& frmt2) const;
|
||||
|
||||
protected:
|
||||
wxUint32 m_srate;
|
||||
wxSoundG72XType m_g72x_type;
|
||||
};
|
||||
|
||||
//
|
||||
// ULAW converter class
|
||||
//
|
||||
|
||||
class WXDLLEXPORT wxSoundRouterStream;
|
||||
class WXDLLEXPORT wxSoundStreamG72X: public wxSoundStreamCodec {
|
||||
public:
|
||||
wxSoundStreamG72X(wxSoundStream& sndio);
|
||||
~wxSoundStreamG72X();
|
||||
|
||||
wxSoundStream& Read(void *buffer, wxUint32 len);
|
||||
wxSoundStream& Write(const void *buffer, wxUint32 len);
|
||||
|
||||
bool SetSoundFormat(const wxSoundFormatBase& format);
|
||||
|
||||
protected:
|
||||
wxSoundRouterStream *m_router;
|
||||
wxUint8 m_n_bits, m_current_mask, m_current_b_pos, m_current_byte;
|
||||
wxUint8 *m_io_buffer;
|
||||
g72state *m_state;
|
||||
|
||||
int (*m_coder)(int code, int in_code, struct g72x_state *state);
|
||||
int (*m_decoder)(int code, int out_code, struct g72x_state *state);
|
||||
|
||||
protected:
|
||||
void PutBits(wxUint8 bits);
|
||||
wxUint8 GetBits();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,338 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndoss.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "sndoss.cpp"
|
||||
#endif
|
||||
|
||||
#include <sys/soundcard.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <wx/defs.h>
|
||||
#include <wx/string.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndoss.h"
|
||||
#include "sndpcm.h"
|
||||
#ifdef __WXGTK__
|
||||
#include <gdk/gdk.h>
|
||||
#endif
|
||||
|
||||
wxSoundStreamOSS::wxSoundStreamOSS(const wxString& dev_name)
|
||||
{
|
||||
wxSoundFormatPcm pcm_default;
|
||||
|
||||
m_fd = open(dev_name.mb_str(), O_WRONLY);
|
||||
|
||||
if (m_fd == -1) {
|
||||
m_snderror = wxSOUND_INVDEV;
|
||||
return;
|
||||
}
|
||||
|
||||
m_devname = dev_name;
|
||||
|
||||
wxSoundStreamOSS::SetSoundFormat(pcm_default);
|
||||
|
||||
ioctl(m_fd, SNDCTL_DSP_GETBLKSIZE, &m_bufsize);
|
||||
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
|
||||
close(m_fd);
|
||||
|
||||
m_oss_stop = TRUE;
|
||||
m_q_filled = TRUE;
|
||||
}
|
||||
|
||||
wxSoundStreamOSS::~wxSoundStreamOSS()
|
||||
{
|
||||
if (m_fd > 0)
|
||||
close(m_fd);
|
||||
}
|
||||
|
||||
wxUint32 wxSoundStreamOSS::GetBestSize() const
|
||||
{
|
||||
return m_bufsize;
|
||||
}
|
||||
|
||||
wxSoundStream& wxSoundStreamOSS::Read(void *buffer, wxUint32 len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
m_lastcount = (wxUint32)ret = read(m_fd, buffer, len);
|
||||
m_q_filled = TRUE;
|
||||
|
||||
if (ret < 0)
|
||||
m_snderror = wxSOUND_IOERROR;
|
||||
else
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
wxSoundStream& wxSoundStreamOSS::Write(const void *buffer, wxUint32 len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
m_lastcount = (wxUint32)ret = write(m_fd, buffer, len);
|
||||
m_q_filled = TRUE;
|
||||
|
||||
if (ret < 0)
|
||||
m_snderror = wxSOUND_IOERROR;
|
||||
else
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool wxSoundStreamOSS::SetSoundFormat(const wxSoundFormatBase& format)
|
||||
{
|
||||
int tmp;
|
||||
wxSoundFormatPcm *pcm_format;
|
||||
|
||||
if (format.GetType() != wxSOUND_PCM) {
|
||||
m_snderror = wxSOUND_INVFRMT;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_fd == -1) {
|
||||
m_snderror = wxSOUND_INVDEV;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (m_sndformat)
|
||||
delete m_sndformat;
|
||||
|
||||
m_sndformat = format.Clone();
|
||||
if (!m_sndformat) {
|
||||
m_snderror = wxSOUND_MEMERROR;
|
||||
return FALSE;
|
||||
}
|
||||
pcm_format = (wxSoundFormatPcm *)m_sndformat;
|
||||
|
||||
// Set the sample rate field.
|
||||
tmp = pcm_format->GetSampleRate();
|
||||
ioctl(m_fd, SNDCTL_DSP_SPEED, &tmp);
|
||||
|
||||
pcm_format->SetSampleRate(tmp);
|
||||
|
||||
// Detect the best format
|
||||
DetectBest(pcm_format);
|
||||
SetupFormat(pcm_format);
|
||||
|
||||
tmp = pcm_format->GetChannels();
|
||||
ioctl(m_fd, SNDCTL_DSP_CHANNELS, &tmp);
|
||||
pcm_format->SetChannels(tmp);
|
||||
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
if (*pcm_format != format) {
|
||||
m_snderror = wxSOUND_NOEXACT;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundStreamOSS::SetupFormat(wxSoundFormatPcm *pcm_format)
|
||||
{
|
||||
int tmp;
|
||||
|
||||
switch(pcm_format->GetBPS()) {
|
||||
case 8:
|
||||
if (pcm_format->Signed())
|
||||
tmp = AFMT_S8;
|
||||
else
|
||||
tmp = AFMT_U8;
|
||||
break;
|
||||
case 16:
|
||||
switch (pcm_format->GetOrder()) {
|
||||
case wxBIG_ENDIAN:
|
||||
if (pcm_format->Signed())
|
||||
tmp = AFMT_S16_BE;
|
||||
else
|
||||
tmp = AFMT_U16_BE;
|
||||
break;
|
||||
case wxLITTLE_ENDIAN:
|
||||
if (pcm_format->Signed())
|
||||
tmp = AFMT_S16_LE;
|
||||
else
|
||||
tmp = AFMT_U16_LE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ioctl(m_fd, SNDCTL_DSP_SETFMT, &tmp);
|
||||
|
||||
// Demangling.
|
||||
switch (tmp) {
|
||||
case AFMT_U8:
|
||||
pcm_format->SetBPS(8);
|
||||
pcm_format->Signed(FALSE);
|
||||
break;
|
||||
case AFMT_S8:
|
||||
pcm_format->SetBPS(8);
|
||||
pcm_format->Signed(TRUE);
|
||||
break;
|
||||
case AFMT_U16_LE:
|
||||
pcm_format->SetBPS(16);
|
||||
pcm_format->Signed(FALSE);
|
||||
pcm_format->SetOrder(wxLITTLE_ENDIAN);
|
||||
break;
|
||||
case AFMT_U16_BE:
|
||||
pcm_format->SetBPS(16);
|
||||
pcm_format->Signed(FALSE);
|
||||
pcm_format->SetOrder(wxBIG_ENDIAN);
|
||||
break;
|
||||
case AFMT_S16_LE:
|
||||
pcm_format->SetBPS(16);
|
||||
pcm_format->Signed(TRUE);
|
||||
pcm_format->SetOrder(wxLITTLE_ENDIAN);
|
||||
break;
|
||||
case AFMT_S16_BE:
|
||||
pcm_format->SetBPS(16);
|
||||
pcm_format->Signed(TRUE);
|
||||
pcm_format->SetOrder(wxBIG_ENDIAN);
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef __WXGTK__
|
||||
static void _wxSound_OSS_CBack(gpointer data, int source,
|
||||
GdkInputCondition condition)
|
||||
{
|
||||
wxSoundStreamOSS *oss = (wxSoundStreamOSS *)data;
|
||||
|
||||
switch (condition) {
|
||||
case GDK_INPUT_READ:
|
||||
oss->WakeUpEvt(wxSOUND_INPUT);
|
||||
break;
|
||||
case GDK_INPUT_WRITE:
|
||||
oss->WakeUpEvt(wxSOUND_OUTPUT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void wxSoundStreamOSS::WakeUpEvt(int evt)
|
||||
{
|
||||
m_q_filled = FALSE;
|
||||
OnSoundEvent(evt);
|
||||
}
|
||||
|
||||
bool wxSoundStreamOSS::StartProduction(int evt)
|
||||
{
|
||||
wxSoundFormatBase *old_frmt;
|
||||
|
||||
if (!m_oss_stop)
|
||||
StopProduction();
|
||||
|
||||
old_frmt = m_sndformat->Clone();
|
||||
if (!old_frmt) {
|
||||
m_snderror = wxSOUND_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__
|
||||
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);
|
||||
|
||||
m_oss_stop = FALSE;
|
||||
m_q_filled = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundStreamOSS::StopProduction()
|
||||
{
|
||||
if (m_oss_stop)
|
||||
return FALSE;
|
||||
|
||||
#ifdef __WXGTK__
|
||||
gdk_input_remove(m_tag);
|
||||
#endif
|
||||
|
||||
close(m_fd);
|
||||
m_oss_stop = TRUE;
|
||||
m_q_filled = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundStreamOSS::QueueFilled() const
|
||||
{
|
||||
return m_q_filled;
|
||||
}
|
||||
|
||||
//
|
||||
// Detect the closest format (The best).
|
||||
//
|
||||
void wxSoundStreamOSS::DetectBest(wxSoundFormatPcm *pcm)
|
||||
{
|
||||
#define MASK_16BITS (AFMT_S16_LE | AFMT_S16_BE | AFMT_U16_LE | AFMT_U16_BE)
|
||||
|
||||
int fmt_mask;
|
||||
wxSoundFormatPcm best_pcm;
|
||||
|
||||
// We change neither the number of channels nor the sample rate
|
||||
|
||||
best_pcm.SetSampleRate(pcm->GetSampleRate());
|
||||
best_pcm.SetChannels(pcm->GetChannels());
|
||||
|
||||
// Get the supported format by the sound card
|
||||
ioctl(m_fd, SNDCTL_DSP_GETFMTS, &fmt_mask);
|
||||
|
||||
// It supports 16 bits
|
||||
if (pcm->GetBPS() == 16 && ((fmt_mask & MASK_16BITS) != 0))
|
||||
best_pcm.SetBPS(16);
|
||||
|
||||
// It supports big endianness
|
||||
if (pcm->GetOrder() == wxBIG_ENDIAN && ((fmt_mask & (AFMT_S16_BE | AFMT_U16_BE)) != 0))
|
||||
best_pcm.SetOrder(wxBIG_ENDIAN);
|
||||
|
||||
// It supports little endianness
|
||||
if (pcm->GetOrder() == wxLITTLE_ENDIAN && ((fmt_mask & (AFMT_S16_LE | AFMT_U16_LE)) != 0))
|
||||
best_pcm.SetOrder(wxLITTLE_ENDIAN);
|
||||
|
||||
// It supports signed samples
|
||||
if (pcm->Signed() && ((fmt_mask & (AFMT_S16_LE | AFMT_S16_BE | AFMT_S8)) != 0))
|
||||
best_pcm.Signed(TRUE);
|
||||
|
||||
// It supports unsigned samples
|
||||
if (!pcm->Signed() && ((fmt_mask & (AFMT_U16_LE | AFMT_U16_BE | AFMT_U8)) != 0))
|
||||
best_pcm.Signed(FALSE);
|
||||
|
||||
// Finally recopy the new format
|
||||
*pcm = best_pcm;
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndoss.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDOSS_H
|
||||
#define _WX_SNDOSS_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "sndoss.h"
|
||||
#endif
|
||||
|
||||
#include <wx/string.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndpcm.h"
|
||||
|
||||
//
|
||||
// OSS output class
|
||||
//
|
||||
|
||||
class wxSoundStreamOSS : public wxSoundStream {
|
||||
public:
|
||||
wxSoundStreamOSS(const wxString& dev_name = _T("/dev/dsp"));
|
||||
~wxSoundStreamOSS();
|
||||
|
||||
wxSoundStream& Read(void *buffer, wxUint32 len);
|
||||
wxSoundStream& Write(const void *buffer, wxUint32 len);
|
||||
wxUint32 GetBestSize() const;
|
||||
|
||||
bool SetSoundFormat(const wxSoundFormatBase& format);
|
||||
|
||||
bool StartProduction(int evt);
|
||||
bool StopProduction();
|
||||
|
||||
bool QueueFilled() const;
|
||||
|
||||
// You should not call this.
|
||||
void WakeUpEvt(int evt);
|
||||
protected:
|
||||
int m_fd;
|
||||
wxUint32 m_bufsize;
|
||||
int m_tag;
|
||||
bool m_oss_stop, m_q_filled;
|
||||
wxString m_devname;
|
||||
|
||||
private:
|
||||
bool SetupFormat(wxSoundFormatPcm *pcm);
|
||||
void DetectBest(wxSoundFormatPcm *pcm);
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,89 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndpcm.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "sndpcm.cpp"
|
||||
#endif
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndpcm.h"
|
||||
|
||||
wxSoundFormatPcm::wxSoundFormatPcm(wxUint32 srate, wxUint8 bps,
|
||||
wxUint16 nchannels, bool sign,
|
||||
int order)
|
||||
: m_srate(srate), m_bps(bps), m_nchan(nchannels), m_order(order),
|
||||
m_signed(sign)
|
||||
{
|
||||
}
|
||||
|
||||
wxSoundFormatPcm::~wxSoundFormatPcm()
|
||||
{
|
||||
}
|
||||
|
||||
void wxSoundFormatPcm::SetSampleRate(wxUint32 srate)
|
||||
{
|
||||
m_srate = srate;
|
||||
}
|
||||
|
||||
void wxSoundFormatPcm::SetBPS(wxUint8 bps)
|
||||
{
|
||||
m_bps = bps;
|
||||
}
|
||||
|
||||
void wxSoundFormatPcm::SetChannels(wxUint16 nchannels)
|
||||
{
|
||||
m_nchan = nchannels;
|
||||
}
|
||||
|
||||
void wxSoundFormatPcm::SetOrder(int order)
|
||||
{
|
||||
m_order = order;
|
||||
}
|
||||
|
||||
void wxSoundFormatPcm::Signed(bool sign)
|
||||
{
|
||||
m_signed = sign;
|
||||
}
|
||||
|
||||
wxSoundFormatBase *wxSoundFormatPcm::Clone() const
|
||||
{
|
||||
wxSoundFormatPcm *new_pcm;
|
||||
|
||||
new_pcm = new wxSoundFormatPcm();
|
||||
new_pcm->m_srate = m_srate;
|
||||
new_pcm->m_bps = m_bps;
|
||||
new_pcm->m_nchan = m_nchan;
|
||||
new_pcm->m_order = m_order;
|
||||
new_pcm->m_signed= m_signed;
|
||||
|
||||
return new_pcm;
|
||||
}
|
||||
|
||||
wxUint32 wxSoundFormatPcm::GetTimeFromBytes(wxUint32 bytes) const
|
||||
{
|
||||
return (bytes / (m_srate * (m_bps / 8) * m_nchan));
|
||||
}
|
||||
|
||||
wxUint32 wxSoundFormatPcm::GetBytesFromTime(wxUint32 time) const
|
||||
{
|
||||
return (time * (m_srate * (m_bps / 8) * m_nchan));
|
||||
}
|
||||
|
||||
bool wxSoundFormatPcm::operator!=(const wxSoundFormatBase& format) const
|
||||
{
|
||||
wxSoundFormatPcm *format2 = (wxSoundFormatPcm *)&format;
|
||||
|
||||
if (format.GetType() != wxSOUND_PCM)
|
||||
return TRUE;
|
||||
|
||||
return ( (m_srate != format2->m_srate) ||
|
||||
(m_bps != format2->m_bps) ||
|
||||
(m_nchan != format2->m_nchan) ||
|
||||
(m_order != format2->m_order) ||
|
||||
(m_signed != format2->m_signed) );
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndpcm.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDPCM_H
|
||||
#define _WX_SNDPCM_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "sndpcm.h"
|
||||
#endif
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include "sndbase.h"
|
||||
|
||||
//
|
||||
// PCM specification class
|
||||
//
|
||||
|
||||
class wxSoundFormatPcm : public wxSoundFormatBase {
|
||||
public:
|
||||
wxSoundFormatPcm(wxUint32 srate = 22500, wxUint8 bps = 8,
|
||||
wxUint16 channels = 2, bool sign = TRUE,
|
||||
int order = wxLITTLE_ENDIAN);
|
||||
~wxSoundFormatPcm();
|
||||
|
||||
void SetSampleRate(wxUint32 srate);
|
||||
void SetBPS(wxUint8 bps);
|
||||
void SetChannels(wxUint16 nchannels);
|
||||
void SetOrder(int order);
|
||||
void Signed(bool sign);
|
||||
|
||||
wxUint32 GetSampleRate() const { return m_srate; }
|
||||
wxUint8 GetBPS() const { return m_bps; }
|
||||
wxUint16 GetChannels() const { return m_nchan; }
|
||||
int GetOrder() const { return m_order; }
|
||||
bool Signed() const { return m_signed; }
|
||||
|
||||
wxSoundFormatType GetType() const { return wxSOUND_PCM; }
|
||||
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_bps;
|
||||
wxUint16 m_nchan;
|
||||
int m_order;
|
||||
bool m_signed;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,180 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndulaw.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "sndulaw.cpp"
|
||||
#endif
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#endif
|
||||
|
||||
#include "sndbase.h"
|
||||
#include "sndfile.h"
|
||||
#include "sndpcm.h"
|
||||
#include "sndulaw.h"
|
||||
#include "g72x.h"
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// wxSoundFormatUlaw
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
wxSoundFormatUlaw::wxSoundFormatUlaw()
|
||||
: m_srate(22050), m_channels(1)
|
||||
{
|
||||
}
|
||||
|
||||
wxSoundFormatUlaw::~wxSoundFormatUlaw()
|
||||
{
|
||||
}
|
||||
|
||||
void wxSoundFormatUlaw::SetSampleRate(wxUint32 srate)
|
||||
{
|
||||
m_srate = srate;
|
||||
}
|
||||
|
||||
wxUint32 wxSoundFormatUlaw::GetSampleRate() const
|
||||
{
|
||||
return m_srate;
|
||||
}
|
||||
|
||||
wxUint8 wxSoundFormatUlaw::GetChannels() const
|
||||
{
|
||||
return m_channels;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
wxUint32 wxSoundFormatUlaw::GetBytesFromTime(wxUint32 time) const
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// wxSoundStreamUlaw
|
||||
// --------------------------------------------------------------------------
|
||||
wxSoundStreamUlaw::wxSoundStreamUlaw(wxSoundStream& sndio)
|
||||
: wxSoundStreamCodec(sndio)
|
||||
{
|
||||
// PCM converter
|
||||
m_router = new wxSoundRouterStream(sndio);
|
||||
}
|
||||
|
||||
wxSoundStreamUlaw::~wxSoundStreamUlaw()
|
||||
{
|
||||
delete m_router;
|
||||
}
|
||||
|
||||
wxSoundStream& wxSoundStreamUlaw::Read(void *buffer, wxUint32 len)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
wxUint32 wxSoundStreamUlaw::GetBestSize() const
|
||||
{
|
||||
return m_sndio->GetBestSize() / 2;
|
||||
}
|
||||
|
||||
bool wxSoundStreamUlaw::SetSoundFormat(const wxSoundFormatBase& format)
|
||||
{
|
||||
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;
|
||||
}
|
@@ -1,68 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndulaw.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDULAW_H
|
||||
#define _WX_SNDULAW_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#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;
|
||||
wxUint8 m_channels;
|
||||
};
|
||||
|
||||
//
|
||||
// ULAW converter class
|
||||
//
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,355 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndwav.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "sndwav.cpp"
|
||||
#endif
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
#include <wx/stream.h>
|
||||
#include <wx/datstrm.h>
|
||||
#include <wx/filefn.h>
|
||||
#include <wx/mstream.h>
|
||||
|
||||
#include "sndbase.h"
|
||||
#include "sndcodec.h"
|
||||
#include "sndfile.h"
|
||||
#include "sndpcm.h"
|
||||
#include "sndg72x.h"
|
||||
#include "sndwav.h"
|
||||
|
||||
#define BUILD_SIGNATURE(a,b,c,d) (((wxUint32)a) | (((wxUint32)b) << 8) | (((wxUint32)c) << 16) | (((wxUint32)d) << 24))
|
||||
|
||||
#define RIFF_SIGNATURE BUILD_SIGNATURE('R','I','F','F')
|
||||
#define WAVE_SIGNATURE BUILD_SIGNATURE('W','A','V','E')
|
||||
#define FMT_SIGNATURE BUILD_SIGNATURE('f','m','t',' ')
|
||||
#define DATA_SIGNATURE BUILD_SIGNATURE('d','a','t','a')
|
||||
|
||||
#define HEADER_SIZE 4+4 + 4+4+16 + 4+4
|
||||
// 4+4 => NAME + LEN
|
||||
// 16 => fmt size
|
||||
|
||||
wxSoundWave::wxSoundWave(wxInputStream& stream, wxSoundStream& io_sound)
|
||||
: wxSoundFileStream(stream, io_sound)
|
||||
{
|
||||
m_base_offset = wxInvalidOffset;
|
||||
}
|
||||
|
||||
wxSoundWave::wxSoundWave(wxOutputStream& stream, wxSoundStream& io_sound)
|
||||
: wxSoundFileStream(stream, io_sound)
|
||||
{
|
||||
m_base_offset = wxInvalidOffset;
|
||||
}
|
||||
|
||||
wxSoundWave::~wxSoundWave()
|
||||
{
|
||||
}
|
||||
|
||||
wxString wxSoundWave::GetCodecName() const
|
||||
{
|
||||
return wxString(wxT("wxSoundWave codec"));
|
||||
}
|
||||
|
||||
#define FAIL_WITH(condition, err) if (condition) { m_snderror = err; return FALSE; }
|
||||
|
||||
bool wxSoundWave::CanRead()
|
||||
{
|
||||
wxUint32 len, signature1, signature2;
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
|
||||
// Test the main signatures:
|
||||
// "RIFF"
|
||||
FAIL_WITH(m_input->Read(&signature1, 4).LastRead() != 4, wxSOUND_INVSTRM);
|
||||
|
||||
if (wxUINT32_SWAP_ON_BE(signature1) != RIFF_SIGNATURE) {
|
||||
m_input->Ungetch(&signature1, 4);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Pass the global length
|
||||
m_input->Read(&len, 4);
|
||||
FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
|
||||
|
||||
// Get the second signature
|
||||
FAIL_WITH(m_input->Read(&signature2, 4).LastRead() != 4, wxSOUND_INVSTRM);
|
||||
// Ungetch all
|
||||
m_input->Ungetch(&signature2, 4);
|
||||
m_input->Ungetch(&len, 4);
|
||||
m_input->Ungetch(&signature1, 4);
|
||||
|
||||
// Test the second signature
|
||||
if (wxUINT32_SWAP_ON_BE(signature2) != WAVE_SIGNATURE)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundWave::HandleOutputPCM(wxDataInputStream& data, wxUint16 channels,
|
||||
wxUint32 sample_fq, wxUint32 byte_p_sec,
|
||||
wxUint16 byte_p_spl, wxUint16 bits_p_spl)
|
||||
{
|
||||
wxSoundFormatPcm sndformat;
|
||||
|
||||
sndformat.SetSampleRate(sample_fq);
|
||||
sndformat.SetBPS(bits_p_spl);
|
||||
sndformat.SetChannels(channels);
|
||||
sndformat.Signed(TRUE);
|
||||
sndformat.SetOrder(wxLITTLE_ENDIAN);
|
||||
|
||||
if (!SetSoundFormat(sndformat))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundWave::HandleOutputG721(wxDataInputStream& data, wxUint16 channels,
|
||||
wxUint32 sample_fq, wxUint32 byte_p_sec,
|
||||
wxUint16 byte_p_spl, wxUint16 bits_p_spl)
|
||||
{
|
||||
wxSoundFormatG72X sndformat;
|
||||
|
||||
sndformat.SetSampleRate(sample_fq);
|
||||
sndformat.SetG72XType(wxSOUND_G721);
|
||||
|
||||
if (!SetSoundFormat(sndformat))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundWave::PrepareToPlay()
|
||||
{
|
||||
wxUint32 signature, len;
|
||||
bool end_headers;
|
||||
|
||||
if (!m_input) {
|
||||
m_snderror = wxSOUND_INVSTRM;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wxDataInputStream data(*m_input);
|
||||
data.BigEndianOrdered(FALSE);
|
||||
|
||||
// Get the first signature
|
||||
FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
|
||||
FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != RIFF_SIGNATURE, wxSOUND_INVSTRM);
|
||||
// "RIFF"
|
||||
|
||||
len = data.Read32();
|
||||
FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
|
||||
// dummy len
|
||||
|
||||
// Get the second signature
|
||||
FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
|
||||
FAIL_WITH(wxUINT32_SWAP_ON_BE(signature) != WAVE_SIGNATURE, wxSOUND_INVSTRM);
|
||||
// "WAVE"
|
||||
|
||||
end_headers = FALSE;
|
||||
// Chunk loop
|
||||
while (!end_headers) {
|
||||
FAIL_WITH(m_input->Read(&signature, 4).LastRead() != 4, wxSOUND_INVSTRM);
|
||||
|
||||
len = data.Read32();
|
||||
FAIL_WITH(m_input->LastRead() != 4, wxSOUND_INVSTRM);
|
||||
|
||||
switch (wxUINT32_SWAP_ON_BE(signature)) {
|
||||
case FMT_SIGNATURE: { // "fmt "
|
||||
wxUint16 format, channels, byte_p_spl, bits_p_spl;
|
||||
wxUint32 sample_fq, byte_p_sec;
|
||||
|
||||
// Get the common parameters
|
||||
data >> format >> channels >> sample_fq
|
||||
>> byte_p_sec >> byte_p_spl >> bits_p_spl;
|
||||
|
||||
switch (format) {
|
||||
case 0x01: // PCM
|
||||
if (!HandleOutputPCM(data, channels, sample_fq,
|
||||
byte_p_sec, byte_p_spl, bits_p_spl))
|
||||
return FALSE;
|
||||
break;
|
||||
case 0x40: // G721
|
||||
if (!HandleOutputG721(data, channels, sample_fq,
|
||||
byte_p_sec, byte_p_spl, bits_p_spl))
|
||||
return FALSE;
|
||||
break;
|
||||
default:
|
||||
m_snderror = wxSOUND_NOCODEC;
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DATA_SIGNATURE: // "data"
|
||||
m_base_offset = m_input->TellI();
|
||||
end_headers = TRUE;
|
||||
FinishPreparation(len);
|
||||
break;
|
||||
default:
|
||||
// We pass the chunk
|
||||
m_input->SeekI(len, wxFromCurrent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
wxSoundFormatBase *wxSoundWave::HandleInputPCM(wxDataOutputStream& data)
|
||||
{
|
||||
wxUint16 format, channels, byte_p_spl, bits_p_spl;
|
||||
wxUint32 sample_fq, byte_p_sec;
|
||||
wxSoundFormatPcm *pcm;
|
||||
|
||||
pcm = (wxSoundFormatPcm *)(m_sndformat->Clone());
|
||||
|
||||
// Write block length
|
||||
data.Write32(16);
|
||||
|
||||
sample_fq = pcm->GetSampleRate();
|
||||
bits_p_spl = pcm->GetBPS();
|
||||
channels = pcm->GetChannels();
|
||||
byte_p_spl = pcm->GetBPS() / 8;
|
||||
byte_p_sec = pcm->GetBytesFromTime(1);
|
||||
format = 0x01;
|
||||
|
||||
pcm->Signed(TRUE);
|
||||
pcm->SetOrder(wxLITTLE_ENDIAN);
|
||||
|
||||
data << format << channels << sample_fq
|
||||
<< byte_p_sec << byte_p_spl << bits_p_spl;
|
||||
|
||||
return pcm;
|
||||
}
|
||||
|
||||
wxSoundFormatBase *wxSoundWave::HandleInputG72X(wxDataOutputStream& data)
|
||||
{
|
||||
wxUint16 format, channels, byte_p_spl, bits_p_spl;
|
||||
wxUint32 sample_fq, byte_p_sec;
|
||||
wxSoundFormatG72X *g72x;
|
||||
|
||||
// Write block length
|
||||
data.Write32(16);
|
||||
|
||||
g72x = (wxSoundFormatG72X *)(m_sndformat->Clone());
|
||||
if (g72x->GetG72XType() != wxSOUND_G721) {
|
||||
delete g72x;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sample_fq = g72x->GetSampleRate();
|
||||
bits_p_spl = 4;
|
||||
channels = 1;
|
||||
byte_p_spl = 0;
|
||||
byte_p_sec = g72x->GetBytesFromTime(1);
|
||||
format = 0x40;
|
||||
data << format << channels << sample_fq
|
||||
<< byte_p_sec << byte_p_spl << bits_p_spl;
|
||||
|
||||
return g72x;
|
||||
}
|
||||
|
||||
bool wxSoundWave::PrepareToRecord(wxUint32 time)
|
||||
{
|
||||
#define WRITE_SIGNATURE(s,sig) \
|
||||
signature = sig; \
|
||||
signature = wxUINT32_SWAP_ON_BE(signature); \
|
||||
FAIL_WITH(s->Write(&signature, 4).LastWrite() != 4, wxSOUND_INVSTRM);
|
||||
|
||||
wxUint32 signature;
|
||||
wxMemoryOutputStream fmt_data;
|
||||
|
||||
if (!m_output) {
|
||||
m_snderror = wxSOUND_INVSTRM;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wxDataOutputStream data(*m_output);
|
||||
wxDataOutputStream fmt_d_data(fmt_data);
|
||||
|
||||
data.BigEndianOrdered(FALSE);
|
||||
fmt_d_data.BigEndianOrdered(FALSE);
|
||||
|
||||
WRITE_SIGNATURE(m_output, RIFF_SIGNATURE);
|
||||
|
||||
FAIL_WITH(m_output->LastWrite() != 4, wxSOUND_INVSTRM);
|
||||
|
||||
WRITE_SIGNATURE((&fmt_data), WAVE_SIGNATURE);
|
||||
|
||||
{
|
||||
wxSoundFormatBase *frmt;
|
||||
|
||||
WRITE_SIGNATURE((&fmt_data), FMT_SIGNATURE);
|
||||
|
||||
switch (m_sndformat->GetType()) {
|
||||
case wxSOUND_PCM:
|
||||
frmt = HandleInputPCM(fmt_d_data);
|
||||
break;
|
||||
case wxSOUND_G72X:
|
||||
frmt = HandleInputG72X(fmt_d_data);
|
||||
break;
|
||||
default:
|
||||
m_snderror = wxSOUND_NOCODEC;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FAIL_WITH(!frmt, wxSOUND_NOCODEC);
|
||||
|
||||
if (!SetSoundFormat(*frmt)) {
|
||||
delete frmt;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
delete frmt;
|
||||
}
|
||||
|
||||
data << (fmt_data.GetSize() + m_sndformat->GetBytesFromTime(time));
|
||||
|
||||
// We, finally, copy the header block to the output stream
|
||||
{
|
||||
char *out_buf;
|
||||
out_buf = new char[fmt_data.GetSize()];
|
||||
|
||||
fmt_data.CopyTo(out_buf, fmt_data.GetSize());
|
||||
m_output->Write(out_buf, fmt_data.GetSize());
|
||||
|
||||
delete[] out_buf;
|
||||
}
|
||||
|
||||
WRITE_SIGNATURE(m_output, DATA_SIGNATURE);
|
||||
data.Write32(m_sndformat->GetBytesFromTime(time));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundWave::FinishRecording()
|
||||
{
|
||||
if (m_output->SeekO(0, wxFromStart) == wxInvalidOffset)
|
||||
// We can't but there is no error.
|
||||
return TRUE;
|
||||
|
||||
if (m_bytes_left == 0)
|
||||
return TRUE;
|
||||
|
||||
// TODO: Update headers when we stop before the specified time (if possible)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxSoundWave::RepositionStream(wxUint32 position)
|
||||
{
|
||||
if (m_base_offset == wxInvalidOffset)
|
||||
return FALSE;
|
||||
m_input->SeekI(m_base_offset, wxFromStart);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
wxUint32 wxSoundWave::GetData(void *buffer, wxUint32 len)
|
||||
{
|
||||
return m_input->Read(buffer, len).LastRead();
|
||||
}
|
||||
|
||||
wxUint32 wxSoundWave::PutData(const void *buffer, wxUint32 len)
|
||||
{
|
||||
return m_output->Write(buffer, len).LastWrite();
|
||||
}
|
@@ -1,57 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndwav.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDWAV_H
|
||||
#define _WX_SNDWAV_H
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "sndwav.h"
|
||||
#endif
|
||||
|
||||
#include <wx/defs.h>
|
||||
#include <wx/stream.h>
|
||||
#include <wx/datstrm.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndcodec.h"
|
||||
#include "sndfile.h"
|
||||
|
||||
//
|
||||
// WAVE codec
|
||||
//
|
||||
|
||||
class wxSoundWave: public wxSoundFileStream {
|
||||
public:
|
||||
wxSoundWave(wxInputStream& stream, wxSoundStream& io_sound);
|
||||
wxSoundWave(wxOutputStream& stream, wxSoundStream& io_sound);
|
||||
~wxSoundWave();
|
||||
|
||||
bool CanRead();
|
||||
wxString GetCodecName() const;
|
||||
|
||||
protected:
|
||||
bool PrepareToPlay();
|
||||
bool PrepareToRecord(wxUint32 time);
|
||||
bool FinishRecording();
|
||||
bool RepositionStream(wxUint32 position);
|
||||
|
||||
wxUint32 GetData(void *buffer, wxUint32 len);
|
||||
wxUint32 PutData(const void *buffer, wxUint32 len);
|
||||
|
||||
bool HandleOutputPCM(wxDataInputStream& data, wxUint16 channels,
|
||||
wxUint32 sample_fq, wxUint32 byte_p_sec,
|
||||
wxUint16 byte_p_spl, wxUint16 bits_p_spl);
|
||||
bool HandleOutputG721(wxDataInputStream& data, wxUint16 channels,
|
||||
wxUint32 sample_fq, wxUint32 byte_p_sec,
|
||||
wxUint16 byte_p_spl, wxUint16 bits_p_spl);
|
||||
wxSoundFormatBase *HandleInputPCM(wxDataOutputStream& data);
|
||||
wxSoundFormatBase *HandleInputG72X(wxDataOutputStream& data);
|
||||
|
||||
protected:
|
||||
off_t m_base_offset;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,751 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndwin.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999, 2000
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
#include <wx/app.h>
|
||||
#include <wx/module.h>
|
||||
#include <wx/msw/private.h>
|
||||
#include <string.h>
|
||||
#include "sndbase.h"
|
||||
#include "sndwin.h"
|
||||
#include "sndpcm.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
typedef struct _wxSoundInternal wxSoundInternal;
|
||||
typedef struct _wxSoundInfoHeader wxSoundInfoHeader;
|
||||
|
||||
extern const wxChar *wxCanvasClassName;
|
||||
|
||||
wxList *wxSoundHandleList = NULL;
|
||||
|
||||
static inline wxSoundStreamWin *wxFindSoundFromHandle(WXHWND hWnd)
|
||||
{
|
||||
wxNode *node = wxSoundHandleList->Find((long)hWnd);
|
||||
if (!node)
|
||||
return NULL;
|
||||
return (wxSoundStreamWin *)node->Data();
|
||||
}
|
||||
|
||||
struct _wxSoundInternal {
|
||||
HWND m_sndWin;
|
||||
HWAVEIN m_devin;
|
||||
HWAVEOUT m_devout;
|
||||
bool m_output_enabled, m_input_enabled;
|
||||
};
|
||||
|
||||
struct _wxSoundInfoHeader {
|
||||
HGLOBAL m_h_header, m_h_data;
|
||||
char *m_data;
|
||||
WAVEHDR *m_header;
|
||||
int m_mode;
|
||||
bool m_playing, m_recording;
|
||||
wxUint32 m_position, m_size;
|
||||
|
||||
wxSoundStreamWin *m_driver;
|
||||
};
|
||||
|
||||
#define WXSOUND_MAX_QUEUE 10
|
||||
|
||||
wxSoundStreamWin::wxSoundStreamWin()
|
||||
{
|
||||
wxSoundFormatPcm pcm;
|
||||
|
||||
m_production_started = FALSE;
|
||||
m_internal = new wxSoundInternal;
|
||||
if (!m_internal) {
|
||||
m_snderror = wxSOUND_MEMERROR;
|
||||
m_internal = NULL;
|
||||
return;
|
||||
}
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
|
||||
// Setup defaults
|
||||
CreateSndWindow();
|
||||
SetSoundFormat(pcm);
|
||||
|
||||
m_internal->m_input_enabled = FALSE;
|
||||
m_internal->m_output_enabled = FALSE;
|
||||
|
||||
m_waiting_for = FALSE;
|
||||
|
||||
if (!OpenDevice(wxSOUND_OUTPUT))
|
||||
return;
|
||||
|
||||
CloseDevice();
|
||||
}
|
||||
|
||||
wxSoundStreamWin::~wxSoundStreamWin()
|
||||
{
|
||||
if (m_internal) {
|
||||
if (m_production_started)
|
||||
StopProduction();
|
||||
DestroySndWindow();
|
||||
|
||||
delete m_internal;
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// _wxSoundHandlerWndProc: Window callback to handle buffer completion
|
||||
// -----------------------------------------------------------------------
|
||||
LRESULT APIENTRY _EXPORT _wxSoundHandlerWndProc(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
wxSoundStreamWin *sndwin;
|
||||
|
||||
sndwin = wxFindSoundFromHandle((WXHWND)hWnd);
|
||||
if (!sndwin)
|
||||
return (LRESULT)0;
|
||||
|
||||
switch (message) {
|
||||
case MM_WOM_DONE:
|
||||
sndwin->NotifyDoneBuffer(wParam, wxSOUND_OUTPUT);
|
||||
break;
|
||||
case MM_WIM_DATA:
|
||||
sndwin->NotifyDoneBuffer(wParam, wxSOUND_INPUT);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (LRESULT)0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// CreateSndWindow() creates an hidden window which will receive the sound
|
||||
// events
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void wxSoundStreamWin::CreateSndWindow()
|
||||
{
|
||||
FARPROC proc = MakeProcInstance((FARPROC)_wxSoundHandlerWndProc,
|
||||
wxGetInstance());
|
||||
int error;
|
||||
|
||||
m_internal->m_sndWin = ::CreateWindow(wxCanvasClassName, NULL, 0,
|
||||
0, 0, 0, 0, NULL, (HMENU) NULL,
|
||||
wxGetInstance(), NULL);
|
||||
|
||||
error = GetLastError();
|
||||
|
||||
::SetWindowLong(m_internal->m_sndWin, GWL_WNDPROC, (LONG)proc);
|
||||
|
||||
// Add this window to the sound handle list so we'll be able to redecode
|
||||
// the "magic" number.
|
||||
wxSoundHandleList->Append((long)m_internal->m_sndWin, (wxObject *)this);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// DestroySndWindow() destroys the hidden window
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void wxSoundStreamWin::DestroySndWindow()
|
||||
{
|
||||
if (m_internal->m_sndWin) {
|
||||
::DestroyWindow(m_internal->m_sndWin);
|
||||
wxSoundHandleList->DeleteObject((wxObject *)this);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// OpenDevice(int mode) initializes the windows driver for a "mode"
|
||||
// operation. mode is a bit mask: if the bit "wxSOUND_OUTPUT" is set,
|
||||
// the driver is opened for output operation, and if the bit "wxSOUND_INPUT"
|
||||
// is set, then the driver is opened for input operation. The two modes
|
||||
// aren't exclusive.
|
||||
// The initialization parameters (sample rate, ...) are taken from the
|
||||
// m_sndformat object.
|
||||
// At the end, OpenDevice() calls AllocHeaders() to initialize the Sound IO
|
||||
// queue.
|
||||
// -------------------------------------------------------------------------
|
||||
bool wxSoundStreamWin::OpenDevice(int mode)
|
||||
{
|
||||
wxSoundFormatPcm *pcm;
|
||||
WAVEFORMATEX wformat;
|
||||
|
||||
if (!m_sndformat) {
|
||||
m_snderror = wxSOUND_INVFRMT;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pcm = (wxSoundFormatPcm *)m_sndformat;
|
||||
|
||||
wformat.wFormatTag = WAVE_FORMAT_PCM;
|
||||
wformat.nChannels = pcm->GetChannels();
|
||||
wformat.nBlockAlign = wformat.nChannels * pcm->GetBPS() / 8;
|
||||
wformat.nSamplesPerSec = pcm->GetSampleRate();
|
||||
wformat.nAvgBytesPerSec = wformat.nSamplesPerSec * wformat.nBlockAlign;
|
||||
wformat.wBitsPerSample = pcm->GetBPS();
|
||||
wformat.cbSize = 0;
|
||||
|
||||
// -----------------------------------
|
||||
// Open the driver for Output operation
|
||||
// -----------------------------------
|
||||
if (mode & wxSOUND_OUTPUT) {
|
||||
MMRESULT result;
|
||||
|
||||
result = waveOutOpen(&m_internal->m_devout,
|
||||
WAVE_MAPPER, &wformat,
|
||||
(DWORD)m_internal->m_sndWin, 0,
|
||||
CALLBACK_WINDOW);
|
||||
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
m_snderror = wxSOUND_INVDEV;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_output_frag_out = WXSOUND_MAX_QUEUE-1;
|
||||
m_current_frag_out = 0;
|
||||
|
||||
m_internal->m_output_enabled = TRUE;
|
||||
}
|
||||
// -----------------------------------
|
||||
// Open the driver for Input operation
|
||||
// -----------------------------------
|
||||
if (mode & wxSOUND_INPUT) {
|
||||
MMRESULT result;
|
||||
|
||||
result = waveInOpen(&m_internal->m_devin,
|
||||
WAVE_MAPPER, &wformat,
|
||||
(DWORD)m_internal->m_sndWin, 0,
|
||||
CALLBACK_WINDOW);
|
||||
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
m_snderror = wxSOUND_INVDEV;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_current_frag_in = WXSOUND_MAX_QUEUE-1;
|
||||
m_input_frag_in = 0;
|
||||
|
||||
m_internal->m_input_enabled = TRUE;
|
||||
}
|
||||
|
||||
if (mode & wxSOUND_OUTPUT) {
|
||||
if (!AllocHeaders(wxSOUND_OUTPUT)) {
|
||||
CloseDevice();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (mode & wxSOUND_INPUT) {
|
||||
if (!AllocHeaders(wxSOUND_INPUT)) {
|
||||
CloseDevice();
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// CloseDevice() closes the driver handles and frees memory allocated for
|
||||
// IO queues.
|
||||
// -------------------------------------------------------------------------
|
||||
void wxSoundStreamWin::CloseDevice()
|
||||
{
|
||||
if (m_internal->m_output_enabled) {
|
||||
FreeHeaders(wxSOUND_OUTPUT);
|
||||
m_internal->m_output_enabled = FALSE;
|
||||
waveOutClose(m_internal->m_devout);
|
||||
}
|
||||
|
||||
if (m_internal->m_input_enabled) {
|
||||
FreeHeaders(wxSOUND_INPUT);
|
||||
m_internal->m_input_enabled = FALSE;
|
||||
waveInClose(m_internal->m_devin);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// AllocHeader(int mode)
|
||||
//
|
||||
// mode has the same mean as in OpenDevice() except that here the two flags
|
||||
// must be exclusive.
|
||||
// AllocHeader() initializes an element of an operation (this can be input
|
||||
// or output). It means it allocates the sound header's memory block
|
||||
// and "prepares" it (It is needed by Windows). At the same time, it sets
|
||||
// private datas so we can the header's owner (See callback).
|
||||
//
|
||||
// It returns the new allocated block or NULL.
|
||||
// -------------------------------------------------------------------------
|
||||
wxSoundInfoHeader *wxSoundStreamWin::AllocHeader(int mode)
|
||||
{
|
||||
wxSoundInfoHeader *info;
|
||||
WAVEHDR *header;
|
||||
|
||||
// Some memory allocation
|
||||
info = new wxSoundInfoHeader;
|
||||
info->m_h_data = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, GetBestSize());
|
||||
info->m_h_header = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, sizeof(WAVEHDR));
|
||||
if (!info->m_h_data || !info->m_h_header) {
|
||||
delete info;
|
||||
m_snderror = wxSOUND_MEMERR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Get the two pointers from the system
|
||||
info->m_data = (char *)GlobalLock(info->m_h_data);
|
||||
info->m_header = (WAVEHDR *)GlobalLock(info->m_h_header);
|
||||
// Set the header's mode
|
||||
info->m_mode = mode;
|
||||
// Set the parent of the header
|
||||
info->m_driver = this;
|
||||
// Clean it up
|
||||
ClearHeader(info);
|
||||
|
||||
header = info->m_header;
|
||||
// Initialize Windows variables
|
||||
header->lpData = info->m_data;
|
||||
header->dwBufferLength = GetBestSize();
|
||||
header->dwUser = (DWORD)info;
|
||||
header->dwFlags = WHDR_DONE;
|
||||
|
||||
// "Prepare" the header
|
||||
if (mode == wxSOUND_INPUT) {
|
||||
MMRESULT result;
|
||||
|
||||
result = waveInPrepareHeader(m_internal->m_devin, header,
|
||||
sizeof(WAVEHDR));
|
||||
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
// If something goes wrong, free everything.
|
||||
GlobalUnlock(info->m_data);
|
||||
GlobalUnlock(info->m_header);
|
||||
GlobalFree(info->m_h_data);
|
||||
GlobalFree(info->m_h_header);
|
||||
delete info;
|
||||
|
||||
m_snderror = wxSOUND_IOERROR;
|
||||
return NULL;
|
||||
}
|
||||
} else if (mode == wxSOUND_OUTPUT) {
|
||||
MMRESULT result;
|
||||
|
||||
result = waveOutPrepareHeader(m_internal->m_devout, header,
|
||||
sizeof(WAVEHDR));
|
||||
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
// If something goes wrong, free everything.
|
||||
GlobalUnlock(info->m_data);
|
||||
GlobalUnlock(info->m_header);
|
||||
GlobalFree(info->m_h_data);
|
||||
GlobalFree(info->m_h_header);
|
||||
delete info;
|
||||
|
||||
m_snderror = wxSOUND_IOERROR;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// AllocHeaders(int mode)
|
||||
//
|
||||
// "mode" has the same mean as for OpenDevice() except that the two flags must
|
||||
// be exclusive.
|
||||
// AllocHeaders() allocates WXSOUND_MAX_QUEUE (= 128) blocks for an operation
|
||||
// queue. It uses AllocHeader() for each element.
|
||||
//
|
||||
// Once it has allocated all blocks, it returns TRUE and if an error occured
|
||||
// it returns FALSE.
|
||||
// -------------------------------------------------------------------------
|
||||
bool wxSoundStreamWin::AllocHeaders(int mode)
|
||||
{
|
||||
int i;
|
||||
wxSoundInfoHeader **headers;
|
||||
|
||||
if (mode == wxSOUND_OUTPUT)
|
||||
headers = m_headers_play = new wxSoundInfoHeader *[WXSOUND_MAX_QUEUE];
|
||||
else
|
||||
headers = m_headers_rec = new wxSoundInfoHeader *[WXSOUND_MAX_QUEUE];
|
||||
|
||||
memset(headers, 0, WXSOUND_MAX_QUEUE*sizeof(wxSoundInfoHeader *));
|
||||
|
||||
for (i=0;i<WXSOUND_MAX_QUEUE;i++) {
|
||||
headers[i] = AllocHeader(mode);
|
||||
if (!headers[i]) {
|
||||
FreeHeaders(mode);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// FreeHeader(int mode)
|
||||
//
|
||||
// "mode" has the same mean as for OpenDevice() except that the two flags must
|
||||
// be exclusive.
|
||||
// FreeHeader() frees a memory block and "unprepares" it.
|
||||
// -------------------------------------------------------------------------
|
||||
void wxSoundStreamWin::FreeHeader(wxSoundInfoHeader *header, int mode)
|
||||
{
|
||||
if (mode == wxSOUND_OUTPUT)
|
||||
waveOutUnprepareHeader(m_internal->m_devout, header->m_header, sizeof(WAVEHDR));
|
||||
else
|
||||
waveInUnprepareHeader(m_internal->m_devin, header->m_header, sizeof(WAVEHDR));
|
||||
|
||||
GlobalUnlock(header->m_data);
|
||||
GlobalUnlock(header->m_header);
|
||||
GlobalFree(header->m_h_header);
|
||||
GlobalFree(header->m_h_data);
|
||||
delete header;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// FreeHeaders(int mode)
|
||||
//
|
||||
// "mode" has the same mean as for OpenDevice() except that the two flags must
|
||||
// be exclusive.
|
||||
// FreeHeaders() frees all an operation queue once it has checked that
|
||||
// all buffers have been terminated.
|
||||
// -------------------------------------------------------------------------
|
||||
void wxSoundStreamWin::FreeHeaders(int mode)
|
||||
{
|
||||
int i;
|
||||
wxSoundInfoHeader ***headers;
|
||||
|
||||
if (mode == wxSOUND_OUTPUT)
|
||||
headers = &m_headers_play;
|
||||
else
|
||||
headers = &m_headers_rec;
|
||||
|
||||
for (i=0;i<WXSOUND_MAX_QUEUE;i++) {
|
||||
if ((*headers)[i]) {
|
||||
// We wait for the end of the buffer
|
||||
WaitFor((*headers)[i]);
|
||||
// Then, we free the header
|
||||
FreeHeader((*headers)[i], mode);
|
||||
}
|
||||
}
|
||||
delete[] (*headers);
|
||||
(*headers) = NULL;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// WaitFor(wxSoundInfoHeader *info)
|
||||
//
|
||||
// "info" is one element of an IO queue
|
||||
// WaitFor() checks whether the specified block has been terminated.
|
||||
// If it hasn't been terminated, it waits for its termination.
|
||||
//
|
||||
// NB: if it's a partially filled buffer it adds it to the Windows queue
|
||||
// -------------------------------------------------------------------------
|
||||
void wxSoundStreamWin::WaitFor(wxSoundInfoHeader *info)
|
||||
{
|
||||
// If the buffer is finished, we return immediately
|
||||
if (!info->m_playing) {
|
||||
|
||||
// We begun filling it: we must send it to the Windows queue
|
||||
if (info->m_position != 0) {
|
||||
memset(info->m_data + info->m_position, 0, info->m_size);
|
||||
AddToQueue(info);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_waiting_for) {
|
||||
// PROBLEM //
|
||||
return;
|
||||
}
|
||||
m_waiting_for = TRUE;
|
||||
// Else, we wait for its termination
|
||||
while (info->m_playing || info->m_recording)
|
||||
wxYield();
|
||||
m_waiting_for = FALSE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// AddToQueue(wxSoundInfoHeader *info)
|
||||
//
|
||||
// For "info", see WaitFor()
|
||||
// AddToQueue() sends the IO queue element to the Windows queue.
|
||||
//
|
||||
// Warning: in the current implementation, it partially assume we send the
|
||||
// element in the right order. This is true in that implementation but if
|
||||
// you use it elsewhere, be careful: it may shuffle all your sound datas.
|
||||
// -------------------------------------------------------------------------
|
||||
bool wxSoundStreamWin::AddToQueue(wxSoundInfoHeader *info)
|
||||
{
|
||||
MMRESULT result;
|
||||
|
||||
if (info->m_mode == wxSOUND_INPUT) {
|
||||
// Increment the input fragment pointer
|
||||
result = waveInAddBuffer(m_internal->m_devin,
|
||||
info->m_header, sizeof(WAVEHDR));
|
||||
if (result == MMSYSERR_NOERROR)
|
||||
info->m_recording = TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
} else if (info->m_mode == wxSOUND_OUTPUT) {
|
||||
result = waveOutWrite(m_internal->m_devout,
|
||||
info->m_header, sizeof(WAVEHDR));
|
||||
if (result == MMSYSERR_NOERROR)
|
||||
info->m_playing = TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// ClearHeader(wxSoundInfoHeader *info)
|
||||
//
|
||||
// ClearHeader() reinitializes the parameters of "info" to their default
|
||||
// value.
|
||||
// -------------------------------------------------------------------------
|
||||
void wxSoundStreamWin::ClearHeader(wxSoundInfoHeader *info)
|
||||
{
|
||||
info->m_playing = FALSE;
|
||||
info->m_recording = FALSE;
|
||||
info->m_position = 0;
|
||||
info->m_size = GetBestSize();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// wxSoundInfoHeader *NextFragmentOutput()
|
||||
//
|
||||
// NextFragmentOutput() looks for a free output block. It will always
|
||||
// return you a non-NULL pointer but it may waits for an empty buffer a long
|
||||
// time.
|
||||
// -------------------------------------------------------------------------
|
||||
wxSoundInfoHeader *wxSoundStreamWin::NextFragmentOutput()
|
||||
{
|
||||
if (m_headers_play[m_current_frag_out]->m_playing) {
|
||||
m_current_frag_out = (m_current_frag_out + 1) % WXSOUND_MAX_QUEUE;
|
||||
|
||||
if (m_headers_play[m_current_frag_out]->m_playing)
|
||||
WaitFor(m_headers_play[m_current_frag_out]);
|
||||
}
|
||||
if (m_current_frag_out == m_output_frag_out)
|
||||
m_queue_filled = TRUE;
|
||||
return m_headers_play[m_current_frag_out];
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// The behaviour of Write is documented in the global documentation.
|
||||
// -------------------------------------------------------------------------
|
||||
wxSoundStream& wxSoundStreamWin::Write(const void *buffer, wxUint32 len)
|
||||
{
|
||||
m_lastcount = 0;
|
||||
if (!m_internal->m_output_enabled) {
|
||||
m_snderror = wxSOUND_NOTSTARTED;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
while (len > 0) {
|
||||
wxSoundInfoHeader *header;
|
||||
wxUint32 to_copy;
|
||||
|
||||
// Get a new output fragment
|
||||
header = NextFragmentOutput();
|
||||
|
||||
to_copy = (len > header->m_size) ? header->m_size : len;
|
||||
memcpy(header->m_data + header->m_position, buffer, to_copy);
|
||||
|
||||
header->m_position += to_copy;
|
||||
header->m_size -= to_copy;
|
||||
buffer = (((const char *)buffer) + to_copy);
|
||||
len -= to_copy;
|
||||
m_lastcount += to_copy;
|
||||
|
||||
// If the fragment is full, we send it to the Windows queue.
|
||||
if (header->m_size == 0)
|
||||
if (!AddToQueue(header)) {
|
||||
m_snderror = wxSOUND_IOERROR;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// NextFragmentInput is not functional.
|
||||
// -------------------------------------------------------------------------
|
||||
wxSoundInfoHeader *wxSoundStreamWin::NextFragmentInput()
|
||||
{
|
||||
wxSoundInfoHeader *header;
|
||||
|
||||
// Queue pointer: reader
|
||||
m_current_frag_in = (m_current_frag_in + 1) % WXSOUND_MAX_QUEUE;
|
||||
|
||||
header = m_headers_rec[m_current_frag_in];
|
||||
// If the current buffer is in recording mode, we must wait for its
|
||||
// completion.
|
||||
if (header->m_recording)
|
||||
WaitFor(header);
|
||||
|
||||
// We reached the writer position: the queue is full.
|
||||
if (m_current_frag_in == m_input_frag_in)
|
||||
m_queue_filled = TRUE;
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// The behaviour of Read is documented in the global documentation.
|
||||
// -------------------------------------------------------------------------
|
||||
wxSoundStream& wxSoundStreamWin::Read(void *buffer, wxUint32 len)
|
||||
{
|
||||
wxSoundInfoHeader *header;
|
||||
wxUint32 to_copy;
|
||||
|
||||
m_lastcount = 0;
|
||||
if (!m_internal->m_input_enabled)
|
||||
return *this;
|
||||
|
||||
while (len > 0) {
|
||||
header = NextFragmentInput();
|
||||
|
||||
to_copy = (len > header->m_size) ? header->m_size : len;
|
||||
memcpy(buffer, header->m_data + header->m_position, to_copy);
|
||||
|
||||
header->m_position += to_copy;
|
||||
header->m_size -= to_copy;
|
||||
buffer = (((char *)buffer) + to_copy);
|
||||
len -= to_copy;
|
||||
m_lastcount += to_copy;
|
||||
|
||||
if (header->m_size == 0) {
|
||||
ClearHeader(header);
|
||||
if (!AddToQueue(header)) {
|
||||
m_snderror = wxSOUND_IOERROR;
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// NotifyDoneBuffer(wxUint32 dev_handle)
|
||||
//
|
||||
// NotifyDoneBuffer() is called by wxSoundHandlerProc each time a sound
|
||||
// fragment finished. It reinitializes the parameters of the fragment and
|
||||
// sends an event to the clients.
|
||||
// -------------------------------------------------------------------------
|
||||
void wxSoundStreamWin::NotifyDoneBuffer(wxUint32 dev_handle, int flag)
|
||||
{
|
||||
wxSoundInfoHeader *info;
|
||||
|
||||
if (flag == wxSOUND_OUTPUT) {
|
||||
if (!m_internal->m_output_enabled)
|
||||
return;
|
||||
|
||||
// Queue pointer: reader
|
||||
m_output_frag_out = (m_output_frag_out + 1) % WXSOUND_MAX_QUEUE;
|
||||
info = m_headers_play[m_output_frag_out];
|
||||
// Clear header to tell the system the buffer is free now
|
||||
ClearHeader(info);
|
||||
m_queue_filled = FALSE;
|
||||
if (!m_waiting_for)
|
||||
// Try to requeue a new buffer.
|
||||
OnSoundEvent(wxSOUND_OUTPUT);
|
||||
} else {
|
||||
if (!m_internal->m_input_enabled)
|
||||
return;
|
||||
|
||||
// Recording completed
|
||||
m_headers_rec[m_input_frag_in]->m_recording = FALSE;
|
||||
// Queue pointer: writer
|
||||
m_input_frag_in = (m_input_frag_in + 1) % WXSOUND_MAX_QUEUE;
|
||||
if (!m_waiting_for)
|
||||
OnSoundEvent(wxSOUND_INPUT);
|
||||
m_queue_filled = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// SetSoundFormat()
|
||||
// -------------------------------------------------------------------------
|
||||
bool wxSoundStreamWin::SetSoundFormat(wxSoundFormatBase& base)
|
||||
{
|
||||
// TODO: detect best format
|
||||
return wxSoundStream::SetSoundFormat(base);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// StartProduction()
|
||||
// -------------------------------------------------------------------------
|
||||
bool wxSoundStreamWin::StartProduction(int evt)
|
||||
{
|
||||
if (!m_internal)
|
||||
return FALSE;
|
||||
|
||||
if ((m_internal->m_output_enabled && (evt & wxSOUND_OUTPUT)) ||
|
||||
(m_internal->m_input_enabled && (evt & wxSOUND_INPUT)))
|
||||
CloseDevice();
|
||||
|
||||
if (!OpenDevice(evt))
|
||||
return FALSE;
|
||||
|
||||
m_production_started = TRUE;
|
||||
m_queue_filled = FALSE;
|
||||
// Send a dummy event to start.
|
||||
if (evt & wxSOUND_OUTPUT)
|
||||
OnSoundEvent(wxSOUND_OUTPUT);
|
||||
|
||||
if (evt & wxSOUND_INPUT) {
|
||||
int i;
|
||||
for (i=0;i<WXSOUND_MAX_QUEUE;i++)
|
||||
AddToQueue(m_headers_rec[i]);
|
||||
|
||||
waveInStart(m_internal->m_devin);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// StopProduction()
|
||||
// ------------------------------------------------------------------------
|
||||
bool wxSoundStreamWin::StopProduction()
|
||||
{
|
||||
if (!m_production_started) {
|
||||
m_snderror = wxSOUND_NOTSTARTED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
m_snderror = wxSOUND_NOERROR;
|
||||
m_production_started = FALSE;
|
||||
CloseDevice();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// QueueFilled()
|
||||
// -------------------------------------------------------------------------
|
||||
bool wxSoundStreamWin::QueueFilled() const
|
||||
{
|
||||
return (!m_production_started || m_queue_filled);
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// wxSoundWinModule
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
class WXDLLEXPORT wxSoundWinModule : public wxModule {
|
||||
DECLARE_DYNAMIC_CLASS(wxSoundWinModule)
|
||||
public:
|
||||
bool OnInit();
|
||||
void OnExit();
|
||||
};
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxSoundWinModule, wxModule)
|
||||
|
||||
bool wxSoundWinModule::OnInit() {
|
||||
wxSoundHandleList = new wxList(wxKEY_INTEGER);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wxSoundWinModule::OnExit() {
|
||||
delete wxSoundHandleList;
|
||||
}
|
@@ -1,64 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: sndwin.h
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#ifndef _WX_SNDWIN_H
|
||||
#define _WX_SNDWIN_H
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
#include "sndbase.h"
|
||||
|
||||
typedef struct _wxSoundInternal wxSoundInternal;
|
||||
typedef struct _wxSoundInfoHeader wxSoundInfoHeader;
|
||||
|
||||
class WXDLLEXPORT wxSoundStreamWin : public wxSoundStream {
|
||||
public:
|
||||
wxSoundStreamWin();
|
||||
~wxSoundStreamWin();
|
||||
|
||||
wxSoundStream& Write(const void *buffer, wxUint32 len);
|
||||
wxSoundStream& Read(void *buffer, wxUint32 len);
|
||||
|
||||
bool SetSoundFormat(wxSoundFormatBase& base);
|
||||
|
||||
bool StartProduction(int evt);
|
||||
bool StopProduction();
|
||||
|
||||
bool QueueFilled() const;
|
||||
|
||||
// Internal but defined as public
|
||||
void NotifyDoneBuffer(wxUint32 dev_handle, int flag);
|
||||
|
||||
wxUint32 GetBestSize() const { return 4096; }
|
||||
|
||||
protected:
|
||||
wxSoundInternal *m_internal;
|
||||
wxUint32 m_current_frag_in, m_current_frag_out;
|
||||
wxUint32 m_input_frag_in, m_output_frag_out;
|
||||
wxSoundInfoHeader **m_headers_play, **m_headers_rec;
|
||||
|
||||
bool m_production_started, m_queue_filled, m_waiting_for;
|
||||
|
||||
protected:
|
||||
void CreateSndWindow();
|
||||
void DestroySndWindow();
|
||||
bool OpenDevice(int mode);
|
||||
void CloseDevice();
|
||||
|
||||
wxSoundInfoHeader *AllocHeader(int mode);
|
||||
void FreeHeader(wxSoundInfoHeader *header, int mode);
|
||||
bool AllocHeaders(int mode);
|
||||
void FreeHeaders(int mode);
|
||||
|
||||
void WaitFor(wxSoundInfoHeader *info);
|
||||
bool AddToQueue(wxSoundInfoHeader *info);
|
||||
void ClearHeader(wxSoundInfoHeader *info);
|
||||
|
||||
wxSoundInfoHeader *NextFragmentOutput();
|
||||
wxSoundInfoHeader *NextFragmentInput();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,74 +0,0 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Name: vidbdrv.cpp
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1998
|
||||
// Copyright: (C) 1997, 1998, Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "vidbase.h"
|
||||
#endif
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/stream.h>
|
||||
#include <wx/wfstream.h>
|
||||
#endif
|
||||
|
||||
#include "vidbase.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
IMPLEMENT_ABSTRACT_CLASS(wxVideoBaseDriver, wxObject)
|
||||
|
||||
///
|
||||
wxVideoBaseDriver::wxVideoBaseDriver()
|
||||
{
|
||||
m_video_output = NULL;
|
||||
}
|
||||
|
||||
wxVideoBaseDriver::wxVideoBaseDriver(wxInputStream& str)
|
||||
{
|
||||
m_video_output = NULL;
|
||||
}
|
||||
|
||||
wxVideoBaseDriver::wxVideoBaseDriver(const wxString& filename)
|
||||
{
|
||||
m_video_output = NULL;
|
||||
}
|
||||
|
||||
wxVideoBaseDriver::~wxVideoBaseDriver()
|
||||
{
|
||||
}
|
||||
|
||||
bool wxVideoBaseDriver::AttachOutput(wxWindow& output)
|
||||
{
|
||||
m_video_output = &output;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wxVideoBaseDriver::DetachOutput()
|
||||
{
|
||||
m_video_output = NULL;
|
||||
}
|
||||
|
||||
// Use an external frame for video output
|
||||
|
||||
wxFrame *wxVideoCreateFrame(wxVideoBaseDriver *vid_drv)
|
||||
{
|
||||
wxFrame *frame = new wxFrame(NULL, -1, "Video Output", wxDefaultPosition, wxSize(100, 100));
|
||||
wxWindow *vid_out = new wxWindow(frame, -1, wxPoint(0, 0), wxSize(300, 300));
|
||||
|
||||
frame->Layout();
|
||||
frame->Show(TRUE);
|
||||
|
||||
vid_drv->AttachOutput(*vid_out);
|
||||
vid_drv->Play();
|
||||
|
||||
return frame;
|
||||
}
|
@@ -1,110 +0,0 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// Name: vidbase.h
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1998
|
||||
// Copyright: (C) 1997, 1998, Guilhem Lavaux
|
||||
// CVS: $Id$
|
||||
// License: wxWindows license
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
/* Real -*- C++ -*- */
|
||||
#ifndef __VID_bdrv_H__
|
||||
#define __VID_bdrv_H__
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "vidbase.h"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
// for all others, include the necessary headers (this file is usually all you
|
||||
// need because it includes almost all "standard" wxWindows headers
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/defs.h"
|
||||
#include "wx/stream.h"
|
||||
#include "wx/string.h"
|
||||
#include "wx/window.h"
|
||||
#include "wx/frame.h"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxMMedia2 (video) types
|
||||
|
||||
typedef enum {
|
||||
wxVIDEO_MSAVI,
|
||||
wxVIDEO_MPEG,
|
||||
wxVIDEO_QT,
|
||||
wxVIDEO_GIF,
|
||||
wxVIDEO_JMOV,
|
||||
wxVIDEO_FLI,
|
||||
wxVIDEO_IFF,
|
||||
wxVIDEO_SGI,
|
||||
wxVIDEO_MPEG2
|
||||
} wxVideoType;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Classes definition
|
||||
|
||||
class WXDLLEXPORT wxVideoBaseDriver : public wxObject {
|
||||
DECLARE_ABSTRACT_CLASS(wxVideoBaseDriver)
|
||||
protected:
|
||||
wxWindow *m_video_output;
|
||||
public:
|
||||
// Ctors
|
||||
wxVideoBaseDriver();
|
||||
wxVideoBaseDriver(wxInputStream& str);
|
||||
wxVideoBaseDriver(const wxString& filename);
|
||||
// Dtor
|
||||
virtual ~wxVideoBaseDriver();
|
||||
|
||||
// Usual functions ... They all return FALSE in case of errors.
|
||||
virtual bool Play() = 0;
|
||||
virtual bool Stop() = 0;
|
||||
virtual bool Pause() = 0;
|
||||
virtual bool Resume() = 0;
|
||||
|
||||
// Size management
|
||||
virtual bool SetSize(wxSize size) = 0;
|
||||
virtual bool GetSize(wxSize& size) const = 0;
|
||||
|
||||
// Test the capability of the driver to handle the specified type
|
||||
virtual bool IsCapable(wxVideoType WXUNUSED(v_type)) const { return FALSE; }
|
||||
|
||||
// Return the video codec name
|
||||
virtual wxString GetMovieCodec() const = 0;
|
||||
// Return the audio codec name
|
||||
virtual wxString GetAudioCodec() const = 0;
|
||||
// Return misc info about audio
|
||||
virtual wxUint32 GetSampleRate() const = 0;
|
||||
virtual wxUint8 GetChannels() const = 0;
|
||||
virtual wxUint8 GetBPS() const = 0;
|
||||
// Return frame rate
|
||||
virtual double GetFrameRate() const = 0;
|
||||
// Return number of frames
|
||||
virtual wxUint32 GetNbFrames() const = 0;
|
||||
|
||||
// Called when the movie finished
|
||||
virtual void OnFinished() {}
|
||||
|
||||
// Attaches the video output to a window. The video will be shown in that window.
|
||||
virtual bool AttachOutput(wxWindow& output);
|
||||
virtual void DetachOutput();
|
||||
|
||||
// They return the state of the movie.
|
||||
virtual bool IsPaused() const = 0;
|
||||
virtual bool IsStopped() const = 0;
|
||||
};
|
||||
|
||||
WXDLLEXPORT wxFrame *wxVideoCreateFrame(wxVideoBaseDriver *vid_drv);
|
||||
|
||||
|
||||
#endif
|
@@ -1,242 +0,0 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// Name: vidwin.h
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: February 1998
|
||||
// Updated:
|
||||
// Copyright: (C) 1998, 1999, 2000 Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "vidwin.h"
|
||||
#endif
|
||||
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
#include "wx/stream.h"
|
||||
#include "wx/wfstream.h"
|
||||
|
||||
#define WXMMEDIA_INTERNAL
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#include <digitalv.h>
|
||||
#include "vidwin.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxVideoWindows, wxVideoBaseDriver)
|
||||
|
||||
wxVideoWindows::wxVideoWindows()
|
||||
{
|
||||
}
|
||||
|
||||
wxVideoWindows::wxVideoWindows(wxInputStream& str)
|
||||
: wxVideoBaseDriver(str)
|
||||
{
|
||||
m_internal = new wxVIDWinternal;
|
||||
m_remove_file = TRUE;
|
||||
m_filename = wxGetTempFileName("wxvid");
|
||||
m_paused = FALSE;
|
||||
m_stopped = TRUE;
|
||||
m_frameRate = 1.0;
|
||||
|
||||
wxFileOutputStream temp_file(m_filename);
|
||||
temp_file << str;
|
||||
|
||||
OpenFile();
|
||||
}
|
||||
|
||||
wxVideoWindows::wxVideoWindows(const wxString& filename)
|
||||
: wxVideoBaseDriver(filename)
|
||||
{
|
||||
m_internal = new wxVIDWinternal;
|
||||
m_remove_file = FALSE;
|
||||
m_filename = filename;
|
||||
m_paused = FALSE;
|
||||
m_stopped = TRUE;
|
||||
m_frameRate = 1.0;
|
||||
OpenFile();
|
||||
}
|
||||
|
||||
wxVideoWindows::~wxVideoWindows(void)
|
||||
{
|
||||
mciSendCommand(m_internal->m_dev_id, MCI_CLOSE, 0, 0);
|
||||
|
||||
if (m_internal)
|
||||
delete m_internal;
|
||||
}
|
||||
|
||||
void wxVideoWindows::OpenFile()
|
||||
{
|
||||
MCI_DGV_OPEN_PARMS openStruct;
|
||||
MCI_DGV_SET_PARMS setStruct;
|
||||
MCI_STATUS_PARMS statusStruct;
|
||||
DWORD ret;
|
||||
|
||||
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)&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, MCI_WAIT, 0) == 0);
|
||||
}
|
||||
|
||||
bool wxVideoWindows::Resume()
|
||||
{
|
||||
if (!m_paused || m_stopped)
|
||||
return TRUE;
|
||||
m_paused = FALSE;
|
||||
return (mciSendCommand(m_internal->m_dev_id, MCI_RESUME, 0, 0) == 0);
|
||||
}
|
||||
|
||||
bool wxVideoWindows::IsPaused() const
|
||||
{
|
||||
return m_paused;
|
||||
}
|
||||
|
||||
bool wxVideoWindows::IsStopped() const
|
||||
{
|
||||
return m_stopped;
|
||||
}
|
||||
|
||||
bool wxVideoWindows::GetSize(wxSize& size) const
|
||||
{
|
||||
size.SetWidth(200);
|
||||
size.SetHeight(200);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxVideoWindows::SetSize(wxSize size)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxVideoWindows::IsCapable(wxVideoType v_type)
|
||||
{
|
||||
return (v_type == wxVIDEO_MSAVI);
|
||||
}
|
||||
|
||||
bool wxVideoWindows::AttachOutput(wxWindow& output)
|
||||
{
|
||||
MCI_DGV_WINDOW_PARMS win_struct;
|
||||
|
||||
if (!wxVideoBaseDriver::AttachOutput(output))
|
||||
return FALSE;
|
||||
|
||||
win_struct.hWnd = (HWND)output.GetHWND();
|
||||
mciSendCommand(m_internal->m_dev_id, MCI_WINDOW,
|
||||
MCI_DGV_WINDOW_HWND, (DWORD)(LPVOID)&win_struct);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wxVideoWindows::DetachOutput()
|
||||
{
|
||||
MCI_DGV_WINDOW_PARMS win_struct;
|
||||
|
||||
wxVideoBaseDriver::DetachOutput();
|
||||
|
||||
win_struct.hWnd = 0;
|
||||
mciSendCommand(m_internal->m_dev_id, MCI_WINDOW,
|
||||
MCI_DGV_WINDOW_HWND, (DWORD)(LPVOID)&win_struct);
|
||||
}
|
||||
|
||||
bool wxVideoWindows::Play()
|
||||
{
|
||||
if (!m_stopped)
|
||||
return FALSE;
|
||||
m_stopped = FALSE;
|
||||
return (mciSendCommand(m_internal->m_dev_id, MCI_PLAY, 0, NULL) == 0);
|
||||
}
|
||||
|
||||
bool wxVideoWindows::Stop()
|
||||
{
|
||||
MCI_SEEK_PARMS seekStruct;
|
||||
|
||||
if (m_stopped)
|
||||
return FALSE;
|
||||
m_stopped = TRUE;
|
||||
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, 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
|
||||
{
|
||||
return wxT("No info");
|
||||
}
|
||||
|
||||
wxString wxVideoWindows::GetAudioCodec() const
|
||||
{
|
||||
return wxT("No info");
|
||||
}
|
||||
|
||||
wxUint32 wxVideoWindows::GetSampleRate() const
|
||||
{
|
||||
return 22500;
|
||||
}
|
||||
|
||||
wxUint8 wxVideoWindows::GetChannels() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
wxUint8 wxVideoWindows::GetBPS() const
|
||||
{
|
||||
return m_bps;
|
||||
}
|
||||
|
||||
double wxVideoWindows::GetFrameRate() const
|
||||
{
|
||||
return m_frameRate;
|
||||
}
|
||||
|
||||
wxUint32 wxVideoWindows::GetNbFrames() const
|
||||
{
|
||||
return 0;
|
||||
}
|
@@ -1,101 +0,0 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Name: vidwin.h
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: February 1998
|
||||
// Updated:
|
||||
// Copyright: (C) 1998, Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __VID_windows_H__
|
||||
#define __VID_windows_H__
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "vidwin.h"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
// for all others, include the necessary headers (this file is usually all you
|
||||
// need because it includes almost all "standard" wxWindows headers
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/string.h"
|
||||
#include "wx/stream.h"
|
||||
#include "wx/window.h"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxMMedia2 headers
|
||||
|
||||
#include "vidbase.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// System headers and private types
|
||||
|
||||
#ifdef WXMMEDIA_INTERNAL
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
typedef struct VIDW_Internal {
|
||||
MCIDEVICEID m_dev_id;
|
||||
} wxVIDWinternal;
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Class definition
|
||||
|
||||
class WXDLLEXPORT wxVideoWindows : public wxVideoBaseDriver {
|
||||
DECLARE_DYNAMIC_CLASS(wxVideoWindows)
|
||||
protected:
|
||||
struct VIDW_Internal *m_internal;
|
||||
bool m_paused, m_stopped, m_remove_file;
|
||||
wxString m_filename;
|
||||
double m_frameRate;
|
||||
wxUint8 m_bps;
|
||||
|
||||
void OpenFile();
|
||||
public:
|
||||
wxVideoWindows(void);
|
||||
wxVideoWindows(wxInputStream& str);
|
||||
wxVideoWindows(const wxString& fname);
|
||||
~wxVideoWindows(void);
|
||||
|
||||
bool Play();
|
||||
bool Stop();
|
||||
bool Pause();
|
||||
bool Resume();
|
||||
|
||||
bool GetSize(wxSize& size) const;
|
||||
bool SetSize(wxSize size);
|
||||
|
||||
// Return codec name for each stream.
|
||||
wxString GetMovieCodec() const;
|
||||
wxString GetAudioCodec() const;
|
||||
// Return misc. info about audio
|
||||
wxUint32 GetSampleRate() const;
|
||||
wxUint8 GetChannels() const;
|
||||
wxUint8 GetBPS() const;
|
||||
// Return the frame rate of the video (in frames/second)
|
||||
double GetFrameRate() const;
|
||||
// Return the total number of frames in the movie
|
||||
wxUint32 GetNbFrames() const;
|
||||
|
||||
bool IsCapable(wxVideoType v_type);
|
||||
|
||||
bool AttachOutput(wxWindow& output);
|
||||
void DetachOutput(void);
|
||||
|
||||
bool IsPaused() const;
|
||||
bool IsStopped() const;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,510 +0,0 @@
|
||||
// -------------------------------------------------------------------------
|
||||
// Name: vidxanm.cpp
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1998
|
||||
// Copyright: (C) 1997, 1998, 1999 Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "vidxanm.h"
|
||||
#endif
|
||||
|
||||
#include <wx/wxprec.h>
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include <wx/wx.h>
|
||||
#endif
|
||||
|
||||
// Pizza !
|
||||
#include <wx/gtk/win_gtk.h>
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#ifdef __WXGTK__
|
||||
#include <gtk/gtkwidget.h>
|
||||
#include <gtk/gtkwindow.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkprivate.h>
|
||||
#endif
|
||||
|
||||
#include <wx/filefn.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/datstrm.h>
|
||||
#include <wx/tokenzr.h>
|
||||
|
||||
#define WXMMEDIA_INTERNAL
|
||||
#include "vidbase.h"
|
||||
#include "vidxanm.h"
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxVideoXANIM, wxVideoBaseDriver)
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// End process detector
|
||||
|
||||
class wxVideoXANIMProcess: public wxProcess {
|
||||
public:
|
||||
wxVideoXANIMProcess(wxVideoXANIM *xanim);
|
||||
|
||||
void OnTerminate(int pid, int status);
|
||||
|
||||
protected:
|
||||
wxVideoXANIM *m_vid_xanim;
|
||||
};
|
||||
|
||||
class wxVideoXANIMOutput: public wxProcess {
|
||||
public:
|
||||
wxVideoXANIMOutput();
|
||||
|
||||
void OnTerminate(int pid, int status);
|
||||
|
||||
bool IsTerminated() const;
|
||||
protected:
|
||||
bool m_terminated;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XAnim video driver (process handling implementation)
|
||||
|
||||
wxVideoXANIMProcess::wxVideoXANIMProcess(wxVideoXANIM *xanim)
|
||||
{
|
||||
m_vid_xanim = xanim;
|
||||
}
|
||||
|
||||
void wxVideoXANIMProcess::OnTerminate(int WXUNUSED(pid), int WXUNUSED(status))
|
||||
{
|
||||
m_vid_xanim->m_xanim_started = FALSE;
|
||||
m_vid_xanim->OnFinished();
|
||||
}
|
||||
|
||||
wxVideoXANIMOutput::wxVideoXANIMOutput()
|
||||
: wxProcess(NULL, TRUE, -1)
|
||||
{
|
||||
m_terminated = FALSE;
|
||||
}
|
||||
|
||||
bool wxVideoXANIMOutput::IsTerminated() const
|
||||
{
|
||||
return m_terminated;
|
||||
}
|
||||
|
||||
void wxVideoXANIMOutput::OnTerminate(int pid, int status)
|
||||
{
|
||||
m_terminated = TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XAnim video driver (implementation)
|
||||
|
||||
wxVideoXANIM::wxVideoXANIM()
|
||||
: wxVideoBaseDriver()
|
||||
{
|
||||
m_internal = new wxXANIMinternal;
|
||||
m_xanim_detector = new wxVideoXANIMProcess(this);
|
||||
m_xanim_started = FALSE;
|
||||
m_paused = FALSE;
|
||||
m_filename = "";
|
||||
m_remove_file = FALSE;
|
||||
}
|
||||
|
||||
wxVideoXANIM::wxVideoXANIM(wxInputStream& str)
|
||||
: wxVideoBaseDriver(str)
|
||||
{
|
||||
m_internal = new wxXANIMinternal;
|
||||
m_xanim_detector = new wxVideoXANIMProcess(this);
|
||||
m_xanim_started = FALSE;
|
||||
m_paused = FALSE;
|
||||
m_size[0] = 0;
|
||||
m_size[1] = 0;
|
||||
|
||||
m_filename = wxGetTempFileName("vidxa");
|
||||
m_remove_file = TRUE;
|
||||
wxFileOutputStream fout(m_filename);
|
||||
|
||||
fout << str;
|
||||
|
||||
CollectInfo();
|
||||
}
|
||||
|
||||
wxVideoXANIM::wxVideoXANIM(const wxString& filename)
|
||||
{
|
||||
m_internal = new wxXANIMinternal;
|
||||
m_xanim_detector = new wxVideoXANIMProcess(this);
|
||||
m_xanim_started = FALSE;
|
||||
m_paused = FALSE;
|
||||
|
||||
m_filename = filename;
|
||||
m_remove_file = FALSE;
|
||||
m_size[0] = 0;
|
||||
m_size[1] = 0;
|
||||
|
||||
CollectInfo();
|
||||
}
|
||||
|
||||
wxVideoXANIM::~wxVideoXANIM()
|
||||
{
|
||||
if (m_xanim_started)
|
||||
Stop();
|
||||
delete m_internal;
|
||||
delete m_xanim_detector;
|
||||
|
||||
if (m_remove_file)
|
||||
wxRemoveFile(m_filename);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Movie controller
|
||||
|
||||
bool wxVideoXANIM::Play()
|
||||
{
|
||||
if (!m_paused && m_xanim_started)
|
||||
return TRUE;
|
||||
if (!m_video_output) {
|
||||
wxVideoCreateFrame(this);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// The movie starts with xanim
|
||||
if (RestartXANIM()) {
|
||||
m_paused = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool wxVideoXANIM::Pause()
|
||||
{
|
||||
if (!m_paused && SendCommand(" ")) {
|
||||
m_paused = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool wxVideoXANIM::Resume()
|
||||
{
|
||||
if (m_paused && SendCommand(" ")) {
|
||||
m_paused = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool wxVideoXANIM::Stop()
|
||||
{
|
||||
if (!m_xanim_started)
|
||||
return FALSE;
|
||||
|
||||
SendCommand("q");
|
||||
|
||||
// We are waiting for the termination of the subprocess.
|
||||
while (m_xanim_started) {
|
||||
wxYield();
|
||||
}
|
||||
|
||||
m_paused = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Movie size controller
|
||||
|
||||
bool wxVideoXANIM::SetSize(wxSize size)
|
||||
{
|
||||
if (!m_video_output)
|
||||
return FALSE;
|
||||
|
||||
m_video_output->SetSize(size.GetWidth(), size.GetHeight());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool wxVideoXANIM::GetSize(wxSize& size) const
|
||||
{
|
||||
if (m_size[0] == 0)
|
||||
return FALSE;
|
||||
size.Set(m_size[0], m_size[1]);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Capabilities of XAnim
|
||||
|
||||
bool wxVideoXANIM::IsCapable(wxVideoType v_type) const
|
||||
{
|
||||
if (v_type == wxVIDEO_MSAVI || v_type == wxVIDEO_MPEG ||
|
||||
v_type == wxVIDEO_QT || v_type == wxVIDEO_GIF || v_type == wxVIDEO_JMOV ||
|
||||
v_type == wxVIDEO_FLI || v_type == wxVIDEO_IFF || v_type == wxVIDEO_SGI)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Movie state
|
||||
|
||||
wxString wxVideoXANIM::GetMovieCodec() const
|
||||
{
|
||||
if (m_size[0] == 0)
|
||||
return wxT("");
|
||||
return m_movieCodec;
|
||||
}
|
||||
|
||||
wxString wxVideoXANIM::GetAudioCodec() const
|
||||
{
|
||||
if (m_size[0] == 0)
|
||||
return wxT("");
|
||||
return m_audioCodec;
|
||||
}
|
||||
|
||||
wxUint32 wxVideoXANIM::GetSampleRate() const
|
||||
{
|
||||
if (m_size[0] == 0)
|
||||
return 0;
|
||||
return m_sampleRate;
|
||||
}
|
||||
|
||||
wxUint8 wxVideoXANIM::GetChannels() const
|
||||
{
|
||||
if (m_size[0] == 0)
|
||||
return 0;
|
||||
return m_channels;
|
||||
}
|
||||
|
||||
wxUint8 wxVideoXANIM::GetBPS() const
|
||||
{
|
||||
if (m_size[0] == 0)
|
||||
return 0;
|
||||
return m_bps;
|
||||
}
|
||||
|
||||
double wxVideoXANIM::GetFrameRate() const
|
||||
{
|
||||
if (m_size[0] == 0)
|
||||
return 0.0;
|
||||
return m_frameRate;
|
||||
}
|
||||
|
||||
wxUint32 wxVideoXANIM::GetNbFrames() const
|
||||
{
|
||||
if (m_size[0] == 0)
|
||||
return 0;
|
||||
return m_frames;
|
||||
}
|
||||
|
||||
|
||||
bool wxVideoXANIM::IsPaused() const
|
||||
{
|
||||
return m_paused;
|
||||
}
|
||||
|
||||
bool wxVideoXANIM::IsStopped() const
|
||||
{
|
||||
return !m_xanim_started;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Output management
|
||||
|
||||
bool wxVideoXANIM::AttachOutput(wxWindow& out)
|
||||
{
|
||||
if (!wxVideoBaseDriver::AttachOutput(out))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void wxVideoXANIM::DetachOutput()
|
||||
{
|
||||
SendCommand("q");
|
||||
m_xanim_started = FALSE;
|
||||
m_paused = FALSE;
|
||||
|
||||
wxVideoBaseDriver::DetachOutput();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Lowlevel XAnim controller
|
||||
|
||||
bool wxVideoXANIM::SendCommand(const char *command, char **ret,
|
||||
wxUint32 *size)
|
||||
{
|
||||
if (!m_xanim_started)
|
||||
if (!RestartXANIM())
|
||||
return FALSE;
|
||||
|
||||
// Send a command to XAnim through X11 Property
|
||||
XChangeProperty(m_internal->xanim_dpy, m_internal->xanim_window,
|
||||
m_internal->xanim_atom,
|
||||
XA_STRING, 8, PropModeReplace, (unsigned char *)command,
|
||||
strlen(command));
|
||||
XFlush(m_internal->xanim_dpy);
|
||||
if (ret) {
|
||||
int prop_format;
|
||||
Atom prop_type;
|
||||
unsigned long extra;
|
||||
|
||||
XGetWindowProperty(m_internal->xanim_dpy, m_internal->xanim_window,
|
||||
m_internal->xanim_ret, 0, 16, True, AnyPropertyType,
|
||||
&prop_type, &prop_format, (unsigned long *)size,
|
||||
&extra, (unsigned char **)ret);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxVideoXANIM::CollectInfo()
|
||||
{
|
||||
wxVideoXANIMOutput *xanimProcess;
|
||||
wxString xanim_command;
|
||||
wxStringTokenizer tokenizer;
|
||||
|
||||
xanimProcess = new wxVideoXANIMOutput;
|
||||
xanim_command = wxT("xanim +v +Zv -Ae ");
|
||||
xanim_command += m_filename;
|
||||
if (!wxExecute(xanim_command, FALSE, xanimProcess))
|
||||
return FALSE;
|
||||
|
||||
wxInputStream *infoStream = xanimProcess->GetInputStream();
|
||||
wxString totalOutput;
|
||||
|
||||
while (infoStream->LastError() == wxSTREAM_NOERROR) {
|
||||
char line[100];
|
||||
|
||||
infoStream->Read(line, sizeof(line)-1);
|
||||
if (infoStream->LastRead() == 0)
|
||||
break;
|
||||
|
||||
line[infoStream->LastRead()] = 0;
|
||||
|
||||
totalOutput += line;
|
||||
}
|
||||
|
||||
// This is good for everything ... :-)
|
||||
int position = totalOutput.Find(wxT("Video Codec:"));
|
||||
|
||||
totalOutput.Remove(0, position+13);
|
||||
|
||||
position = totalOutput.Find(wxT("depth="));
|
||||
m_movieCodec = totalOutput(0, position);
|
||||
|
||||
totalOutput.Remove(0, position);
|
||||
tokenizer.SetString(totalOutput, "\n\r");
|
||||
|
||||
// the rest of the line
|
||||
wxString token = tokenizer.GetNextToken();
|
||||
unsigned long my_long;
|
||||
|
||||
#define GETINT(i) \
|
||||
totalOutput.ToULong(&my_long); \
|
||||
i = my_long;
|
||||
|
||||
// 'Audio Codec:'
|
||||
totalOutput = tokenizer.GetString();
|
||||
totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2);
|
||||
|
||||
position = totalOutput.Find(wxT("Rate"));
|
||||
m_audioCodec = totalOutput(0, position-1);
|
||||
|
||||
// 'Rate='
|
||||
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
|
||||
GETINT(m_sampleRate);
|
||||
// 'Chans='
|
||||
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
|
||||
GETINT(m_channels);
|
||||
// 'Bps='
|
||||
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
|
||||
GETINT(m_bps);
|
||||
// 'Frame Stats:'
|
||||
tokenizer.Reinit(totalOutput);
|
||||
tokenizer.GetNextToken();
|
||||
totalOutput = tokenizer.GetString();
|
||||
totalOutput.Remove(0, totalOutput.Find(wxT(":"))+2);
|
||||
// 'Size='
|
||||
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
|
||||
GETINT(m_size[0]);
|
||||
// 'x'
|
||||
totalOutput.Remove(0,1);
|
||||
GETINT(m_size[1]);
|
||||
// 'Frames='
|
||||
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
|
||||
GETINT(m_frames);
|
||||
// 'avfps='
|
||||
totalOutput.Remove(0, totalOutput.Find(wxT("="))+1);
|
||||
totalOutput.ToDouble(&m_frameRate);
|
||||
|
||||
// We wait for the conclusion
|
||||
while (!xanimProcess->IsTerminated())
|
||||
wxYield();
|
||||
|
||||
delete xanimProcess;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bool wxVideoXANIM::RestartXANIM()
|
||||
{
|
||||
wxString xanim_command;
|
||||
int ret;
|
||||
Atom prop_type;
|
||||
int prop_format;
|
||||
unsigned long nitems;
|
||||
unsigned long extra;
|
||||
char prop[4];
|
||||
bool xanim_chg_size;
|
||||
|
||||
if (!m_video_output || m_xanim_started)
|
||||
return FALSE;
|
||||
|
||||
// Check if we can change the size of the window dynamicly
|
||||
xanim_chg_size = TRUE;
|
||||
// Get current display
|
||||
#ifdef __WXGTK__
|
||||
m_internal->xanim_dpy = gdk_display;
|
||||
GtkPizza *pizza = GTK_PIZZA( m_video_output->m_wxwindow );
|
||||
GdkWindow *window = pizza->bin_window;
|
||||
|
||||
m_internal->xanim_window =
|
||||
((GdkWindowPrivate *)window)->xwindow;
|
||||
#endif
|
||||
// Get the XANIM atom
|
||||
m_internal->xanim_atom = XInternAtom(m_internal->xanim_dpy,
|
||||
"XANIM_PROPERTY", False);
|
||||
|
||||
// Build the command
|
||||
xanim_command.Printf(wxT("xanim -Zr +Ze +Sr +f +W%d +f +q "
|
||||
"+Av70 %s %s"), m_internal->xanim_window,
|
||||
(xanim_chg_size) ? _T("") : _T(""),
|
||||
WXSTRINGCAST m_filename);
|
||||
|
||||
// Execute it
|
||||
if (!wxExecute(xanim_command, FALSE, m_xanim_detector))
|
||||
return FALSE;
|
||||
|
||||
// Wait for XAnim to be ready
|
||||
nitems = 0;
|
||||
m_xanim_started = TRUE;
|
||||
while (nitems == 0 && m_xanim_started) {
|
||||
ret = XGetWindowProperty(m_internal->xanim_dpy, m_internal->xanim_window,
|
||||
m_internal->xanim_atom,
|
||||
0, 4, False, AnyPropertyType, &prop_type,
|
||||
&prop_format, &nitems, &extra,
|
||||
(unsigned char **)&prop);
|
||||
wxYield();
|
||||
}
|
||||
|
||||
wxSize vibrato_size;
|
||||
|
||||
vibrato_size = m_video_output->GetSize();
|
||||
|
||||
vibrato_size.SetWidth(vibrato_size.GetWidth()+1);
|
||||
m_video_output->SetSize(vibrato_size);
|
||||
vibrato_size.SetWidth(vibrato_size.GetWidth()-1);
|
||||
m_video_output->SetSize(vibrato_size);
|
||||
// Very useful ! Actually it sends a SETSIZE event to XAnim
|
||||
|
||||
m_paused = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
@@ -1,136 +0,0 @@
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
// Name: vidxanm.h
|
||||
// Purpose: wxMMedia
|
||||
// Author: Guilhem Lavaux
|
||||
// Created: 1997
|
||||
// Updated: 1998
|
||||
// Copyright: (C) 1997, 1998, Guilhem Lavaux
|
||||
// License: wxWindows license
|
||||
// /////////////////////////////////////////////////////////////////////////////
|
||||
/* Real -*- C++ -*- */
|
||||
#ifndef __VID_xanim_H__
|
||||
#define __VID_xanim_H__
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "vidxanm.h"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
// for all others, include the necessary headers (this file is usually all you
|
||||
// need because it includes almost all "standard" wxWindows headers
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/defs.h"
|
||||
#include "wx/string.h"
|
||||
#include "wx/process.h"
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// System dependent headers
|
||||
|
||||
#if defined(WXMMEDIA_INTERNAL) && (defined(__X__) || defined(__WXGTK__))
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxMMedia2 headers
|
||||
|
||||
#include "vidbase.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Internal types
|
||||
|
||||
#ifdef WXMMEDIA_INTERNAL
|
||||
typedef struct wxXANIMinternal {
|
||||
Display *xanim_dpy;
|
||||
Window xanim_window;
|
||||
Atom xanim_atom, xanim_ret;
|
||||
} wxXANIMinternal;
|
||||
|
||||
#ifndef __XANIM_COMMAND__
|
||||
#define __XANIM_COMMAND__ "/usr/X11R6/bin/xanim"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Class definition
|
||||
|
||||
class WXDLLEXPORT wxVideoXANIM : public wxVideoBaseDriver {
|
||||
DECLARE_DYNAMIC_CLASS(wxVideoXANIM)
|
||||
protected:
|
||||
// Remember the state of the subprocess
|
||||
bool m_xanim_started, m_paused;
|
||||
// Pure X11 variables
|
||||
struct wxXANIMinternal *m_internal;
|
||||
wxString m_filename;
|
||||
wxProcess *m_xanim_detector;
|
||||
// Remember to delete the temporary file when necessary
|
||||
bool m_remove_file;
|
||||
wxUint32 m_size[2];
|
||||
wxUint32 m_sampleRate;
|
||||
wxUint8 m_channels;
|
||||
wxUint8 m_bps;
|
||||
wxUint32 m_frames;
|
||||
double m_frameRate;
|
||||
wxString m_movieCodec, m_audioCodec;
|
||||
|
||||
public:
|
||||
wxVideoXANIM();
|
||||
wxVideoXANIM(wxInputStream& str);
|
||||
wxVideoXANIM(const wxString& filename);
|
||||
~wxVideoXANIM();
|
||||
|
||||
bool Play();
|
||||
bool Pause();
|
||||
bool Resume();
|
||||
bool Stop();
|
||||
|
||||
bool SetVolume(wxUint8 vol);
|
||||
bool SetSize(wxSize size);
|
||||
bool GetSize(wxSize& size) const;
|
||||
|
||||
// Return the video codec name
|
||||
wxString GetMovieCodec() const;
|
||||
// Return the audio codec name
|
||||
wxString GetAudioCodec() const;
|
||||
// Return misc info about audio
|
||||
wxUint32 GetSampleRate() const;
|
||||
wxUint8 GetChannels() const;
|
||||
wxUint8 GetBPS() const;
|
||||
// Return frame rate
|
||||
double GetFrameRate() const;
|
||||
// Return number of frames in the movie
|
||||
wxUint32 GetNbFrames() const;
|
||||
|
||||
bool IsCapable(wxVideoType v_type) const;
|
||||
|
||||
bool AttachOutput(wxWindow& output);
|
||||
void DetachOutput();
|
||||
|
||||
bool IsPaused() const;
|
||||
bool IsStopped() const;
|
||||
|
||||
friend class wxVideoXANIMProcess;
|
||||
|
||||
protected:
|
||||
// Start the subprocess with the right parameters
|
||||
bool RestartXANIM();
|
||||
// Send a command to the subprocess
|
||||
bool SendCommand(const char *command,char **ret = NULL,
|
||||
wxUint32 *size = NULL);
|
||||
|
||||
// Collect informations from XAnim
|
||||
bool CollectInfo();
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,85 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: process.cpp
|
||||
// Purpose: Process termination classes
|
||||
// Author: Guilhem Lavaux
|
||||
// Modified by: Vadim Zeitlin to check error codes, added Detach() method
|
||||
// Created: 24/06/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Guilhem Lavaux
|
||||
// Licence: wxWindows license
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation "process.h"
|
||||
#endif
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/defs.h"
|
||||
#endif
|
||||
|
||||
#include "wx/process.h"
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxProcess, wxEvtHandler)
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxProcessEvent, wxEvent)
|
||||
|
||||
wxProcess::wxProcess(wxEvtHandler *parent, bool needPipe, int id)
|
||||
{
|
||||
if (parent)
|
||||
SetNextHandler(parent);
|
||||
|
||||
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)
|
||||
{
|
||||
wxProcessEvent event(m_id, pid, status);
|
||||
|
||||
if ( !ProcessEvent(event) )
|
||||
delete this;
|
||||
//else: the object which processed the event is responsible for deleting
|
||||
// us!
|
||||
}
|
||||
|
||||
void wxProcess::Detach()
|
||||
{
|
||||
SetNextHandler(NULL);
|
||||
}
|
||||
|
||||
void wxProcess::SetPipeStreams(wxInputStream *in_stream, wxOutputStream *out_stream)
|
||||
{
|
||||
m_in_stream = in_stream;
|
||||
m_out_stream = out_stream;
|
||||
}
|
||||
|
||||
wxInputStream *wxProcess::GetInputStream() const
|
||||
{
|
||||
return m_in_stream;
|
||||
}
|
||||
|
||||
wxOutputStream *wxProcess::GetOutputStream() const
|
||||
{
|
||||
return m_out_stream;
|
||||
}
|
||||
|
||||
bool wxProcess::NeedPipe() const
|
||||
{
|
||||
return m_needPipe;
|
||||
}
|
@@ -1,86 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: process.h
|
||||
// Purpose: wxProcess class
|
||||
// Author: Guilhem Lavaux
|
||||
// Modified by: Vadim Zeitlin to check error codes, added Detach() method
|
||||
// Created: 24/06/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) 1998 Guilhem Lavaux
|
||||
// Licence: wxWindows license
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_PROCESSH__
|
||||
#define _WX_PROCESSH__
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma interface "process.h"
|
||||
#endif
|
||||
|
||||
#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(wxProcessEvent)
|
||||
|
||||
public:
|
||||
wxProcessEvent(int id = 0, int pid = 0, int exitcode = 0) : wxEvent(id)
|
||||
{
|
||||
m_eventType = wxEVT_END_PROCESS;
|
||||
m_pid = pid;
|
||||
m_exitcode = exitcode;
|
||||
}
|
||||
|
||||
// accessors
|
||||
// PID of process which terminated
|
||||
int GetPid() { return m_pid; }
|
||||
|
||||
// the exit code
|
||||
int GetExitCode() { return m_exitcode; }
|
||||
|
||||
public:
|
||||
int m_pid, m_exitcode;
|
||||
};
|
||||
|
||||
// A wxProcess object should be passed to wxExecute - than its OnTerminate()
|
||||
// function will be called when the process terminates.
|
||||
class WXDLLEXPORT wxProcess : public wxEvtHandler
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS(wxProcess)
|
||||
|
||||
public:
|
||||
wxProcess(wxEvtHandler *parent = (wxEvtHandler *) NULL, bool needPipe = FALSE, int id = -1);
|
||||
~wxProcess();
|
||||
|
||||
virtual void OnTerminate(int pid, int status);
|
||||
|
||||
// detach from the parent - should be called by the parent if it's deleted
|
||||
// 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&);
|
||||
|
||||
#define EVT_END_PROCESS(id, func) { wxEVT_END_PROCESS, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxProcessEventFunction) & func, NULL},
|
||||
|
||||
#endif
|
||||
// _WX_PROCESSH__
|
@@ -1,51 +0,0 @@
|
||||
#
|
||||
# File: Makefile.in
|
||||
# Author: Julian Smart
|
||||
# Created: 1998
|
||||
# Updated:
|
||||
# Copyright: (c) 1998 Julian Smart
|
||||
#
|
||||
# "%W% %G%"
|
||||
#
|
||||
# Makefile for wxsocket example (UNIX).
|
||||
|
||||
top_srcdir = @top_srcdir@/..
|
||||
top_builddir = ../../..
|
||||
program_dir = utils/wxMMedia2/sample
|
||||
# the comment at the end of the next line is needed because otherwise autoconf
|
||||
# would remove this line completely - it contains a built-in hack to remove
|
||||
# any VPATH assignment not containing ':'
|
||||
VPATH = @PATH_IFS@$(top_srcdir)/utils/wxMMedia2/sample # ':' for autoconf
|
||||
|
||||
# Clears all default suffixes
|
||||
.SUFFIXES: .o .cpp .c .cxx
|
||||
|
||||
.cpp.o :
|
||||
$(CC) -c $(CPPFLAGS) -o $@ $<
|
||||
|
||||
# Set defaults from configure
|
||||
include ../../../src/make.env
|
||||
|
||||
LDLIBS2 = $(LDLIBS) ../lib/libwxmmedia2.a
|
||||
|
||||
all: test_med test_med3 test_med5 test_med2 test_med4
|
||||
|
||||
test_med: test_med.o ../../../lib/@WX_TARGET_LIBRARY@
|
||||
$(CC) $(LDFLAGS) -o test_med test_med.o $(LDLIBS2)
|
||||
|
||||
test_med2: test_med2.o ../../../lib/@WX_TARGET_LIBRARY@
|
||||
$(CC) $(LDFLAGS) -o test_med2 test_med2.o $(LDLIBS2)
|
||||
|
||||
test_med3: test_med3.o ../../../lib/@WX_TARGET_LIBRARY@
|
||||
$(CC) $(LDFLAGS) -o test_med3 test_med3.o $(LDLIBS2)
|
||||
|
||||
test_med4: test_med4.o ../../../lib/@WX_TARGET_LIBRARY@
|
||||
$(CC) $(LDFLAGS) -o test_med4 test_med4.o $(LDLIBS2)
|
||||
|
||||
test_med5: test_med5.o ../../../lib/@WX_TARGET_LIBRARY@
|
||||
$(CC) $(LDFLAGS) -o test_med5 test_med5.o $(LDLIBS2)
|
||||
|
||||
|
||||
clean:
|
||||
rm -f test_med* core
|
||||
|
@@ -1,17 +0,0 @@
|
||||
#
|
||||
# File: makefile.g95
|
||||
# Author: Julian Smart
|
||||
# Created: 1999
|
||||
# Updated:
|
||||
# Copyright: (c) Julian Smart, 1999
|
||||
#
|
||||
# Makefile for wxWindows sample (Cygwin/Mingw32).
|
||||
|
||||
WXDIR = ../../..
|
||||
|
||||
TARGET=test_med4
|
||||
OBJECTS = $(TARGET).o
|
||||
EXTRALIBS= ../lib/libwxmmedia2 -lwx -lwinmm
|
||||
|
||||
include $(WXDIR)\src\makeprog.g95
|
||||
|
@@ -1,66 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: test_med.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#include <wx/app.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/frame.h>
|
||||
#include "../lib/sndoss.h"
|
||||
#include "../lib/sndwav.h"
|
||||
#include "../lib/sndaiff.h"
|
||||
#include "../lib/sndulaw.h"
|
||||
|
||||
wxSoundStreamOSS *oss_dev;
|
||||
wxInputStream *f_input;
|
||||
wxSoundStreamUlaw *ulaw_codec;
|
||||
|
||||
class MySoundStream: public wxSoundStream {
|
||||
public:
|
||||
wxSoundStream& Read(void *buffer, size_t len) { return *this; }
|
||||
wxSoundStream& Write(const void *buffer, size_t len) { return *this; }
|
||||
|
||||
bool StartProduction(int evt) { return FALSE; }
|
||||
bool StopProduction() { return FALSE; }
|
||||
|
||||
void SetDuplexMode(bool on) {}
|
||||
|
||||
void OnSoundEvent(int evt) {
|
||||
char buffer[2048];
|
||||
|
||||
f_input->Read(buffer, sizeof(buffer));
|
||||
ulaw_codec->Write(buffer, sizeof(buffer));
|
||||
}
|
||||
};
|
||||
|
||||
class MyApp: public wxApp {
|
||||
bool OnInit() {
|
||||
wxSoundFormatUlaw ulaw;
|
||||
MySoundStream strm;
|
||||
|
||||
oss_dev = new wxSoundStreamOSS();
|
||||
f_input = new wxFileInputStream(argv[1]);
|
||||
|
||||
if (oss_dev->GetError() != wxSOUND_NOERR) {
|
||||
wxPrintf("No device\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
ulaw.SetSampleRate(8000);
|
||||
ulaw_codec = new wxSoundStreamUlaw(*oss_dev);
|
||||
ulaw_codec->SetSoundFormat(ulaw);
|
||||
|
||||
oss_dev->SetEventHandler(&strm);
|
||||
oss_dev->StartProduction(wxSOUND_OUTPUT);
|
||||
|
||||
while (1) {
|
||||
// wxYield();
|
||||
strm.OnSoundEvent(0);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_APP(MyApp)
|
@@ -1,43 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: test_med.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#include <wx/app.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/frame.h>
|
||||
#include "../lib/sndoss.h"
|
||||
#include "../lib/sndesd.h"
|
||||
#include "../lib/sndwav.h"
|
||||
#include "../lib/sndaiff.h"
|
||||
|
||||
class MyApp: public wxApp {
|
||||
bool OnInit() {
|
||||
// wxSoundStreamOSS *oss_dev = new wxSoundStreamOSS();
|
||||
wxSoundStreamESD *oss_dev = new wxSoundStreamESD();
|
||||
wxFileInputStream *f_input = new wxFileInputStream(argv[1]);
|
||||
wxSoundFileStream *wav_file;
|
||||
wxFrame *frame = new wxFrame(NULL, -1, "My Frame");
|
||||
wxSoundFormatPcm pcm;
|
||||
|
||||
if (oss_dev->GetError() != wxSOUND_NOERR) {
|
||||
wxPrintf("No device\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wav_file = new wxSoundWave(*f_input, *oss_dev);
|
||||
if (!wav_file->CanRead()) {
|
||||
wav_file = new wxSoundAiff(*f_input, *oss_dev);
|
||||
if (!wav_file->CanRead())
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wav_file->Play();
|
||||
frame->Show(TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_APP(MyApp)
|
@@ -1,23 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: test_med.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#include <wx/app.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/frame.h>
|
||||
#include "../lib/vidxanm.h"
|
||||
|
||||
class MyApp: public wxApp {
|
||||
bool OnInit() {
|
||||
wxFileInputStream *file = new wxFileInputStream(argv[1]);
|
||||
wxVideoXANIM *vidxanm = new wxVideoXANIM(*file);
|
||||
|
||||
vidxanm->Play();
|
||||
return TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_APP(MyApp)
|
@@ -1,54 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: test_med.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#include <wx/wxprec.h>
|
||||
#include <wx/app.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/frame.h>
|
||||
#include "../lib/sndoss.h"
|
||||
#include "../lib/sndwav.h"
|
||||
#include "../lib/sndaiff.h"
|
||||
#include "../lib/sndwin.h"
|
||||
|
||||
class MyApp: public wxApp {
|
||||
wxSoundStream *oss_dev;
|
||||
wxOutputStream *f_output;
|
||||
wxSoundFileStream *wav_file;
|
||||
|
||||
bool OnInit() {
|
||||
wxFrame *frame = new wxFrame(NULL, -1, "My Frame");
|
||||
wxSoundFormatPcm pcm;
|
||||
|
||||
oss_dev = new wxSoundStreamWin();
|
||||
f_output = new wxFileOutputStream(argv[1]);
|
||||
wav_file = new wxSoundWave(*f_output, *oss_dev);
|
||||
|
||||
if (oss_dev->GetError() != wxSOUND_NOERR) {
|
||||
wxPrintf("No device\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pcm.SetSampleRate(22050);
|
||||
pcm.SetBPS(8);
|
||||
pcm.SetChannels(1);
|
||||
|
||||
wav_file->SetSoundFormat(pcm);
|
||||
|
||||
// Record 10 sec of sound
|
||||
wav_file->Record(10);
|
||||
frame->Show(TRUE);
|
||||
return TRUE;
|
||||
}
|
||||
int OnExit() {
|
||||
delete wav_file;
|
||||
delete f_output;
|
||||
delete oss_dev;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_APP(MyApp)
|
@@ -1,22 +0,0 @@
|
||||
// --------------------------------------------------------------------------
|
||||
// Name: test_med.cpp
|
||||
// Purpose:
|
||||
// Date: 08/11/1999
|
||||
// Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999
|
||||
// CVSID: $Id$
|
||||
// --------------------------------------------------------------------------
|
||||
#include <wx/app.h>
|
||||
#include <wx/wfstream.h>
|
||||
#include <wx/frame.h>
|
||||
#include "../lib/cdunix.h"
|
||||
|
||||
class MyApp: public wxApp {
|
||||
bool OnInit() {
|
||||
wxCDAudioLinux m_cd;
|
||||
|
||||
m_cd.Play(m_cd.GetToc().GetTrackTime(0),m_cd.GetToc().GetTrackTime(1));
|
||||
return TRUE;
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_APP(MyApp)
|
@@ -1,672 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: msw/utilsexec.cpp
|
||||
// Purpose: Various utilities
|
||||
// Author: Julian Smart
|
||||
// Modified by:
|
||||
// Created: 04/01/98
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) Julian Smart and Markus Holzem
|
||||
// Licence: wxWindows license
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
// For compilers that support precompilation, includes "wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/utils.h"
|
||||
#include "wx/app.h"
|
||||
#include "wx/intl.h"
|
||||
#endif
|
||||
|
||||
#include "wx/log.h"
|
||||
|
||||
#ifdef __WIN32__
|
||||
#include "wx/stream.h"
|
||||
#include "wx/process.h"
|
||||
#endif
|
||||
|
||||
#include "wx/msw/private.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#if !defined(__GNUWIN32__) && !defined(__WXWINE__) && !defined(__SALFORDC__)
|
||||
#include <direct.h>
|
||||
#ifndef __MWERKS__
|
||||
#include <dos.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__GNUWIN32__) && !defined(__TWIN32__)
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#if defined(__WIN32__) && !defined(__WXWINE__)
|
||||
#include <io.h>
|
||||
|
||||
#ifndef __GNUWIN32__
|
||||
#include <shellapi.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef __WATCOMC__
|
||||
#if !(defined(_MSC_VER) && (_MSC_VER > 800))
|
||||
#include <errno.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <stdarg.h>
|
||||
|
||||
#if wxUSE_IPC
|
||||
#include "wx/dde.h" // for WX_DDE hack in wxExecute
|
||||
#endif // wxUSE_IPC
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// constants
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// this message is sent when the process we're waiting for terminates
|
||||
#define wxWM_PROC_TERMINATED (WM_USER + 10000)
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// this module globals
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// we need to create a hidden window to receive the process termination
|
||||
// notifications and for this we need a (Win) class name for it which we will
|
||||
// register the first time it's needed
|
||||
static const wxChar *gs_classForHiddenWindow = NULL;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// private types
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// structure describing the process we're being waiting for
|
||||
struct wxExecuteData
|
||||
{
|
||||
public:
|
||||
~wxExecuteData()
|
||||
{
|
||||
#ifndef __WIN16__
|
||||
if ( !::CloseHandle(hProcess) )
|
||||
{
|
||||
wxLogLastError("CloseHandle(hProcess)");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
HWND hWnd; // window to send wxWM_PROC_TERMINATED to
|
||||
HANDLE hProcess; // handle of the process
|
||||
DWORD dwProcessId; // pid of the process
|
||||
wxProcess *handler;
|
||||
DWORD dwExitCode; // the exit code of the process
|
||||
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
|
||||
// ============================================================================
|
||||
|
||||
#ifdef __WIN32__
|
||||
static DWORD wxExecuteThread(wxExecuteData *data)
|
||||
{
|
||||
WaitForSingleObject(data->hProcess, INFINITE);
|
||||
|
||||
// get the exit code
|
||||
if ( !GetExitCodeProcess(data->hProcess, &data->dwExitCode) )
|
||||
{
|
||||
wxLogLastError("GetExitCodeProcess");
|
||||
}
|
||||
|
||||
wxASSERT_MSG( data->dwExitCode != STILL_ACTIVE,
|
||||
wxT("process should have terminated") );
|
||||
|
||||
// send a message indicating process termination to the window
|
||||
SendMessage(data->hWnd, wxWM_PROC_TERMINATED, 0, (LPARAM)data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// window procedure of a hidden window which is created just to receive
|
||||
// the notification message when a process exits
|
||||
LRESULT APIENTRY _EXPORT wxExecuteWindowCbk(HWND hWnd, UINT message,
|
||||
WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if ( message == wxWM_PROC_TERMINATED )
|
||||
{
|
||||
DestroyWindow(hWnd); // we don't need it any more
|
||||
|
||||
wxExecuteData *data = (wxExecuteData *)lParam;
|
||||
if ( data->handler )
|
||||
{
|
||||
data->handler->OnTerminate((int)data->dwProcessId,
|
||||
(int)data->dwExitCode);
|
||||
}
|
||||
|
||||
if ( data->state )
|
||||
{
|
||||
// we're executing synchronously, tell the waiting thread
|
||||
// that the process finished
|
||||
data->state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// asynchronous execution - we should do the clean up
|
||||
delete data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
}
|
||||
#endif // Win32
|
||||
|
||||
long wxExecute(const wxString& cmd, bool sync, wxProcess *handler)
|
||||
{
|
||||
wxCHECK_MSG( !!cmd, 0, wxT("empty command in wxExecute") );
|
||||
|
||||
wxString command;
|
||||
#if wxUSE_IPC
|
||||
// DDE hack: this is really not pretty, but we need to allow this for
|
||||
// transparent handling of DDE servers in wxMimeTypesManager. Usually it
|
||||
// returns the command which should be run to view/open/... a file of the
|
||||
// given type. Sometimes, however, this command just launches the server
|
||||
// and an additional DDE request must be made to really open the file. To
|
||||
// keep all this well hidden from the application, we allow a special form
|
||||
// of command: WX_DDE:<command>:DDE_SERVER:DDE_TOPIC:DDE_COMMAND in which
|
||||
// case we execute just <command> and process the rest below
|
||||
wxString ddeServer, ddeTopic, ddeCommand;
|
||||
static const size_t lenDdePrefix = 7; // strlen("WX_DDE:")
|
||||
if ( cmd.Left(lenDdePrefix) == _T("WX_DDE#") )
|
||||
{
|
||||
const wxChar *p = cmd.c_str() + 7;
|
||||
while ( *p && *p != _T('#') )
|
||||
{
|
||||
command += *p++;
|
||||
}
|
||||
|
||||
if ( *p )
|
||||
{
|
||||
// skip '#'
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
|
||||
}
|
||||
|
||||
while ( *p && *p != _T('#') )
|
||||
{
|
||||
ddeServer += *p++;
|
||||
}
|
||||
|
||||
if ( *p )
|
||||
{
|
||||
// skip '#'
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
|
||||
}
|
||||
|
||||
while ( *p && *p != _T('#') )
|
||||
{
|
||||
ddeTopic += *p++;
|
||||
}
|
||||
|
||||
if ( *p )
|
||||
{
|
||||
// skip '#'
|
||||
p++;
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFAIL_MSG(_T("invalid WX_DDE command in wxExecute"));
|
||||
}
|
||||
|
||||
while ( *p )
|
||||
{
|
||||
ddeCommand += *p++;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // wxUSE_IPC
|
||||
{
|
||||
// no DDE
|
||||
command = cmd;
|
||||
}
|
||||
|
||||
#if defined(__WIN32__) && !defined(__TWIN32__)
|
||||
// the old code is disabled because we really need a process handle
|
||||
// if we want to execute it asynchronously or even just get its
|
||||
// return code and for this we must use CreateProcess() and not
|
||||
// ShellExecute()
|
||||
#if 0
|
||||
// isolate command and arguments
|
||||
wxString commandName;
|
||||
bool insideQuotes = FALSE;
|
||||
const char *pc;
|
||||
for ( pc = command.c_str(); *pc != '\0'; pc++ )
|
||||
{
|
||||
switch ( *pc )
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
if ( !insideQuotes )
|
||||
break;
|
||||
// fall through
|
||||
|
||||
case '"':
|
||||
insideQuotes = !insideQuotes;
|
||||
// fall through
|
||||
|
||||
default:
|
||||
commandName += *pc;
|
||||
continue; // skip the next break
|
||||
}
|
||||
|
||||
// only reached for space not inside quotes
|
||||
break;
|
||||
}
|
||||
wxString commandArgs = pc;
|
||||
|
||||
wxWindow *winTop = wxTheApp->GetTopWindow();
|
||||
HWND hwndTop = (HWND)(winTop ? winTop->GetHWND() : 0);
|
||||
|
||||
HANDLE result;
|
||||
#ifdef __GNUWIN32__
|
||||
result = ShellExecute(hwndTop,
|
||||
(const wchar_t)"open",
|
||||
(const wchar_t)commandName,
|
||||
(const wchar_t)commandArgs,
|
||||
(const wchar_t)NULL,
|
||||
SW_SHOWNORMAL);
|
||||
#else // !GNUWIN32
|
||||
result = ShellExecute(hwndTop, "open", commandName,
|
||||
commandArgs, NULL, SW_SHOWNORMAL);
|
||||
#endif // GNUWIN32
|
||||
|
||||
if ( ((long)result) <= 32 )
|
||||
wxLogSysError(_("Can't execute command '%s'"), command.c_str());
|
||||
|
||||
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;
|
||||
wxZeroMemory(si);
|
||||
|
||||
si.cb = sizeof(si);
|
||||
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
if ( ::CreateProcess(
|
||||
NULL, // application name (use only cmd line)
|
||||
(wxChar *)command.c_str(), // full command line
|
||||
NULL, // security attributes: defaults for both
|
||||
NULL, // the process and its main thread
|
||||
inheritHandles, // don't inherit handles
|
||||
CREATE_DEFAULT_ERROR_MODE |
|
||||
CREATE_SUSPENDED, // flags
|
||||
NULL, // environment (use the same)
|
||||
NULL, // current directory (use the same)
|
||||
&si, // startup info (unused here)
|
||||
&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 )
|
||||
{
|
||||
gs_classForHiddenWindow = _T("wxHiddenWindow");
|
||||
|
||||
WNDCLASS wndclass;
|
||||
wxZeroMemory(wndclass);
|
||||
wndclass.lpfnWndProc = (WNDPROC)wxExecuteWindowCbk;
|
||||
wndclass.hInstance = wxGetInstance();
|
||||
wndclass.lpszClassName = gs_classForHiddenWindow;
|
||||
|
||||
if ( !::RegisterClass(&wndclass) )
|
||||
{
|
||||
wxLogLastError("RegisterClass(hidden window)");
|
||||
}
|
||||
}
|
||||
|
||||
// create a hidden window to receive notification about process
|
||||
// termination
|
||||
HWND hwnd = ::CreateWindow(gs_classForHiddenWindow, NULL,
|
||||
WS_OVERLAPPEDWINDOW,
|
||||
0, 0, 0, 0, NULL,
|
||||
(HMENU)NULL, wxGetInstance(), 0);
|
||||
wxASSERT_MSG( hwnd, wxT("can't create a hidden window for wxExecute") );
|
||||
|
||||
// Alloc data
|
||||
wxExecuteData *data = new wxExecuteData;
|
||||
data->hProcess = pi.hProcess;
|
||||
data->dwProcessId = pi.dwProcessId;
|
||||
data->hWnd = hwnd;
|
||||
data->state = sync;
|
||||
if ( sync )
|
||||
{
|
||||
wxASSERT_MSG( !handler, wxT("wxProcess param ignored for sync execution") );
|
||||
|
||||
data->handler = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
// may be NULL or not
|
||||
data->handler = handler;
|
||||
}
|
||||
|
||||
DWORD tid;
|
||||
HANDLE hThread = ::CreateThread(NULL,
|
||||
0,
|
||||
(LPTHREAD_START_ROUTINE)wxExecuteThread,
|
||||
(void *)data,
|
||||
0,
|
||||
&tid);
|
||||
|
||||
// resume process we created now - whether the thread creation succeeded or
|
||||
// not
|
||||
if ( ::ResumeThread(pi.hThread) == (DWORD)-1 )
|
||||
{
|
||||
// ignore it - what can we do?
|
||||
wxLogLastError("ResumeThread in wxExecute");
|
||||
}
|
||||
|
||||
// close unneeded handle
|
||||
if ( !::CloseHandle(pi.hThread) )
|
||||
wxLogLastError("CloseHandle(hThread)");
|
||||
|
||||
if ( !hThread )
|
||||
{
|
||||
wxLogLastError("CreateThread in wxExecute");
|
||||
|
||||
DestroyWindow(hwnd);
|
||||
delete data;
|
||||
|
||||
// the process still started up successfully...
|
||||
return pi.dwProcessId;
|
||||
}
|
||||
|
||||
#if wxUSE_IPC
|
||||
// second part of DDE hack: now establish the DDE conversation with the
|
||||
// just launched process
|
||||
if ( !!ddeServer )
|
||||
{
|
||||
wxDDEClient client;
|
||||
wxConnectionBase *conn = client.MakeConnection(_T(""),
|
||||
ddeServer,
|
||||
ddeTopic);
|
||||
if ( !conn || !conn->Execute(ddeCommand) )
|
||||
{
|
||||
wxLogError(_("Couldn't launch DDE server '%s'."), command.c_str());
|
||||
}
|
||||
}
|
||||
#endif // wxUSE_IPC
|
||||
|
||||
if ( !sync )
|
||||
{
|
||||
// clean up will be done when the process terminates
|
||||
|
||||
// return the pid
|
||||
return pi.dwProcessId;
|
||||
}
|
||||
|
||||
// waiting until command executed (disable everything while doing it)
|
||||
#if wxUSE_GUI
|
||||
wxBeginBusyCursor();
|
||||
wxEnableTopLevelWindows(FALSE);
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
while ( data->state )
|
||||
wxYield();
|
||||
|
||||
#if wxUSE_GUI
|
||||
wxEnableTopLevelWindows(TRUE);
|
||||
wxEndBusyCursor();
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
DWORD dwExitCode = data->dwExitCode;
|
||||
delete data;
|
||||
|
||||
// return the exit code
|
||||
return dwExitCode;
|
||||
#endif // 0/1
|
||||
#else // Win16
|
||||
long instanceID = WinExec((LPCSTR) WXSTRINGCAST command, SW_SHOW);
|
||||
if (instanceID < 32) return(0);
|
||||
|
||||
if (sync) {
|
||||
int running;
|
||||
do {
|
||||
wxYield();
|
||||
running = GetModuleUsage((HINSTANCE)instanceID);
|
||||
} while (running);
|
||||
}
|
||||
|
||||
return(instanceID);
|
||||
#endif // Win16/32
|
||||
}
|
||||
|
||||
long wxExecute(char **argv, bool sync, wxProcess *handler)
|
||||
{
|
||||
wxString command;
|
||||
|
||||
while ( *argv != NULL )
|
||||
{
|
||||
command << *argv++ << ' ';
|
||||
}
|
||||
|
||||
command.RemoveLast();
|
||||
|
||||
return wxExecute(command, sync, handler);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Metafile helpers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern void PixelToHIMETRIC(LONG *x, LONG *y)
|
||||
{
|
||||
ScreenHDC hdcRef;
|
||||
|
||||
int iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE),
|
||||
iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE),
|
||||
iWidthPels = GetDeviceCaps(hdcRef, HORZRES),
|
||||
iHeightPels = GetDeviceCaps(hdcRef, VERTRES);
|
||||
|
||||
*x *= (iWidthMM * 100);
|
||||
*x /= iWidthPels;
|
||||
*y *= (iHeightMM * 100);
|
||||
*y /= iHeightPels;
|
||||
}
|
||||
|
||||
extern void HIMETRICToPixel(LONG *x, LONG *y)
|
||||
{
|
||||
ScreenHDC hdcRef;
|
||||
|
||||
int iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE),
|
||||
iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE),
|
||||
iWidthPels = GetDeviceCaps(hdcRef, HORZRES),
|
||||
iHeightPels = GetDeviceCaps(hdcRef, VERTRES);
|
||||
|
||||
*x *= iWidthPels;
|
||||
*x /= (iWidthMM * 100);
|
||||
*y *= iHeightPels;
|
||||
*y /= (iHeightMM * 100);
|
||||
}
|
@@ -1,771 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: utilsunx.cpp
|
||||
// Purpose: generic Unix implementation of many wx functions
|
||||
// Author: Vadim Zeitlin
|
||||
// Id: $Id$
|
||||
// Copyright: (c) 1998 Robert Roebling, Vadim Zeitlin
|
||||
// Licence: wxWindows licence
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ============================================================================
|
||||
// declarations
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// headers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
#include "wx/defs.h"
|
||||
#include "wx/string.h"
|
||||
|
||||
#include "wx/intl.h"
|
||||
#include "wx/log.h"
|
||||
|
||||
#include "wx/utils.h"
|
||||
#include "wx/process.h"
|
||||
#include "wx/thread.h"
|
||||
|
||||
#include "wx/stream.h"
|
||||
|
||||
#if wxUSE_GUI
|
||||
#include "wx/unix/execute.h"
|
||||
#endif
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h> // for O_WRONLY and friends
|
||||
#include <time.h> // nanosleep() and/or usleep()
|
||||
#include <ctype.h> // isspace()
|
||||
#include <sys/time.h> // needed for FD_SETSIZE
|
||||
|
||||
#ifdef HAVE_UNAME
|
||||
#include <sys/utsname.h> // for uname()
|
||||
#endif // HAVE_UNAME
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// conditional compilation
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// many versions of Unices have this function, but it is not defined in system
|
||||
// headers - please add your system here if it is the case for your OS.
|
||||
// SunOS < 5.6 (i.e. Solaris < 2.6) and DG-UX are like this.
|
||||
#if !defined(HAVE_USLEEP) && \
|
||||
(defined(__SUN__) && !defined(__SunOs_5_6) && \
|
||||
!defined(__SunOs_5_7) && !defined(__SUNPRO_CC)) || \
|
||||
defined(__osf__) || defined(__EMX__)
|
||||
extern "C"
|
||||
{
|
||||
#ifdef __SUN__
|
||||
int usleep(unsigned int usec);
|
||||
#else // !Sun
|
||||
#ifdef __EMX__
|
||||
/* I copied this from the XFree86 diffs. AV. */
|
||||
#define INCL_DOSPROCESS
|
||||
#include <os2.h>
|
||||
inline void usleep(unsigned long delay)
|
||||
{
|
||||
DosSleep(delay ? (delay/1000l) : 1l);
|
||||
}
|
||||
#else // !Sun && !EMX
|
||||
void usleep(unsigned long usec);
|
||||
#endif
|
||||
#endif // Sun/EMX/Something else
|
||||
};
|
||||
|
||||
#define HAVE_USLEEP 1
|
||||
#endif // Unices without usleep()
|
||||
|
||||
// ============================================================================
|
||||
// implementation
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// sleeping
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxSleep(int nSecs)
|
||||
{
|
||||
sleep(nSecs);
|
||||
}
|
||||
|
||||
void wxUsleep(unsigned long milliseconds)
|
||||
{
|
||||
#if defined(HAVE_NANOSLEEP)
|
||||
timespec tmReq;
|
||||
tmReq.tv_sec = (time_t)(milliseconds / 1000);
|
||||
tmReq.tv_nsec = (milliseconds % 1000) * 1000 * 1000;
|
||||
|
||||
// we're not interested in remaining time nor in return value
|
||||
(void)nanosleep(&tmReq, (timespec *)NULL);
|
||||
#elif defined(HAVE_USLEEP)
|
||||
// uncomment this if you feel brave or if you are sure that your version
|
||||
// of Solaris has a safe usleep() function but please notice that usleep()
|
||||
// is known to lead to crashes in MT programs in Solaris 2.[67] and is not
|
||||
// documented as MT-Safe
|
||||
#if defined(__SUN__) && wxUSE_THREADS
|
||||
#error "usleep() cannot be used in MT programs under Solaris."
|
||||
#endif // Sun
|
||||
|
||||
usleep(milliseconds * 1000); // usleep(3) wants microseconds
|
||||
#elif defined(HAVE_SLEEP)
|
||||
// under BeOS sleep() takes seconds (what about other platforms, if any?)
|
||||
sleep(milliseconds * 1000);
|
||||
#else // !sleep function
|
||||
#error "usleep() or nanosleep() function required for wxUsleep"
|
||||
#endif // sleep function
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// process management
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
int wxKill(long pid, wxSignal sig)
|
||||
{
|
||||
return kill((pid_t)pid, (int)sig);
|
||||
}
|
||||
|
||||
#define WXEXECUTE_NARGS 127
|
||||
|
||||
long wxExecute( const wxString& command, bool sync, wxProcess *process )
|
||||
{
|
||||
wxCHECK_MSG( !command.IsEmpty(), 0, wxT("can't exec empty command") );
|
||||
|
||||
int argc = 0;
|
||||
wxChar *argv[WXEXECUTE_NARGS];
|
||||
wxString argument;
|
||||
const wxChar *cptr = command.c_str();
|
||||
wxChar quotechar = wxT('\0'); // is arg quoted?
|
||||
bool escaped = FALSE;
|
||||
|
||||
// split the command line in arguments
|
||||
do
|
||||
{
|
||||
argument=wxT("");
|
||||
quotechar = wxT('\0');
|
||||
|
||||
// eat leading whitespace:
|
||||
while ( wxIsspace(*cptr) )
|
||||
cptr++;
|
||||
|
||||
if ( *cptr == wxT('\'') || *cptr == wxT('"') )
|
||||
quotechar = *cptr++;
|
||||
|
||||
do
|
||||
{
|
||||
if ( *cptr == wxT('\\') && ! escaped )
|
||||
{
|
||||
escaped = TRUE;
|
||||
cptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// all other characters:
|
||||
argument += *cptr++;
|
||||
escaped = FALSE;
|
||||
|
||||
// have we reached the end of the argument?
|
||||
if ( (*cptr == quotechar && ! escaped)
|
||||
|| (quotechar == wxT('\0') && wxIsspace(*cptr))
|
||||
|| *cptr == wxT('\0') )
|
||||
{
|
||||
wxASSERT_MSG( argc < WXEXECUTE_NARGS,
|
||||
wxT("too many arguments in wxExecute") );
|
||||
|
||||
argv[argc] = new wxChar[argument.length() + 1];
|
||||
wxStrcpy(argv[argc], argument.c_str());
|
||||
argc++;
|
||||
|
||||
// if not at end of buffer, swallow last character:
|
||||
if(*cptr)
|
||||
cptr++;
|
||||
|
||||
break; // done with this one, start over
|
||||
}
|
||||
} while(*cptr);
|
||||
} while(*cptr);
|
||||
argv[argc] = NULL;
|
||||
|
||||
// do execute the command
|
||||
long lRc = wxExecute(argv, sync, process);
|
||||
|
||||
// clean up
|
||||
argc = 0;
|
||||
while( argv[argc] )
|
||||
delete [] argv[argc++];
|
||||
|
||||
return lRc;
|
||||
}
|
||||
|
||||
bool wxShell(const wxString& command)
|
||||
{
|
||||
wxString cmd;
|
||||
if ( !!command )
|
||||
cmd.Printf(wxT("xterm -e %s"), command.c_str());
|
||||
else
|
||||
cmd = command;
|
||||
|
||||
return wxExecute(cmd) != 0;
|
||||
}
|
||||
|
||||
#if wxUSE_GUI
|
||||
|
||||
void wxHandleProcessTermination(wxEndProcessData *proc_data)
|
||||
{
|
||||
int pid = (proc_data->pid > 0) ? proc_data->pid : -(proc_data->pid);
|
||||
|
||||
// waitpid is POSIX so should be available everywhere, however on older
|
||||
// systems wait() might be used instead in a loop (until the right pid
|
||||
// terminates)
|
||||
int status = 0;
|
||||
int rc;
|
||||
|
||||
// wait for child termination and if waitpid() was interrupted, try again
|
||||
do
|
||||
{
|
||||
rc = waitpid(pid, &status, 0);
|
||||
}
|
||||
while ( rc == -1 && errno == EINTR );
|
||||
|
||||
|
||||
if( rc == -1 || ! (WIFEXITED(status) || WIFSIGNALED(status)) )
|
||||
{
|
||||
wxLogSysError(_("Waiting for subprocess termination failed"));
|
||||
/* AFAIK, this can only happen if something went wrong within
|
||||
wxGTK, i.e. due to a race condition or some serious bug.
|
||||
After having fixed the order of statements in
|
||||
GTK_EndProcessDetector(). (KB)
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// notify user about termination if required
|
||||
if (proc_data->process)
|
||||
{
|
||||
proc_data->process->OnTerminate(proc_data->pid,
|
||||
WEXITSTATUS(status));
|
||||
}
|
||||
// clean up
|
||||
if ( proc_data->pid > 0 )
|
||||
{
|
||||
delete proc_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
// wxExecute() will know about it
|
||||
proc_data->exitcode = status;
|
||||
|
||||
proc_data->pid = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
#if wxUSE_GUI
|
||||
#define WXUNUSED_UNLESS_GUI(p) p
|
||||
#else
|
||||
#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))
|
||||
{
|
||||
wxCHECK_MSG( *argv, 0, wxT("can't exec empty command") );
|
||||
|
||||
#if wxUSE_UNICODE
|
||||
int mb_argc = 0;
|
||||
char *mb_argv[WXEXECUTE_NARGS];
|
||||
|
||||
while (argv[mb_argc])
|
||||
{
|
||||
wxWX2MBbuf mb_arg = wxConvertWX2MB(argv[mb_argc]);
|
||||
mb_argv[mb_argc] = strdup(mb_arg);
|
||||
mb_argc++;
|
||||
}
|
||||
mb_argv[mb_argc] = (char *) NULL;
|
||||
|
||||
// this macro will free memory we used above
|
||||
#define ARGS_CLEANUP \
|
||||
for ( mb_argc = 0; mb_argv[mb_argc]; mb_argc++ ) \
|
||||
free(mb_argv[mb_argc])
|
||||
#else // ANSI
|
||||
// no need for cleanup
|
||||
#define ARGS_CLEANUP
|
||||
|
||||
wxChar **mb_argv = argv;
|
||||
#endif // Unicode/ANSI
|
||||
|
||||
#if wxUSE_GUI
|
||||
// create pipes
|
||||
int end_proc_detect[2];
|
||||
if (pipe(end_proc_detect) == -1)
|
||||
{
|
||||
wxLogSysError( _("Pipe creation failed") );
|
||||
|
||||
ARGS_CLEANUP;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#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();
|
||||
#else
|
||||
pid_t pid = fork();
|
||||
#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;
|
||||
|
||||
return 0;
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
// we're in child
|
||||
close(end_proc_detect[0]); // close reading side
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
// These three lines close the open file descriptors to to avoid any
|
||||
// input/output which might block the process or irritate the user. If
|
||||
// one wants proper IO for the subprocess, the right thing to do is
|
||||
// to start an xterm executing it.
|
||||
if (sync == 0)
|
||||
{
|
||||
// leave stderr opened, it won't do any hurm
|
||||
for ( int fd = 0; fd < FD_SETSIZE; fd++ )
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
if ( fd == end_proc_detect[1] || fd == in_pipe[0] || fd == out_pipe[1] )
|
||||
continue;
|
||||
#endif // wxUSE_GUI
|
||||
|
||||
if ( fd != STDERR_FILENO )
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// some programs complain about stderr not being open, so redirect
|
||||
// them:
|
||||
open("/dev/null", O_RDONLY); // stdin
|
||||
open("/dev/null", O_WRONLY); // stdout
|
||||
open("/dev/null", O_WRONLY); // stderr
|
||||
#endif
|
||||
|
||||
execvp (*mb_argv, mb_argv);
|
||||
|
||||
// there is no return after successful exec()
|
||||
wxFprintf(stderr, _("Can't execute '%s'\n"), *argv);
|
||||
|
||||
_exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if wxUSE_GUI
|
||||
wxEndProcessData *data = new wxEndProcessData;
|
||||
|
||||
ARGS_CLEANUP;
|
||||
|
||||
if ( sync )
|
||||
{
|
||||
wxASSERT_MSG( !process, wxT("wxProcess param ignored for sync exec") );
|
||||
data->process = NULL;
|
||||
|
||||
// sync execution: indicate it by negating the pid
|
||||
data->pid = -pid;
|
||||
data->tag = wxAddProcessCallback(data, end_proc_detect[0]);
|
||||
// we're in parent
|
||||
close(end_proc_detect[1]); // close writing side
|
||||
|
||||
// it will be set to 0 from GTK_EndProcessDetector
|
||||
while (data->pid != 0)
|
||||
wxYield();
|
||||
|
||||
int exitcode = data->exitcode;
|
||||
|
||||
delete data;
|
||||
|
||||
return exitcode;
|
||||
}
|
||||
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]);
|
||||
// we're in parent
|
||||
close(end_proc_detect[1]); // close writing side
|
||||
|
||||
return pid;
|
||||
}
|
||||
#else // !wxUSE_GUI
|
||||
wxASSERT_MSG( sync, wxT("async execution not supported yet") );
|
||||
|
||||
int exitcode = 0;
|
||||
if ( waitpid(pid, &exitcode, 0) == -1 || !WIFEXITED(exitcode) )
|
||||
{
|
||||
wxLogSysError(_("Waiting for subprocess termination failed"));
|
||||
}
|
||||
|
||||
return exitcode;
|
||||
#endif // wxUSE_GUI
|
||||
}
|
||||
return 0;
|
||||
|
||||
#undef ARGS_CLEANUP
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// file and directory functions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const wxChar* wxGetHomeDir( wxString *home )
|
||||
{
|
||||
*home = wxGetUserHome( wxString() );
|
||||
if ( home->IsEmpty() )
|
||||
*home = wxT("/");
|
||||
|
||||
return home->c_str();
|
||||
}
|
||||
|
||||
#if wxUSE_UNICODE
|
||||
const wxMB2WXbuf wxGetUserHome( const wxString &user )
|
||||
#else // just for binary compatibility -- there is no 'const' here
|
||||
char *wxGetUserHome( const wxString &user )
|
||||
#endif
|
||||
{
|
||||
struct passwd *who = (struct passwd *) NULL;
|
||||
|
||||
if ( !user )
|
||||
{
|
||||
wxChar *ptr;
|
||||
|
||||
if ((ptr = wxGetenv(wxT("HOME"))) != NULL)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
if ((ptr = wxGetenv(wxT("USER"))) != NULL || (ptr = wxGetenv(wxT("LOGNAME"))) != NULL)
|
||||
{
|
||||
who = getpwnam(wxConvertWX2MB(ptr));
|
||||
}
|
||||
|
||||
// We now make sure the the user exists!
|
||||
if (who == NULL)
|
||||
{
|
||||
who = getpwuid(getuid());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
who = getpwnam (user.mb_str());
|
||||
}
|
||||
|
||||
return wxConvertMB2WX(who ? who->pw_dir : 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// network and user id routines
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// retrieve either the hostname or FQDN depending on platform (caller must
|
||||
// check whether it's one or the other, this is why this function is for
|
||||
// private use only)
|
||||
static bool wxGetHostNameInternal(wxChar *buf, int sz)
|
||||
{
|
||||
wxCHECK_MSG( buf, FALSE, wxT("NULL pointer in wxGetHostNameInternal") );
|
||||
|
||||
*buf = wxT('\0');
|
||||
|
||||
// we're using uname() which is POSIX instead of less standard sysinfo()
|
||||
#if defined(HAVE_UNAME)
|
||||
struct utsname uts;
|
||||
bool ok = uname(&uts) != -1;
|
||||
if ( ok )
|
||||
{
|
||||
wxStrncpy(buf, wxConvertMB2WX(uts.nodename), sz - 1);
|
||||
buf[sz] = wxT('\0');
|
||||
}
|
||||
#elif defined(HAVE_GETHOSTNAME)
|
||||
bool ok = gethostname(buf, sz) != -1;
|
||||
#else // no uname, no gethostname
|
||||
wxFAIL_MSG(wxT("don't know host name for this machine"));
|
||||
|
||||
bool ok = FALSE;
|
||||
#endif // uname/gethostname
|
||||
|
||||
if ( !ok )
|
||||
{
|
||||
wxLogSysError(_("Cannot get the hostname"));
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool wxGetHostName(wxChar *buf, int sz)
|
||||
{
|
||||
bool ok = wxGetHostNameInternal(buf, sz);
|
||||
|
||||
if ( ok )
|
||||
{
|
||||
// BSD systems return the FQDN, we only want the hostname, so extract
|
||||
// it (we consider that dots are domain separators)
|
||||
wxChar *dot = wxStrchr(buf, wxT('.'));
|
||||
if ( dot )
|
||||
{
|
||||
// nuke it
|
||||
*dot = wxT('\0');
|
||||
}
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool wxGetFullHostName(wxChar *buf, int sz)
|
||||
{
|
||||
bool ok = wxGetHostNameInternal(buf, sz);
|
||||
|
||||
if ( ok )
|
||||
{
|
||||
if ( !wxStrchr(buf, wxT('.')) )
|
||||
{
|
||||
struct hostent *host = gethostbyname(wxConvertWX2MB(buf));
|
||||
if ( !host )
|
||||
{
|
||||
wxLogSysError(_("Cannot get the official hostname"));
|
||||
|
||||
ok = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the canonical name
|
||||
wxStrncpy(buf, wxConvertMB2WX(host->h_name), sz);
|
||||
}
|
||||
}
|
||||
//else: it's already a FQDN (BSD behaves this way)
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool wxGetUserId(wxChar *buf, int sz)
|
||||
{
|
||||
struct passwd *who;
|
||||
|
||||
*buf = wxT('\0');
|
||||
if ((who = getpwuid(getuid ())) != NULL)
|
||||
{
|
||||
wxStrncpy (buf, wxConvertMB2WX(who->pw_name), sz - 1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool wxGetUserName(wxChar *buf, int sz)
|
||||
{
|
||||
struct passwd *who;
|
||||
|
||||
*buf = wxT('\0');
|
||||
if ((who = getpwuid (getuid ())) != NULL)
|
||||
{
|
||||
// pw_gecos field in struct passwd is not standard
|
||||
#if HAVE_PW_GECOS
|
||||
char *comma = strchr(who->pw_gecos, ',');
|
||||
if (comma)
|
||||
*comma = '\0'; // cut off non-name comment fields
|
||||
wxStrncpy (buf, wxConvertMB2WX(who->pw_gecos), sz - 1);
|
||||
#else // !HAVE_PW_GECOS
|
||||
wxStrncpy (buf, wxConvertMB2WX(who->pw_name), sz - 1);
|
||||
#endif // HAVE_PW_GECOS/!HAVE_PW_GECOS
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wxString wxGetOsDescription()
|
||||
{
|
||||
#ifndef WXWIN_OS_DESCRIPTION
|
||||
#error WXWIN_OS_DESCRIPTION should be defined in config.h by configure
|
||||
#else
|
||||
return WXWIN_OS_DESCRIPTION;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// error and debug output routines (deprecated, use wxLog)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void wxDebugMsg( const char *format, ... )
|
||||
{
|
||||
va_list ap;
|
||||
va_start( ap, format );
|
||||
vfprintf( stderr, format, ap );
|
||||
fflush( stderr );
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void wxError( const wxString &msg, const wxString &title )
|
||||
{
|
||||
wxFprintf( stderr, _("Error ") );
|
||||
if (!title.IsNull()) wxFprintf( stderr, wxT("%s "), WXSTRINGCAST(title) );
|
||||
if (!msg.IsNull()) wxFprintf( stderr, wxT(": %s"), WXSTRINGCAST(msg) );
|
||||
wxFprintf( stderr, wxT(".\n") );
|
||||
}
|
||||
|
||||
void wxFatalError( const wxString &msg, const wxString &title )
|
||||
{
|
||||
wxFprintf( stderr, _("Error ") );
|
||||
if (!title.IsNull()) wxFprintf( stderr, wxT("%s "), WXSTRINGCAST(title) );
|
||||
if (!msg.IsNull()) wxFprintf( stderr, wxT(": %s"), WXSTRINGCAST(msg) );
|
||||
wxFprintf( stderr, wxT(".\n") );
|
||||
exit(3); // the same exit code as for abort()
|
||||
}
|
||||
|
Reference in New Issue
Block a user