Made audio players register manually.

Originally committed to SVN as r1893.
This commit is contained in:
Rodrigo Braz Monteiro 2008-03-05 02:43:01 +00:00
parent 30d1aeb551
commit ee61192c43
12 changed files with 669 additions and 376 deletions

View File

@ -39,6 +39,21 @@
#include <wx/wxprec.h>
#include "audio_player.h"
#include "options.h"
#ifdef WITH_ALSA
#include "audio_player_alsa.h"
#endif
#ifdef WITH_DIRECTSOUND
#include "audio_player_dsound.h"
#endif
#ifdef WITH_OPENAL
#include "audio_player_openal.h"
#endif
#ifdef WITH_PORTAUDIO
#include "audio_player_portaudio.h"
#endif
#ifdef WITH_PULSEAUDIO
#include "audio_player_pulse.h"
#endif
///////////////
@ -112,6 +127,12 @@ void AudioPlayer::OnStopAudio(wxCommandEvent &event) {
//////////////
// Get player
AudioPlayer* AudioPlayerFactory::GetAudioPlayer() {
// Register factories
// HACK: fix me
static bool init = false;
if (!init) RegisterFactories();
init = true;
// List of providers
wxArrayString list = GetFactoryList(Options.AsText(_T("Audio player")));
@ -135,6 +156,27 @@ AudioPlayer* AudioPlayerFactory::GetAudioPlayer() {
}
//////////////////////////
// Register all factories
void AudioPlayerFactory::RegisterFactories() {
#ifdef WITH_ALSA
new AlsaPlayerFactory();
#endif
#ifdef WITH_DIRECTSOUND
new DirectSoundPlayerFactory();
#endif
#ifdef WITH_OPENAL
new OpenALPlayerFactory();
#endif
#ifdef WITH_PORTAUDIO
new PortAudioPlayerFactory();
#endif
#ifdef WITH_PULSEAUDIO
new PulseAudioPlayerFactory();
#endif
}
//////////
// Static
template <class AudioPlayerFactory> std::map<wxString,AudioPlayerFactory*>* AegisubFactory<AudioPlayerFactory>::factories=NULL;

View File

@ -104,6 +104,7 @@ protected:
public:
virtual ~AudioPlayerFactory() {}
static AudioPlayer *GetAudioPlayer();
static void RegisterFactories();
};

View File

@ -45,75 +45,10 @@
#include "utils.h"
#include "main.h"
#include "frame_main.h"
#include "audio_player.h"
#include <alsa/asoundlib.h>
#include "audio_player_alsa.h"
#include "options.h"
///////////////
// Alsa player
class AlsaPlayer : public AudioPlayer {
private:
bool open;
volatile bool playing;
volatile float volume;
volatile unsigned long start_frame; // first frame of playback
volatile unsigned long cur_frame; // last written frame + 1
volatile unsigned long end_frame; // last frame to play
unsigned long bpf; // bytes per frame
AudioProvider *provider;
snd_pcm_t *pcm_handle; // device handle
snd_pcm_stream_t stream; // stream direction
snd_async_handler_t *pcm_callback;
snd_pcm_format_t sample_format;
unsigned int rate; // sample rate of audio
unsigned int real_rate; // actual sample rate played back
unsigned int period_len; // length of period in microseconds
unsigned int buflen; // length of buffer in microseconds
snd_pcm_uframes_t period; // size of period in frames
snd_pcm_uframes_t bufsize; // size of buffer in frames
void SetUpHardware();
void SetUpAsync();
static void async_write_handler(snd_async_handler_t *pcm_callback);
public:
AlsaPlayer();
~AlsaPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying();
int64_t GetStartPosition();
int64_t GetEndPosition();
int64_t GetCurrentPosition();
void SetEndPosition(int64_t pos);
void SetCurrentPosition(int64_t pos);
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
};
///////////
// Factory
class AlsaPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new AlsaPlayer(); }
AlsaPlayerFactory() : AudioPlayerFactory(_T("alsa")) {}
} registerAlsaPlayer;
///////////////
// Constructor
AlsaPlayer::AlsaPlayer()

115
aegisub/audio_player_alsa.h Normal file
View File

@ -0,0 +1,115 @@
// Copyright (c) 2007, Niels Martin Hansen
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:jiifurusu@gmail.com
//
#ifdef WITH_ALSA
///////////
// Headers
#include <wx/wxprec.h>
#include "audio_player.h"
#include "audio_provider.h"
#include "utils.h"
#include "main.h"
#include "frame_main.h"
#include "audio_player.h"
#include <alsa/asoundlib.h>
#include "options.h"
///////////////
// Alsa player
class AlsaPlayer : public AudioPlayer {
private:
bool open;
volatile bool playing;
volatile float volume;
volatile unsigned long start_frame; // first frame of playback
volatile unsigned long cur_frame; // last written frame + 1
volatile unsigned long end_frame; // last frame to play
unsigned long bpf; // bytes per frame
AudioProvider *provider;
snd_pcm_t *pcm_handle; // device handle
snd_pcm_stream_t stream; // stream direction
snd_async_handler_t *pcm_callback;
snd_pcm_format_t sample_format;
unsigned int rate; // sample rate of audio
unsigned int real_rate; // actual sample rate played back
unsigned int period_len; // length of period in microseconds
unsigned int buflen; // length of buffer in microseconds
snd_pcm_uframes_t period; // size of period in frames
snd_pcm_uframes_t bufsize; // size of buffer in frames
void SetUpHardware();
void SetUpAsync();
static void async_write_handler(snd_async_handler_t *pcm_callback);
public:
AlsaPlayer();
~AlsaPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying();
int64_t GetStartPosition();
int64_t GetEndPosition();
int64_t GetCurrentPosition();
void SetEndPosition(int64_t pos);
void SetCurrentPosition(int64_t pos);
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
};
///////////
// Factory
class AlsaPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new AlsaPlayer(); }
AlsaPlayerFactory() : AudioPlayerFactory(_T("alsa")) {}
};
#endif

View File

@ -44,101 +44,7 @@
#include "utils.h"
#include "main.h"
#include "frame_main.h"
#include "audio_player.h"
#include <mmsystem.h>
#include <dsound.h>
//////////////
// Prototypes
class DirectSoundPlayer;
//////////
// Thread
class DirectSoundPlayerThread : public wxThread {
private:
DirectSoundPlayer *parent;
HANDLE stopnotify;
public:
void Stop(); // Notify thread to stop audio playback. Thread safe.
DirectSoundPlayerThread(DirectSoundPlayer *parent);
~DirectSoundPlayerThread();
wxThread::ExitCode Entry();
};
/*
TODO: Rewrite playback thread to manage all of the buffer, and properly marshal the IDirectSound8
object into the thread for creating the buffer there.
The thread should own the buffer and manage all of the playback.
It must be created with start and duration set, and begins playback at the given position.
New functions:
* Seek(pos) : Restart playback from the given position
* SetEnd(pos) : Set new end point
* GetPosition() : Get the current sample number being played
* Stop() : Stop playback immediately
Instead of using a stop event, use a playback parameters changed event. When that one's fired,
detect which were actually changed and act accordingly.
All but GetPosition() set appropriate fields and then raise the parameters changed event.
*/
////////////////////
// Portaudio player
class DirectSoundPlayer : public AudioPlayer {
friend class DirectSoundPlayerThread;
private:
volatile bool playing;
float volume;
int offset;
DWORD bufSize;
volatile int64_t playPos;
int64_t startPos;
volatile int64_t endPos;
DWORD startTime;
IDirectSound8 *directSound;
IDirectSoundBuffer8 *buffer;
bool FillBuffer(bool fill);
DirectSoundPlayerThread *thread;
public:
DirectSoundPlayer();
~DirectSoundPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying() { return playing; }
int64_t GetStartPosition() { return startPos; }
int64_t GetEndPosition() { return endPos; }
int64_t GetCurrentPosition();
void SetEndPosition(int64_t pos);
void SetCurrentPosition(int64_t pos);
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
//wxMutex *GetMutex() { return &DSMutex; }
};
///////////
// Factory
class DirectSoundPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new DirectSoundPlayer(); }
DirectSoundPlayerFactory() : AudioPlayerFactory(_T("dsound")) {}
} registerDirectSoundPlayer;
#include "audio_player_dsound.h"
///////////////

View File

@ -0,0 +1,143 @@
// Copyright (c) 2006, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
///////////
// Headers
#ifdef WITH_DIRECTSOUND
#include <wx/wxprec.h>
#include "audio_player.h"
#include "audio_provider.h"
#include "utils.h"
#include "main.h"
#include "frame_main.h"
#include "audio_player.h"
#include <mmsystem.h>
#include <dsound.h>
//////////////
// Prototypes
class DirectSoundPlayer;
//////////
// Thread
class DirectSoundPlayerThread : public wxThread {
private:
DirectSoundPlayer *parent;
HANDLE stopnotify;
public:
void Stop(); // Notify thread to stop audio playback. Thread safe.
DirectSoundPlayerThread(DirectSoundPlayer *parent);
~DirectSoundPlayerThread();
wxThread::ExitCode Entry();
};
/*
TODO: Rewrite playback thread to manage all of the buffer, and properly marshal the IDirectSound8
object into the thread for creating the buffer there.
The thread should own the buffer and manage all of the playback.
It must be created with start and duration set, and begins playback at the given position.
New functions:
* Seek(pos) : Restart playback from the given position
* SetEnd(pos) : Set new end point
* GetPosition() : Get the current sample number being played
* Stop() : Stop playback immediately
Instead of using a stop event, use a playback parameters changed event. When that one's fired,
detect which were actually changed and act accordingly.
All but GetPosition() set appropriate fields and then raise the parameters changed event.
*/
////////////////////
// Portaudio player
class DirectSoundPlayer : public AudioPlayer {
friend class DirectSoundPlayerThread;
private:
volatile bool playing;
float volume;
int offset;
DWORD bufSize;
volatile int64_t playPos;
int64_t startPos;
volatile int64_t endPos;
DWORD startTime;
IDirectSound8 *directSound;
IDirectSoundBuffer8 *buffer;
bool FillBuffer(bool fill);
DirectSoundPlayerThread *thread;
public:
DirectSoundPlayer();
~DirectSoundPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying() { return playing; }
int64_t GetStartPosition() { return startPos; }
int64_t GetEndPosition() { return endPos; }
int64_t GetCurrentPosition();
void SetEndPosition(int64_t pos);
void SetCurrentPosition(int64_t pos);
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
//wxMutex *GetMutex() { return &DSMutex; }
};
///////////
// Factory
class DirectSoundPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new DirectSoundPlayer(); }
DirectSoundPlayerFactory() : AudioPlayerFactory(_T("dsound")) {}
};
#endif

View File

@ -45,7 +45,7 @@
#include "utils.h"
#include "main.h"
#include "frame_main.h"
#include "audio_player.h"
#include "audio_player_openal.h"
#include "options.h"
#ifdef __APPLE__
#include <OpenAL/AL.h>
@ -62,73 +62,6 @@
#endif
/////////////////
// OpenAL player
class OpenALPlayer : public AudioPlayer, wxTimer {
private:
bool open;
volatile bool playing;
volatile float volume;
static const ALsizei num_buffers = 8;
ALsizei buffer_length;
ALsizei samplerate;
volatile unsigned long start_frame; // first frame of playback
volatile unsigned long cur_frame; // last written frame + 1
volatile unsigned long end_frame; // last frame to play
unsigned long bpf; // bytes per frame
AudioProvider *provider;
ALCdevice *device; // device handle
ALCcontext *context; // sound context
ALuint buffers[num_buffers]; // sound buffers
ALuint source; // playback source
ALsizei buf_first_free; // index into buffers, first free (unqueued) buffer
ALsizei buf_first_queued; // index into buffers, first queued (non-free) buffer
ALsizei buffers_free; // number of free buffers
ALsizei buffers_played;
wxStopWatch playback_segment_timer;
void FillBuffers(ALsizei count);
protected:
void Notify(); // from wxTimer
public:
OpenALPlayer();
~OpenALPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying();
int64_t GetStartPosition();
int64_t GetEndPosition();
int64_t GetCurrentPosition();
void SetEndPosition(int64_t pos);
void SetCurrentPosition(int64_t pos);
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
};
///////////
// Factory
class OpenALPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new OpenALPlayer(); }
OpenALPlayerFactory() : AudioPlayerFactory(_T("openal")) {}
} registerOALPlayer;
///////////////
// Constructor
OpenALPlayer::OpenALPlayer()

View File

@ -0,0 +1,124 @@
// Copyright (c) 2007, Niels Martin Hansen
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:jiifurusu@gmail.com
//
#ifdef WITH_OPENAL
///////////
// Headers
#include <wx/wxprec.h>
#include "audio_player.h"
#include "audio_provider.h"
#include "utils.h"
#include "main.h"
#include "frame_main.h"
#include "audio_player.h"
#include "options.h"
#ifdef __APPLE__
#include <OpenAL/AL.h>
#include <OpenAL/ALC.h>
#else
#include <al.h>
#include <alc.h>
#endif
/////////////////
// OpenAL player
class OpenALPlayer : public AudioPlayer, wxTimer {
private:
bool open;
volatile bool playing;
volatile float volume;
static const ALsizei num_buffers = 8;
ALsizei buffer_length;
ALsizei samplerate;
volatile unsigned long start_frame; // first frame of playback
volatile unsigned long cur_frame; // last written frame + 1
volatile unsigned long end_frame; // last frame to play
unsigned long bpf; // bytes per frame
AudioProvider *provider;
ALCdevice *device; // device handle
ALCcontext *context; // sound context
ALuint buffers[num_buffers]; // sound buffers
ALuint source; // playback source
ALsizei buf_first_free; // index into buffers, first free (unqueued) buffer
ALsizei buf_first_queued; // index into buffers, first queued (non-free) buffer
ALsizei buffers_free; // number of free buffers
ALsizei buffers_played;
wxStopWatch playback_segment_timer;
void FillBuffers(ALsizei count);
protected:
void Notify(); // from wxTimer
public:
OpenALPlayer();
~OpenALPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying();
int64_t GetStartPosition();
int64_t GetEndPosition();
int64_t GetCurrentPosition();
void SetEndPosition(int64_t pos);
void SetCurrentPosition(int64_t pos);
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
};
///////////
// Factory
class OpenALPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new OpenALPlayer(); }
OpenALPlayerFactory() : AudioPlayerFactory(_T("openal")) {}
};
#endif

View File

@ -39,12 +39,9 @@
///////////
// Headers
#include "audio_player.h"
#include "audio_player_portaudio.h"
#include "audio_provider.h"
#include "utils.h"
extern "C" {
#include <portaudio.h>
}
#ifdef HAVE_PA_GETSTREAMTIME
#define Pa_StreamTime Pa_GetStreamTime /* PortAudio v19 */
@ -59,66 +56,6 @@ extern "C" {
#endif
////////////////////
// Portaudio player
class PortAudioPlayer : public AudioPlayer {
private:
static int pa_refcount;
wxMutex PAMutex;
volatile bool stopping;
//bool softStop;
bool playing;
float volume;
volatile int64_t playPos;
volatile int64_t startPos;
volatile int64_t endPos;
void *stream;
PaTimestamp paStart;
volatile int64_t realPlayPos;
#ifndef HAVE_PA_GETSTREAMTIME
static int paCallback(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData);
#else
static int paCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *timei,
PaStreamCallbackFlags flags, void *userData);
#endif
public:
PortAudioPlayer();
~PortAudioPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying() { return playing; }
int64_t GetStartPosition() { return startPos; }
int64_t GetEndPosition() { return endPos; }
int64_t GetCurrentPosition() { return realPlayPos; }
void SetEndPosition(int64_t pos) { endPos = pos; }
void SetCurrentPosition(int64_t pos) { playPos = pos; realPlayPos = pos; }
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
wxMutex *GetMutex() { return &PAMutex; }
};
///////////
// Factory
class PortAudioPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new PortAudioPlayer(); }
PortAudioPlayerFactory() : AudioPlayerFactory(_T("portaudio")) {}
} registerPortAudioPlayer;
/////////////////////
// Reference counter
int PortAudioPlayer::pa_refcount = 0;

View File

@ -0,0 +1,109 @@
// Copyright (c) 2005-2007, Rodrigo Braz Monteiro
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:zeratul@cellosoft.com
//
#ifdef WITH_PORTAUDIO
///////////
// Headers
#include "audio_player.h"
#include "audio_provider.h"
#include "utils.h"
extern "C" {
#include <portaudio.h>
}
////////////////////
// Portaudio player
class PortAudioPlayer : public AudioPlayer {
private:
static int pa_refcount;
wxMutex PAMutex;
volatile bool stopping;
//bool softStop;
bool playing;
float volume;
volatile int64_t playPos;
volatile int64_t startPos;
volatile int64_t endPos;
void *stream;
PaTimestamp paStart;
volatile int64_t realPlayPos;
#ifndef HAVE_PA_GETSTREAMTIME
static int paCallback(void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData);
#else
static int paCallback(const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo *timei,
PaStreamCallbackFlags flags, void *userData);
#endif
public:
PortAudioPlayer();
~PortAudioPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying() { return playing; }
int64_t GetStartPosition() { return startPos; }
int64_t GetEndPosition() { return endPos; }
int64_t GetCurrentPosition() { return realPlayPos; }
void SetEndPosition(int64_t pos) { endPos = pos; }
void SetCurrentPosition(int64_t pos) { playPos = pos; realPlayPos = pos; }
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
wxMutex *GetMutex() { return &PAMutex; }
};
///////////
// Factory
class PortAudioPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new PortAudioPlayer(); }
PortAudioPlayerFactory() : AudioPlayerFactory(_T("portaudio")) {}
};
#endif

View File

@ -41,92 +41,10 @@
// Headers
#include <wx/wxprec.h>
#include <stdio.h>
#include "audio_player.h"
#include "audio_player_pulse.h"
#include "audio_provider.h"
#include "utils.h"
#include "options.h"
#include <pulse/pulseaudio.h>
//////////////
// Prototypes
class PulseAudioPlayer;
//////////////////////
// Pulse Audio player
class PulseAudioPlayer : public AudioPlayer {
private:
float volume;
bool open;
bool is_playing;
// Audio data info
volatile unsigned long start_frame;
volatile unsigned long cur_frame;
volatile unsigned long end_frame;
unsigned long bpf; // bytes per frame
// Used for synchronising with async events
wxSemaphore context_notify;
wxSemaphore context_success;
volatile int context_success_val;
wxSemaphore stream_notify;
wxSemaphore stream_success;
volatile int stream_success_val;
// PulseAudio data
pa_threaded_mainloop *mainloop; // pulseaudio mainloop handle
pa_context *context; // connection context
volatile pa_context_state_t cstate;
pa_stream *stream;
volatile pa_stream_state_t sstate;
volatile pa_usec_t play_start_time; // timestamp when playback was started
int paerror;
// Called by PA to notify about contetxt operation completion
static void pa_context_success(pa_context *c, int success, PulseAudioPlayer *thread);
// Called by PA to notify about other context-related stuff
static void pa_context_notify(pa_context *c, PulseAudioPlayer *thread);
// Called by PA when a stream operation completes
static void pa_stream_success(pa_stream *p, int success, PulseAudioPlayer *thread);
// Called by PA to request more data written to stream
static void pa_stream_write(pa_stream *p, size_t length, PulseAudioPlayer *thread);
// Called by PA to notify about other stream-related stuff
static void pa_stream_notify(pa_stream *p, PulseAudioPlayer *thread);
public:
PulseAudioPlayer();
~PulseAudioPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying();
int64_t GetStartPosition();
int64_t GetEndPosition();
int64_t GetCurrentPosition();
void SetEndPosition(int64_t pos);
void SetCurrentPosition(int64_t pos);
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
};
///////////
// Factory
class PulseAudioPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new PulseAudioPlayer(); }
PulseAudioPlayerFactory() : AudioPlayerFactory(_T("pulse")) {}
} registerPulsePlayer;
///////////////

View File

@ -0,0 +1,130 @@
// Copyright (c) 2007, Niels Martin Hansen
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the Aegisub Group nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// -----------------------------------------------------------------------------
//
// AEGISUB
//
// Website: http://aegisub.cellosoft.com
// Contact: mailto:jiifurusu@gmail.com
//
#ifdef WITH_PULSEAUDIO
///////////
// Headers
#include <wx/wxprec.h>
#include <stdio.h>
#include "audio_player.h"
#include "audio_provider.h"
#include "utils.h"
#include "options.h"
#include <pulse/pulseaudio.h>
//////////////
// Prototypes
class PulseAudioPlayer;
//////////////////////
// Pulse Audio player
class PulseAudioPlayer : public AudioPlayer {
private:
float volume;
bool open;
bool is_playing;
// Audio data info
volatile unsigned long start_frame;
volatile unsigned long cur_frame;
volatile unsigned long end_frame;
unsigned long bpf; // bytes per frame
// Used for synchronising with async events
wxSemaphore context_notify;
wxSemaphore context_success;
volatile int context_success_val;
wxSemaphore stream_notify;
wxSemaphore stream_success;
volatile int stream_success_val;
// PulseAudio data
pa_threaded_mainloop *mainloop; // pulseaudio mainloop handle
pa_context *context; // connection context
volatile pa_context_state_t cstate;
pa_stream *stream;
volatile pa_stream_state_t sstate;
volatile pa_usec_t play_start_time; // timestamp when playback was started
int paerror;
// Called by PA to notify about contetxt operation completion
static void pa_context_success(pa_context *c, int success, PulseAudioPlayer *thread);
// Called by PA to notify about other context-related stuff
static void pa_context_notify(pa_context *c, PulseAudioPlayer *thread);
// Called by PA when a stream operation completes
static void pa_stream_success(pa_stream *p, int success, PulseAudioPlayer *thread);
// Called by PA to request more data written to stream
static void pa_stream_write(pa_stream *p, size_t length, PulseAudioPlayer *thread);
// Called by PA to notify about other stream-related stuff
static void pa_stream_notify(pa_stream *p, PulseAudioPlayer *thread);
public:
PulseAudioPlayer();
~PulseAudioPlayer();
void OpenStream();
void CloseStream();
void Play(int64_t start,int64_t count);
void Stop(bool timerToo=true);
bool IsPlaying();
int64_t GetStartPosition();
int64_t GetEndPosition();
int64_t GetCurrentPosition();
void SetEndPosition(int64_t pos);
void SetCurrentPosition(int64_t pos);
void SetVolume(double vol) { volume = vol; }
double GetVolume() { return volume; }
};
///////////
// Factory
class PulseAudioPlayerFactory : public AudioPlayerFactory {
public:
AudioPlayer *CreatePlayer() { return new PulseAudioPlayer(); }
PulseAudioPlayerFactory() : AudioPlayerFactory(_T("pulse")) {}
};
#endif