From 5f4db637aaedbcefd98b9663d7417adbad32c2ca Mon Sep 17 00:00:00 2001 From: urioxis Date: Tue, 8 Feb 2011 14:52:18 +0000 Subject: [PATCH] Added esd output plugin --- src/contrib/CMakeLists.txt | 3 +- src/contrib/esdout/CMakeLists.txt | 28 ++ src/contrib/esdout/EsdOut.cpp | 269 +++++++++++++++++++ src/contrib/esdout/EsdOut.h | 106 ++++++++ src/contrib/esdout/EsdOutBuffer.cpp | 109 ++++++++ src/contrib/esdout/EsdOutBuffer.h | 71 +++++ src/contrib/esdout/esd.h | 316 +++++++++++++++++++++++ src/contrib/esdout/esdout_plugin.cpp | 71 +++++ src/contrib/esdout/pch.h | 43 +++ src/contrib/mpg123decoder/CMakeLists.txt | 2 +- src/contrib/stdout/StdOut.cpp | 2 +- src/contrib/stdout/StdOut.h | 4 + 12 files changed, 1021 insertions(+), 3 deletions(-) create mode 100644 src/contrib/esdout/CMakeLists.txt create mode 100644 src/contrib/esdout/EsdOut.cpp create mode 100644 src/contrib/esdout/EsdOut.h create mode 100644 src/contrib/esdout/EsdOutBuffer.cpp create mode 100644 src/contrib/esdout/EsdOutBuffer.h create mode 100644 src/contrib/esdout/esd.h create mode 100644 src/contrib/esdout/esdout_plugin.cpp create mode 100644 src/contrib/esdout/pch.h diff --git a/src/contrib/CMakeLists.txt b/src/contrib/CMakeLists.txt index 5f3b3f203..64dcf2a9a 100644 --- a/src/contrib/CMakeLists.txt +++ b/src/contrib/CMakeLists.txt @@ -7,7 +7,7 @@ add_subdirectory( flacdecoder ) #add_subdirectory( httpstream ) #add_subdirectory( oggdecoder ) -add_subdirectory( stdout ) +#add_subdirectory( stdout ) find_package(Taglib) add_definitions(-D_HAVE_TAGLIB) @@ -20,6 +20,7 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows") # endif(NOT DEFINED MINGW) else(CMAKE_SYSTEM_NAME MATCHES "Windows") add_subdirectory( alsaout ) + add_subdirectory( esdout ) add_subdirectory( mpg123decoder ) endif(CMAKE_SYSTEM_NAME MATCHES "Windows") diff --git a/src/contrib/esdout/CMakeLists.txt b/src/contrib/esdout/CMakeLists.txt new file mode 100644 index 000000000..695aa5e51 --- /dev/null +++ b/src/contrib/esdout/CMakeLists.txt @@ -0,0 +1,28 @@ +set ( esdout_SOURCES + esdout_plugin.cpp + EsdOut.cpp + EsdOutBuffer.cpp + ) + +if(CMAKE_SYSTEM_NAME MATCHES "Windows") + add_definitions(-DWIN32) + if(NOT DEFINED MINGW) + + endif(NOT DEFINED MINGW) +else(CMAKE_SYSTEM_NAME MATCHES "Windows") + set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -fpermissive) +endif(CMAKE_SYSTEM_NAME MATCHES "Windows") + +add_definitions( + -DXML_STATIC + -D_CRT_SECURE_NO_DEPRECATE + -D_DEBUG +) + +#include_directories( ../../core ) +include_directories(/usr/include) + +add_library( esdout SHARED ${esdout_SOURCES} ) +target_link_libraries( esdout ${musikCube_LINK_LIBS} esd) + + diff --git a/src/contrib/esdout/EsdOut.cpp b/src/contrib/esdout/EsdOut.cpp new file mode 100644 index 000000000..ca175cd05 --- /dev/null +++ b/src/contrib/esdout/EsdOut.cpp @@ -0,0 +1,269 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright 2007, Daniel nnerby +// +// 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 author nor the names of other 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. +// +////////////////////////////////////////////////////////////////////////////// +#include "EsdOut.h" + +EsdOut::EsdOut() + :waveHandle(NULL) + ,maxBuffers(32) + ,currentVolume(1.0) + ,addToRemovedBuffers(false) + ,device("default") + //,output(NULL) +{ +#ifdef _DEBUG + std::cerr << "EsdOut::EsdOut() called" << std::endl; +#endif +} + +EsdOut::~EsdOut(){ +#ifdef _DEBUG + std::cerr << "EsdOut::~EsdOut()" << std::endl; +#endif + this->ClearBuffers(); + + esd_close( *this->waveHandle ); + +} + +int* EsdOut::getWaveHandle() { +#ifdef _DEBUG + std::cerr << "EsdOut::getWaveHandle()" << std::endl; +#endif + return this->waveHandle; +} + +void EsdOut::Destroy(){ +#ifdef _DEBUG + std::cerr << "EsdOut::Destroy()" << std::endl; +#endif + delete this; +} + +void EsdOut::Pause(){ +#ifdef _DEBUG + std::cerr << "EsdOut::Pause()" << std::endl; +#endif + esd_standby(*this->waveHandle); +} + +void EsdOut::Resume(){ +#ifdef _DEBUG + std::cerr << "EsdOut::Resume()" << std::endl; +#endif + esd_resume(*this->waveHandle); +} + +void EsdOut::SetVolume(double volume){ +#ifdef _DEBUG + std::cerr << "EsdOut::SetVolume()" << std::endl; +#endif + /*if(this->waveHandle){ + DWORD newVolume = (DWORD)(volume*65535.0); + newVolume += newVolume*65536; + + waveOutSetVolume(this->waveHandle,newVolume); + }*/ + this->currentVolume = volume; //TODO: Write Esd SetVolume() function +} + +void EsdOut::ClearBuffers(){ +#ifdef _DEBUG + std::cerr << "EsdOut::ClearBuffers()" << std::endl; +#endif + //snd_pcm_drop(this->waveHandle); + //snd_pcm_reset(this->waveHandle); + //TODO: check nothing needs doing here +} + +void EsdOut::RemoveBuffer(EsdOutBuffer *buffer){ +#ifdef _DEBUG + std::cerr << "EsdOut::RemoveBuffer()" << std::endl; +#endif + BufferList clearBuffers; + { + boost::mutex::scoped_lock lock(this->mutex); + bool found(false); + for(BufferList::iterator buf=this->buffers.begin();buf!=this->buffers.end() && !found;){ + if(buf->get()==buffer){ +// if( !(*buf)->ReadyToRelease() ){ + this->removedBuffers.push_back(*buf); +// } + clearBuffers.push_back(*buf); + buf=this->buffers.erase(buf); + found=true; + }else{ + ++buf; + } + } + } +} + +void EsdOut::ReleaseBuffers(){ +#ifdef _DEBUG + std::cerr << "EsdOut::ReleaseBuffers()" << std::endl; +#endif + BufferList clearBuffers; + { + boost::mutex::scoped_lock lock(this->mutex); + for(BufferList::iterator buf=this->removedBuffers.begin();buf!=this->removedBuffers.end();){ + clearBuffers.push_back(*buf); + buf = this->removedBuffers.erase(buf); + } + } + +} + +bool EsdOut::PlayBuffer(IBuffer *buffer,IPlayer *player){ +#ifdef _DEBUG + std::cerr << "EsdOut::PlayBuffer()" << std::endl; +#endif + + size_t bufferSize = 0; + { + boost::mutex::scoped_lock lock(this->mutex); + bufferSize = this->buffers.size(); + } + + // if the format should change, wait for all buffers to be released + if(bufferSize>0 && (this->currentChannels!=buffer->Channels() || this->currentSampleRate!=buffer->SampleRate())){ + // Format has changed +// this->player->Notify() + return false; + } + + + if(bufferSizemaxBuffers){ + // Start by checking the format + this->SetFormat(buffer); + + // Add to the waveout internal buffers + EsdOutBufferPtr EsdBuffer(new EsdOutBuffer(this,buffer,player)); + + // Header should now be prepared, lets add to waveout + if( EsdBuffer->AddToOutput() ){ + // Add to the buffer list + { + boost::mutex::scoped_lock lock(this->mutex); + this->buffers.push_back(EsdBuffer); + } + return true; + } + + } + + return false; +} + +void EsdOut::SetFormat(IBuffer *buffer){ +#ifdef _DEBUG + std::cerr << "EsdOut::SetFormat()" << std::endl; +#endif + if(this->currentChannels!=buffer->Channels() || this->currentSampleRate!=buffer->SampleRate() ||this->waveHandle==NULL){ + this->currentChannels = buffer->Channels(); + this->currentSampleRate = buffer->SampleRate(); + + //TODO: Do something here? + + // Close old waveout + /*if(this->waveHandle!=NULL){ + snd_pcm_close(this->waveHandle); + this->waveHandle = NULL; + }*/ +/* + // Create a new waveFormat + ZeroMemory(&this->waveFormat, sizeof(this->waveFormat)); + DWORD speakerconfig; + + // Set speaker configuration + switch(buffer->Channels()){ + case 1: + speakerconfig = KSAUDIO_SPEAKER_MONO; + break; + case 2: + speakerconfig = KSAUDIO_SPEAKER_STEREO; + break; + case 4: + speakerconfig = KSAUDIO_SPEAKER_QUAD; + break; + case 5: + speakerconfig = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT); + break; + case 6: + speakerconfig = KSAUDIO_SPEAKER_5POINT1; + break; + default: + speakerconfig = 0; + } + + this->waveFormat.Format.cbSize = 22; + this->waveFormat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + this->waveFormat.Format.nChannels = (WORD)buffer->Channels(); + this->waveFormat.Format.nSamplesPerSec = (DWORD)buffer->SampleRate(); + this->waveFormat.Format.wBitsPerSample = 32; + this->waveFormat.Format.nBlockAlign = (this->waveFormat.Format.wBitsPerSample/8) * this->waveFormat.Format.nChannels; + this->waveFormat.Format.nAvgBytesPerSec = ((this->waveFormat.Format.wBitsPerSample/8) * this->waveFormat.Format.nChannels) * this->waveFormat.Format.nSamplesPerSec; //Compute using nBlkAlign * nSamp/Sec + + // clangen: wValidBitsPerSample/wReserved/wSamplesPerBlock are a union, + // so don't set wReserved or wSamplesPerBlock to 0 after assigning + // wValidBitsPerSample. (Vista bug) + this->waveFormat.Samples.wValidBitsPerSample = 32; + this->waveFormat.dwChannelMask = speakerconfig; + this->waveFormat.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + */ + //this->waveFormat = SND_PCM_FORMAT_FLOAT_LE; + //this->waveAccess = SND_PCM_ACCESS_RW_INTERLEAVED; + + //int err; + //Open the device + /* if ((err = snd_pcm_open(&this->waveHandle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { + printf("Playback open error: %s\n", snd_strerror(err)); + return; + }*/ + //Set simple parameters + /* if (( err = snd_pcm_set_params( + this->waveHandle, + this->waveFormat, + this->waveAccess, + this->currentChannels, + this->currentSampleRate, + 1, //Allow Esd-lib software resampling + 500000) //Required overall latency (us) 0.5s + ) > 0) { //If an error... + printf("Playback open error: %s\n", snd_strerror(err)); + exit(EXIT_FAILURE); + } +*/ + // Set the volume if it's not already set + // this->SetVolume(this->currentVolume); + } +} diff --git a/src/contrib/esdout/EsdOut.h b/src/contrib/esdout/EsdOut.h new file mode 100644 index 000000000..6c16d6c60 --- /dev/null +++ b/src/contrib/esdout/EsdOut.h @@ -0,0 +1,106 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright © 2009, Julian Cromarty +// +// 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 author nor the names of other 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. +// +////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include "pch.h" +#include "EsdOutBuffer.h" +/* +#include +#include + +#include +#include +*/ +#include +#include +#include +#include + +using namespace musik::core::audio; + +class EsdOut : public IOutput{ + public: + EsdOut(); + ~EsdOut(); + + virtual void Destroy(); + //virtual void Initialize(IPlayer *player); + virtual void Pause(); + virtual void Resume(); + virtual void SetVolume(double volume); + virtual void ClearBuffers(); + virtual bool PlayBuffer(IBuffer *buffer,IPlayer *player); + virtual void ReleaseBuffers(); + + int* getWaveHandle(); + + public: + typedef boost::shared_ptr EsdOutBufferPtr; + + //static void CALLBACK WaveCallback(HWAVEOUT hWave, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD dw2); + void RemoveBuffer(EsdOutBuffer *buffer); + + private: + void SetFormat(IBuffer *buffer); + char *device; /* playback device */ + + protected: + friend class EsdOutBuffer; + + //IPlayer *player; + + // Audio stuff + int *waveHandle; + //snd_pcm_t *waveHandle; + esd_format_t waveFormat; + //snd_pcm_access_t waveAccess; + //snd_pcm_hw_params_t *hw_params; + + /*int bits = ESD_BITS16, channels = ESD_STEREO; + int mode = ESD_STREAM, func = ESD_PLAY ;*/ + + // Current format + int currentChannels; + long currentSampleRate; + double currentVolume; + + typedef std::list BufferList; + BufferList buffers; + BufferList removedBuffers; + size_t maxBuffers; + + boost::mutex mutex; + + bool addToRemovedBuffers; + +}; diff --git a/src/contrib/esdout/EsdOutBuffer.cpp b/src/contrib/esdout/EsdOutBuffer.cpp new file mode 100644 index 000000000..7a83e0f5e --- /dev/null +++ b/src/contrib/esdout/EsdOutBuffer.cpp @@ -0,0 +1,109 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright ﺏ 2007, Daniel ﺿnnerby +// +// 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 author nor the names of other 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. +// +////////////////////////////////////////////////////////////////////////////// +#include "EsdOutBuffer.h" +#include "EsdOut.h" + +////////////////////////////////////////////////////////////////////////////// + +EsdOutBuffer::EsdOutBuffer(EsdOut *EsdOut,IBuffer *buffer,IPlayer *player) + :waveOut(EsdOut) + ,buffer(buffer) + ,player(player) +{ +#ifdef _DEBUG + std::cerr << "EsdOutBuffer::EsdOutBuffer()" << std::endl; +#endif + this->PrepareBuffer(); +} + +void EsdOutBuffer::PrepareBuffer(){ +#ifdef _DEBUG + std::cerr << "EsdOutBuffer::PrepareBuffer()" << std::endl; +#endif + //unsigned float bufSize = this->buffer->Samples()*this->buffer->Channels()*sizeof(float); + /*// Prepare the header + this->header.dwBufferLength = this->buffer->Samples()*this->buffer->Channels()*sizeof(float); + this->header.lpData = (LPSTR)this->buffer->BufferPointer(); + this->header.dwUser = (DWORD_PTR)this; + this->header.dwBytesRecorded = 0; + this->header.dwFlags = 0; + this->header.dwLoops = 0; + this->header.lpNext = NULL; + this->header.reserved = NULL; + + MMRESULT result = waveOutPrepareHeader(this->waveOut->waveHandle,&this->header,sizeof(WAVEHDR)); + if(result!=MMSYSERR_NOERROR){ + throw; + } + this->header.dwFlags |= WHDR_DONE; + */ + data = (char*)this->buffer->BufferPointer(); + bufferLength = this->buffer->Samples()*this->buffer->Channels()*sizeof(float); + //TODO: Check data types. + +} + +EsdOutBuffer::~EsdOutBuffer(void) +{ +#ifdef _DEBUG + std::cerr << "EsdOutBuffer::~EsdOutBuffer()" << std::endl; +#endif + this->player->ReleaseBuffer(this->buffer); +} + +bool EsdOutBuffer::AddToOutput(){ +#ifdef _DEBUG + std::cerr << "EsdOutBuffer::AddToOutput()" << std::endl; +#endif + //int err; + int* wHandle = waveOut->getWaveHandle(); + if (wHandle == NULL) { + printf("Error. No device handle \n"); + return false; + } + /*frames = snd_pcm_writei(wHandle, (void*)data, bufferLength); + if (frames < 0) + frames = snd_pcm_recover(wHandle, frames, 0); + if (frames < 0) { + printf("snd_pcm_writei failed: %s\n", snd_strerror(err)); + return false; + } + if (frames > 0 && frames < (long)bufferLength) { + printf("Short write (expected %li, wrote %li)\n", (long)bufferLength, frames); + return false; + }*/ + if ( write( *wHandle, *data, bufferLength ) <= 0 ) + return false; + return true; +} + diff --git a/src/contrib/esdout/EsdOutBuffer.h b/src/contrib/esdout/EsdOutBuffer.h new file mode 100644 index 000000000..511675769 --- /dev/null +++ b/src/contrib/esdout/EsdOutBuffer.h @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////////////// +// Copyright � 2007, Daniel �nnerby +// +// 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 author nor the names of other 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. +// +////////////////////////////////////////////////////////////////////////////// +#pragma once + +#include +#include +#include "pch.h" + +////////////////////////////////////////////////////////////////////////////// +// Forward declare +class EsdOut; + +////////////////////////////////////////////////////////////////////////////// + +using namespace musik::core::audio; + +class EsdOutBuffer +{ + public: + EsdOutBuffer(EsdOut *waveOut,IBuffer *buffer,IPlayer *player); + ~EsdOutBuffer(void); + + bool AddToOutput(); + void PrepareBuffer(); + + EsdOut *waveOut; + IBuffer *buffer; + IPlayer *player; + + //snd_pcm_channel_area_t *areas; + + private: + //char frames; + char* data; + int bufferLength; + + + +}; + +////////////////////////////////////////////////////////////////////////////// diff --git a/src/contrib/esdout/esd.h b/src/contrib/esdout/esd.h new file mode 100644 index 000000000..206993af5 --- /dev/null +++ b/src/contrib/esdout/esd.h @@ -0,0 +1,316 @@ +#ifndef ESD_H +#define ESD_H +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* length of the audio buffer size */ +#define ESD_BUF_SIZE (4 * 1024) + +/* length of the authorization key, octets */ +#define ESD_KEY_LEN (16) + +/* default port for the EsounD server */ +#define ESD_DEFAULT_PORT (5001) + +/* default sample rate for the EsounD server */ +#define ESD_DEFAULT_RATE (44100) + +/* maximum length of a stream/sample name */ +#define ESD_NAME_MAX (128) + +/* a magic number to identify the relative endianness of a client */ +#define ESD_ENDIAN_KEY \ + ( (unsigned int) ( ('E' << 24) + ('N' << 16) + ('D' << 8) + ('N') ) ) + +#define ESD_VOLUME_BASE (256) + +/*************************************/ +/* what can we do to/with the EsounD */ +enum esd_proto { + ESD_PROTO_CONNECT, /* implied on inital client connection */ + + /* pseudo "security" functionality */ + ESD_PROTO_LOCK, /* disable "foreign" client connections */ + ESD_PROTO_UNLOCK, /* enable "foreign" client connections */ + + /* stream functionality: play, record, monitor */ + ESD_PROTO_STREAM_PLAY, /* play all following data as a stream */ + ESD_PROTO_STREAM_REC, /* record data from card as a stream */ + ESD_PROTO_STREAM_MON, /* send mixed buffer output as a stream */ + + /* sample functionality: cache, free, play, loop, EOL, kill */ + ESD_PROTO_SAMPLE_CACHE, /* cache a sample in the server */ + ESD_PROTO_SAMPLE_FREE, /* release a sample in the server */ + ESD_PROTO_SAMPLE_PLAY, /* play a cached sample */ + ESD_PROTO_SAMPLE_LOOP, /* loop a cached sample, til eoloop */ + ESD_PROTO_SAMPLE_STOP, /* stop a looping sample when done */ + ESD_PROTO_SAMPLE_KILL, /* stop the looping sample immed. */ + + /* free and reclaim /dev/dsp functionality */ + ESD_PROTO_STANDBY, /* release /dev/dsp and ignore all data */ + ESD_PROTO_RESUME, /* reclaim /dev/dsp and play sounds again */ + + /* TODO: move these to a more logical place. NOTE: will break the protocol */ + ESD_PROTO_SAMPLE_GETID, /* get the ID for an already-cached sample */ + ESD_PROTO_STREAM_FILT, /* filter mixed buffer output as a stream */ + + /* esd remote management */ + ESD_PROTO_SERVER_INFO, /* get server info (ver, sample rate, format) */ + ESD_PROTO_ALL_INFO, /* get all info (server info, players, samples) */ + ESD_PROTO_SUBSCRIBE, /* track new and removed players and samples */ + ESD_PROTO_UNSUBSCRIBE, /* stop tracking updates */ + + /* esd remote control */ + ESD_PROTO_STREAM_PAN, /* set stream panning */ + ESD_PROTO_SAMPLE_PAN, /* set default sample panning */ + + /* esd status */ + ESD_PROTO_STANDBY_MODE, /* see if server is in standby, autostandby, etc */ + + ESD_PROTO_MAX /* for bounds checking */ +}; + + +/******************/ +/* The EsounD api */ + +/* the properties of a sound buffer are logically or'd */ + +/* bits of stream/sample data */ +#define ESD_MASK_BITS ( 0x000F ) +#define ESD_BITS8 ( 0x0000 ) +#define ESD_BITS16 ( 0x0001 ) + +/* how many interleaved channels of data */ +#define ESD_MASK_CHAN ( 0x00F0 ) +#define ESD_MONO ( 0x0010 ) +#define ESD_STEREO ( 0x0020 ) + +/* whether it's a stream or a sample */ +#define ESD_MASK_MODE ( 0x0F00 ) +#define ESD_STREAM ( 0x0000 ) +#define ESD_SAMPLE ( 0x0100 ) +#define ESD_ADPCM ( 0x0200 ) /* TODO: anyone up for this? =P */ + +/* the function of the stream/sample, and common functions */ +#define ESD_MASK_FUNC ( 0xF000 ) +#define ESD_PLAY ( 0x1000 ) +/* functions for streams only */ +#define ESD_MONITOR ( 0x0000 ) +#define ESD_RECORD ( 0x2000 ) +/* functions for samples only */ +#define ESD_STOP ( 0x0000 ) +#define ESD_LOOP ( 0x2000 ) + +typedef int esd_format_t; +typedef int esd_proto_t; + +/*******************************************************************/ +/* client side API for playing sounds */ + +typedef unsigned char octet; + +/*******************************************************************/ +/* esdlib.c - basic esd client interface functions */ + +/* opens channel, authenticates connection, and prefares for protos */ +/* returns EsounD socket for communication, result < 0 = error */ +/* server = listen socket (localhost:5001, 192.168.168.0:9999 */ +/* rate, format = (bits | channels | stream | func) */ +int esd_open_sound( const char *host ); + +/* send the authorization cookie, create one if needed */ +int esd_send_auth( int sock ); + +/* lock/unlock will disable/enable foreign clients from connecting */ +int esd_lock( int esd ); +int esd_unlock( int esd ); + +/* standby/resume will free/reclaim audio device so others may use it */ +int esd_standby( int esd ); +int esd_resume( int esd ); + +/* open a socket for playing, monitoring, or recording as a stream */ +/* the *_fallback functions try to open /dev/dsp if there's no EsounD */ +int esd_play_stream( esd_format_t format, int rate, + const char *host, const char *name ); +int esd_play_stream_fallback( esd_format_t format, int rate, + const char *host, const char *name ); +int esd_monitor_stream( esd_format_t format, int rate, + const char *host, const char *name ); +/* int esd_monitor_stream_fallback( esd_format_t format, int rate ); */ +int esd_record_stream( esd_format_t format, int rate, + const char *host, const char *name ); +int esd_record_stream_fallback( esd_format_t format, int rate, + const char *host, const char *name ); +int esd_filter_stream( esd_format_t format, int rate, + const char *host, const char *name ); + +/* cache a sample in the server returns sample id, < 0 = error */ +int esd_sample_cache( int esd, esd_format_t format, int rate, + int length, const char *name ); +int esd_confirm_sample_cache( int esd ); + +/* get the sample id for an already-cached sample */ +int esd_sample_getid( int esd, const char *name); + +/* uncache a sample in the server */ +int esd_sample_free( int esd, int sample ); + +/* play a cached sample once */ +int esd_sample_play( int esd, int sample ); +/* make a cached sample loop */ +int esd_sample_loop( int esd, int sample ); + +/* stop the looping sample at end */ +int esd_sample_stop( int esd, int sample ); +/* stop a playing sample immed. */ +int esd_sample_kill( int esd, int sample ); + +/* closes fd, previously obtained by esd_open */ +int esd_close( int esd ); + + +/*******************************************************************/ +/* esdmgr.c - functions to implement a "sound manager" for esd */ + +/* structures to retrieve information about streams/samples from the server */ +typedef struct esd_server_info { + + int version; /* server version encoded as an int */ + esd_format_t format; /* magic int with the format info */ + int rate; /* sample rate */ + +} esd_server_info_t; + +typedef struct esd_player_info { + + struct esd_player_info *next; /* point to next entry in list */ + esd_server_info_t *server; /* the server that contains this stream */ + + int source_id; /* either a stream fd or sample id */ + char name[ ESD_NAME_MAX ]; /* name of stream for remote control */ + int rate; /* sample rate */ + int left_vol_scale; /* volume scaling */ + int right_vol_scale; + + esd_format_t format; /* magic int with the format info */ + +} esd_player_info_t; + +typedef struct esd_sample_info { + + struct esd_sample_info *next; /* point to next entry in list */ + esd_server_info_t *server; /* the server that contains this sample */ + + int sample_id; /* either a stream fd or sample id */ + char name[ ESD_NAME_MAX ]; /* name of stream for remote control */ + int rate; /* sample rate */ + int left_vol_scale; /* volume scaling */ + int right_vol_scale; + + esd_format_t format; /* magic int with the format info */ + int length; /* total buffer length */ + +} esd_sample_info_t; + +typedef struct esd_info { + + esd_server_info_t *server; + esd_player_info_t *player_list; + esd_sample_info_t *sample_list; + +} esd_info_t; + +enum esd_standby_mode { + ESM_ERROR, ESM_ON_STANDBY, ESM_ON_AUTOSTANDBY, ESM_RUNNING +}; +typedef int esd_standby_mode_t; + +/* define callbacks for esd_update_info() */ +/* what to do when a stream connects, or sample is played */ +typedef int esd_new_player_callback_t( esd_player_info_t * ); +/* what to do when a stream disconnects, or sample stops playing */ +typedef int esd_old_player_callback_t( esd_player_info_t * ); +/* what to do when a sample is cached */ +typedef int esd_new_sample_callback_t( esd_sample_info_t * ); +/* what to do when a sample is uncached */ +typedef int esd_old_sample_callback_t( esd_sample_info_t * ); + +typedef struct esd_update_info_callbacks { + esd_new_player_callback_t *esd_new_player_callback; + esd_old_player_callback_t *esd_old_player_callback; + esd_new_sample_callback_t *esd_new_sample_callback; + esd_old_sample_callback_t *esd_old_sample_callback; +} esd_update_info_callbacks_t; + +/* print server into to stdout */ +void esd_print_server_info( esd_server_info_t *server_info ); +void esd_print_player_info( esd_player_info_t *player_info ); +void esd_print_sample_info( esd_sample_info_t *sample_info ); +/* print all info to stdout */ +void esd_print_all_info( esd_info_t *all_info ); + +/* retrieve server properties (sample rate, format, version number) */ +esd_server_info_t *esd_get_server_info( int esd ); +/* release all memory allocated for the server properties structure */ +void esd_free_server_info( esd_server_info_t *server_info ); + +/* retrieve all information from server */ +esd_info_t *esd_get_all_info( int esd ); + +/* retrieve all information from server, and update until unsubsribed or closed */ +esd_info_t *esd_subscribe_all_info( int esd ); + +/* call to update the info structure with new information, and call callbacks */ +esd_info_t *esd_update_info( int esd, esd_info_t *info, + esd_update_info_callbacks_t *callbacks ); +esd_info_t *esd_unsubscribe_info( int esd ); + +/* release all memory allocated for the esd info structure */ +void esd_free_all_info( esd_info_t *info ); + + +/* reset the volume panning for a stream */ +int esd_set_stream_pan( int esd, int stream_id, + int left_scale, int right_scale ); + +/* reset the default volume panning for a sample */ +int esd_set_default_sample_pan( int esd, int sample_id, + int left_scale, int right_scale ); + +/* see if the server is in stnaby, autostandby, etc */ +esd_standby_mode_t esd_get_standby_mode( int esd ); + + +/*******************************************************************/ +/* esdfile.c - audiofile wrappers for sane handling of files */ + +int esd_send_file( int esd, AFfilehandle au_file, int frame_length ); +int esd_play_file( const char *name_prefix, const char *filename, int fallback ); +int esd_file_cache( int esd, const char *name_prefix, const char *filename ); + + +/*******************************************************************/ +/* audio.c - abstract the sound hardware for cross platform usage */ +extern esd_format_t esd_audio_format; +extern int esd_audio_rate; +extern char *esd_audio_device; + +const char *esd_audio_devices( void ); +int esd_audio_open( void ); +void esd_audio_close( void ); +void esd_audio_pause( void ); +int esd_audio_write( void *buffer, int buf_size ); +int esd_audio_read( void *buffer, int buf_size ); +void esd_audio_flush( void ); + +#ifdef __cplusplus +} +#endif + + +#endif /* #ifndef ESD_H */ diff --git a/src/contrib/esdout/esdout_plugin.cpp b/src/contrib/esdout/esdout_plugin.cpp new file mode 100644 index 000000000..ab2d337cd --- /dev/null +++ b/src/contrib/esdout/esdout_plugin.cpp @@ -0,0 +1,71 @@ +////////////////////////////////////////////////////////////////////////////// +// +// License Agreement: +// +// The following are Copyright © 2009, Julian Cromarty +// +// 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 author nor the names of other 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. +// +////////////////////////////////////////////////////////////////////////////// + +#include "pch.h" + +#include +#include "EsdOut.h" + +class EsdOutPlugin : public musik::core::IPlugin +{ + void Destroy() { delete this; }; + + const utfchar* Name() { return TEXT("EsdOut output plugin"); }; + const utfchar* Version() { return TEXT("0.1"); }; + const utfchar* Author() { return TEXT("Julian Cromarty"); }; +}; + +extern "C" { + musik::core::IPlugin* GetPlugin() + { + return new EsdOutPlugin(); + } +} + +/* +extern "C" { + musik::core::audio::IAudioOutputSupplier* CreateAudioOutputSupplier() + { + return new AlsaOutSupplier(); + } +}*/ + +extern "C" { + musik::core::audio::IOutput* GetAudioOutput() + { + return new EsdOut(); + } +} diff --git a/src/contrib/esdout/pch.h b/src/contrib/esdout/pch.h new file mode 100644 index 000000000..da94a0703 --- /dev/null +++ b/src/contrib/esdout/pch.h @@ -0,0 +1,43 @@ +////////////////////////////////////////////////////////////////////////////// +// +// License Agreement: +// +// The following are Copyright � 2008, Bj�rn Olievier +// +// 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 author nor the names of other 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. +// +////////////////////////////////////////////////////////////////////////////// + +// Precompiled headers +#pragma once + +#include +#include + +#include "esd.h" diff --git a/src/contrib/mpg123decoder/CMakeLists.txt b/src/contrib/mpg123decoder/CMakeLists.txt index f980f6fe8..ba8b15369 100644 --- a/src/contrib/mpg123decoder/CMakeLists.txt +++ b/src/contrib/mpg123decoder/CMakeLists.txt @@ -21,6 +21,6 @@ add_definitions( ) add_library( mpg123decoder SHARED ${mpg123decoder_SOURCES} ) -target_link_libraries( mpg123decoder ${musikCube_LINK_LIBS}) +target_link_libraries( mpg123decoder ${musikCube_LINK_LIBS} mpg123) diff --git a/src/contrib/stdout/StdOut.cpp b/src/contrib/stdout/StdOut.cpp index 1e0b4a154..46d81b7a2 100644 --- a/src/contrib/stdout/StdOut.cpp +++ b/src/contrib/stdout/StdOut.cpp @@ -38,7 +38,7 @@ StdOut::StdOut() ,currentVolume(1.0) ,addToRemovedBuffers(false) ,device("default") - ,output(NULL) + ,output(stdout) { #ifdef _DEBUG std::cerr << "StdOut::StdOut() called" << std::endl; diff --git a/src/contrib/stdout/StdOut.h b/src/contrib/stdout/StdOut.h index 5cf88c583..b274b0ec2 100644 --- a/src/contrib/stdout/StdOut.h +++ b/src/contrib/stdout/StdOut.h @@ -71,6 +71,10 @@ class StdOut : public IOutput{ protected: friend class StdOutBuffer; + // Audio stuff + void* waveHandle; + FILE* output; + // Current format int currentChannels; long currentSampleRate;