| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 | 
							- /*
 
-  * openmpt123_pulseaudio.hpp
 
-  * -------------------------
 
-  * Purpose: libopenmpt command line player
 
-  * Notes  : (currently none)
 
-  * Authors: OpenMPT Devs
 
-  * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
 
-  */
 
- #ifndef OPENMPT123_PULSEAUDIO_HPP
 
- #define OPENMPT123_PULSEAUDIO_HPP
 
- #include "openmpt123_config.hpp"
 
- #include "openmpt123.hpp"
 
- #if defined(MPT_WITH_PULSEAUDIO)
 
- #include <pulse/pulseaudio.h>
 
- #include <pulse/simple.h>
 
- namespace openmpt123 {
 
- struct pulseaudio_exception : public exception {
 
- 	static std::string error_to_string( int error ) {
 
- 		try {
 
- 			if ( error == 0 ) {
 
- 				return std::string();
 
- 			}
 
- 			std::ostringstream e;
 
- 			const char * str = pa_strerror( error );
 
- 			if ( !str ) {
 
- 				e << "error=" << error;
 
- 				return e.str();
 
- 			}
 
- 			if ( std::strlen(str) == 0 ) {
 
- 				e << "error=" << error;
 
- 				return e.str();
 
- 			}
 
- 			e << str << " (error=" << error << ")";
 
- 			return e.str();
 
- 		} catch ( const std::bad_alloc & ) {
 
- 			return std::string();
 
- 		}
 
- 	}
 
- 	pulseaudio_exception( int error ) : exception( error_to_string( error ) ) { }
 
- };
 
- class pulseaudio_stream_raii : public write_buffers_interface {
 
- private:
 
- 	pa_simple * stream;
 
- 	std::size_t channels;
 
- 	std::size_t sampleSize;
 
- 	std::vector<float> sampleBufFloat;
 
- 	std::vector<std::int16_t> sampleBufInt;
 
- public:
 
- 	pulseaudio_stream_raii( commandlineflags & flags, std::ostream & /* log */ )
 
- 		: stream(NULL)
 
- 		, channels(flags.channels)
 
- 		, sampleSize(flags.use_float ? sizeof( float ) : sizeof( std::int16_t ))
 
- 	{
 
- 		int error = 0;
 
- 		pa_sample_spec ss;
 
- 		std::memset( &ss, 0, sizeof( pa_sample_spec ) );
 
- 		ss.format = ( flags.use_float ? PA_SAMPLE_FLOAT32 : PA_SAMPLE_S16NE );
 
- 		ss.rate = flags.samplerate;
 
- 		ss.channels = flags.channels;
 
- 		pa_buffer_attr ba;
 
- 		std::memset( &ba, 0, sizeof( pa_buffer_attr ) );
 
- 		bool use_ba = false;
 
- 		if ( flags.buffer != default_high && flags.buffer != default_low ) {
 
- 			use_ba = true;
 
- 			ba.maxlength = channels * sampleSize * ( flags.buffer * flags.samplerate / 1000 );
 
- 		} else {
 
- 			ba.maxlength = static_cast<std::uint32_t>(-1);
 
- 		}
 
- 		if ( flags.period != default_high && flags.period != default_low ) {
 
- 			use_ba = true;
 
- 			ba.minreq = channels * sampleSize * ( flags.period * flags.samplerate / 1000 );
 
- 			if ( ba.maxlength != static_cast<std::uint32_t>(-1) ) {
 
- 				ba.tlength = ba.maxlength - ba.minreq;
 
- 				ba.prebuf = ba.tlength;
 
- 			} else {
 
- 				ba.tlength = static_cast<std::uint32_t>(-1);
 
- 				ba.prebuf = static_cast<std::uint32_t>(-1);
 
- 			}
 
- 		} else {
 
- 			ba.minreq = static_cast<std::uint32_t>(-1);
 
- 			ba.tlength = static_cast<std::uint32_t>(-1);
 
- 			ba.prebuf = static_cast<std::uint32_t>(-1);
 
- 		}
 
- 		ba.fragsize = 0;
 
- 		flags.apply_default_buffer_sizes();
 
- 		sampleBufFloat.resize( channels * ( flags.ui_redraw_interval * flags.samplerate / 1000 ) );
 
- 		sampleBufInt.resize( channels * ( flags.ui_redraw_interval * flags.samplerate / 1000 ) );
 
- 		stream = pa_simple_new( NULL, "openmpt123", PA_STREAM_PLAYBACK, NULL, "openmpt123", &ss, NULL, ( use_ba ? &ba : NULL ), &error );
 
- 		if ( !stream ) {
 
- 			throw pulseaudio_exception( error );
 
- 		}
 
- 	}
 
- 	~pulseaudio_stream_raii() {
 
- 		int error = 0;
 
- 		if ( stream ) {
 
- 			error = 0;
 
- 			if ( pa_simple_drain( stream, &error ) < 0 ) {
 
- 				// throw pulseaudio_exception( error );
 
- 			}
 
- 			pa_simple_free( stream );
 
- 			stream = NULL;
 
- 		}
 
- 	}
 
- private:
 
- 	template<typename Tsample>
 
- 	void write_frames( const Tsample * buffer, std::size_t frames ) {
 
- 		int error = 0;
 
- 		if ( pa_simple_write( stream, buffer, frames * channels * sampleSize, &error ) < 0 ) {
 
- 			throw pulseaudio_exception( error );
 
- 		}
 
- 	}
 
- public:
 
- 	void write( const std::vector<float*> buffers, std::size_t frames ) override {
 
- 		sampleBufFloat.clear();
 
- 		for ( std::size_t frame = 0; frame < frames; ++frame ) {
 
- 			for ( std::size_t channel = 0; channel < channels; ++channel ) {
 
- 				sampleBufFloat.push_back( buffers[channel][frame] );
 
- 			}
 
- 		}
 
- 		write_frames( sampleBufFloat.data(), frames );
 
- 	}
 
- 	void write( const std::vector<std::int16_t*> buffers, std::size_t frames ) override {
 
- 		sampleBufInt.clear();
 
- 		for ( std::size_t frame = 0; frame < frames; ++frame ) {
 
- 			for ( std::size_t channel = 0; channel < channels; ++channel ) {
 
- 				sampleBufInt.push_back( buffers[channel][frame] );
 
- 			}
 
- 		}
 
- 		write_frames( sampleBufInt.data(), frames );
 
- 	}
 
- 	bool unpause() override {
 
- 		return true;
 
- 	}
 
- 	bool pause() override {
 
- 		int error = 0;
 
- 		error = 0;
 
- 		if ( pa_simple_drain( stream, &error ) < 0 ) {
 
- 			throw pulseaudio_exception( error );
 
- 		}
 
- 		return true;
 
- 	}
 
- 	bool sleep( int ms ) override {
 
- 		pa_msleep( ms );
 
- 		return true;
 
- 	}
 
- };
 
- static std::string show_pulseaudio_devices( std::ostream & /* log */ ) {
 
- 	std::ostringstream devices;
 
- 	devices << " pulseaudio:" << std::endl;
 
- 	devices << "    " << "0" << ": Default Device" << std::endl;
 
- 	return devices.str();
 
- }
 
- } // namespace openmpt123
 
- #endif // MPT_WITH_PULSEAUDIO
 
- #endif // OPENMPT123_PULSEAUDIO_HPP
 
 
  |