cannam@124: #include "portaudiocpp/System.hxx"
cannam@124: 
cannam@124: #include <cstddef>
cannam@124: #include <cassert>
cannam@124: 
cannam@124: #include "portaudiocpp/HostApi.hxx"
cannam@124: #include "portaudiocpp/Device.hxx"
cannam@124: #include "portaudiocpp/Stream.hxx"
cannam@124: #include "portaudiocpp/Exception.hxx"
cannam@124: #include "portaudiocpp/SystemHostApiIterator.hxx"
cannam@124: #include "portaudiocpp/SystemDeviceIterator.hxx"
cannam@124: 
cannam@124: namespace portaudio
cannam@124: {
cannam@124: 	// -----------------------------------------------------------------------------------
cannam@124: 
cannam@124: 	// Static members:
cannam@124: 	System *System::instance_ = NULL;
cannam@124: 	int System::initCount_ = 0;
cannam@124: 	HostApi **System::hostApis_ = NULL;
cannam@124: 	Device **System::devices_ = NULL;
cannam@124: 	Device *System::nullDevice_ = NULL;
cannam@124: 
cannam@124: 	// -----------------------------------------------------------------------------------
cannam@124: 
cannam@124: 	int System::version()
cannam@124: 	{
cannam@124: 		return Pa_GetVersion();
cannam@124: 	}
cannam@124: 
cannam@124: 	const char *System::versionText()
cannam@124: 	{
cannam@124: 		return Pa_GetVersionText();
cannam@124: 	}
cannam@124: 
cannam@124: 	void System::initialize()
cannam@124: 	{
cannam@124: 		++initCount_;
cannam@124: 
cannam@124: 		if (initCount_ == 1)
cannam@124: 		{
cannam@124: 			// Create singleton:
cannam@124: 			assert(instance_ == NULL);
cannam@124: 			instance_ = new System();
cannam@124: 
cannam@124: 			// Initialize the PortAudio system:
cannam@124: 			{
cannam@124: 				PaError err = Pa_Initialize();
cannam@124: 
cannam@124: 				if (err != paNoError)
cannam@124: 					throw PaException(err);
cannam@124: 			}
cannam@124: 
cannam@124: 			// Create and populate device array:
cannam@124: 			{
cannam@124: 				int numDevices = instance().deviceCount();
cannam@124: 
cannam@124: 				devices_ = new Device*[numDevices];
cannam@124: 
cannam@124: 				for (int i = 0; i < numDevices; ++i)
cannam@124: 					devices_[i] = new Device(i);
cannam@124: 			}
cannam@124: 
cannam@124: 			// Create and populate host api array:
cannam@124: 			{
cannam@124: 				int numHostApis = instance().hostApiCount();
cannam@124: 
cannam@124: 				hostApis_ = new HostApi*[numHostApis];
cannam@124: 
cannam@124: 				for (int i = 0; i < numHostApis; ++i)
cannam@124: 					hostApis_[i] = new HostApi(i);
cannam@124: 			}
cannam@124: 			
cannam@124: 			// Create null device:
cannam@124: 			nullDevice_ = new Device(paNoDevice);
cannam@124: 		}
cannam@124: 	}
cannam@124: 
cannam@124: 	void System::terminate()
cannam@124: 	{
cannam@124: 		PaError err = paNoError;
cannam@124: 
cannam@124: 		if (initCount_ == 1)
cannam@124: 		{
cannam@124: 			// Destroy null device:
cannam@124: 			delete nullDevice_;
cannam@124: 
cannam@124: 			// Destroy host api array:
cannam@124: 			{
cannam@124: 				if (hostApis_ != NULL)
cannam@124: 				{
cannam@124: 					int numHostApis = instance().hostApiCount();
cannam@124: 
cannam@124: 					for (int i = 0; i < numHostApis; ++i)
cannam@124: 						delete hostApis_[i];
cannam@124: 
cannam@124: 					delete[] hostApis_;
cannam@124: 					hostApis_ = NULL;
cannam@124: 				}
cannam@124: 			}
cannam@124: 
cannam@124: 			// Destroy device array:
cannam@124: 			{
cannam@124: 				if (devices_ != NULL)
cannam@124: 				{
cannam@124: 					int numDevices = instance().deviceCount();
cannam@124: 
cannam@124: 					for (int i = 0; i < numDevices; ++i)
cannam@124: 						delete devices_[i];
cannam@124: 
cannam@124: 					delete[] devices_;
cannam@124: 					devices_ = NULL;
cannam@124: 				}
cannam@124: 			}
cannam@124: 
cannam@124: 			// Terminate the PortAudio system:
cannam@124: 			assert(instance_ != NULL);
cannam@124: 			err = Pa_Terminate();
cannam@124: 
cannam@124: 			// Destroy singleton:
cannam@124: 			delete instance_;
cannam@124: 			instance_ = NULL;
cannam@124: 		}
cannam@124: 
cannam@124: 		if (initCount_ > 0)
cannam@124: 			--initCount_;
cannam@124: 
cannam@124: 		if (err != paNoError)
cannam@124: 			throw PaException(err);
cannam@124: 	}
cannam@124: 
cannam@124: 
cannam@124: 	System &System::instance()
cannam@124: 	{
cannam@124: 		assert(exists());
cannam@124: 
cannam@124: 		return *instance_;
cannam@124: 	}
cannam@124: 
cannam@124: 	bool System::exists()
cannam@124: 	{
cannam@124: 		return (instance_ != NULL);
cannam@124: 	}
cannam@124: 
cannam@124: 	// -----------------------------------------------------------------------------------
cannam@124: 
cannam@124: 	System::HostApiIterator System::hostApisBegin()
cannam@124: 	{
cannam@124: 		System::HostApiIterator tmp;
cannam@124: 		tmp.ptr_ = &hostApis_[0]; // begin (first element)
cannam@124: 		return tmp;
cannam@124: 	}
cannam@124: 
cannam@124: 	System::HostApiIterator System::hostApisEnd()
cannam@124: 	{
cannam@124: 		int count = hostApiCount();
cannam@124: 
cannam@124: 		System::HostApiIterator tmp;
cannam@124: 		tmp.ptr_ = &hostApis_[count]; // end (one past last element)
cannam@124: 		return tmp;
cannam@124: 	}
cannam@124: 
cannam@124: 	HostApi &System::defaultHostApi()
cannam@124: 	{
cannam@124: 		PaHostApiIndex defaultHostApi = Pa_GetDefaultHostApi();
cannam@124: 
cannam@124: 		if (defaultHostApi < 0)
cannam@124: 			throw PaException(defaultHostApi);
cannam@124: 
cannam@124: 		return *hostApis_[defaultHostApi];
cannam@124: 	}
cannam@124: 
cannam@124: 	HostApi &System::hostApiByTypeId(PaHostApiTypeId type)
cannam@124: 	{
cannam@124: 		PaHostApiIndex index = Pa_HostApiTypeIdToHostApiIndex(type);
cannam@124: 
cannam@124: 		if (index < 0)
cannam@124: 			throw PaException(index);
cannam@124: 
cannam@124: 		return *hostApis_[index];
cannam@124: 	}
cannam@124: 
cannam@124: 	HostApi &System::hostApiByIndex(PaHostApiIndex index)
cannam@124: 	{
cannam@124: 		if (index < 0 || index >= hostApiCount())
cannam@124: 			throw PaException(paInternalError);
cannam@124: 
cannam@124: 		return *hostApis_[index];
cannam@124: 	}
cannam@124: 
cannam@124: 	int System::hostApiCount()
cannam@124: 	{
cannam@124: 		PaHostApiIndex count = Pa_GetHostApiCount();
cannam@124: 
cannam@124: 		if (count < 0)
cannam@124: 			throw PaException(count);
cannam@124: 
cannam@124: 		return count;
cannam@124: 	}
cannam@124: 
cannam@124: 	// -----------------------------------------------------------------------------------
cannam@124: 
cannam@124: 	System::DeviceIterator System::devicesBegin()
cannam@124: 	{
cannam@124: 		DeviceIterator tmp;
cannam@124: 		tmp.ptr_ = &devices_[0];
cannam@124: 
cannam@124: 		return tmp;
cannam@124: 	}
cannam@124: 
cannam@124: 	System::DeviceIterator System::devicesEnd()
cannam@124: 	{
cannam@124: 		int count = deviceCount();
cannam@124: 
cannam@124: 		DeviceIterator tmp;
cannam@124: 		tmp.ptr_ = &devices_[count];
cannam@124: 
cannam@124: 		return tmp;
cannam@124: 	}
cannam@124: 
cannam@124: 	//////
cannam@124: 	/// Returns the System's default input Device, or the null Device if none 
cannam@124: 	/// was available.
cannam@124: 	//////
cannam@124: 	Device &System::defaultInputDevice()
cannam@124: 	{
cannam@124: 		PaDeviceIndex index = Pa_GetDefaultInputDevice();
cannam@124: 		return deviceByIndex(index);
cannam@124: 	}
cannam@124: 
cannam@124: 	//////
cannam@124: 	/// Returns the System's default output Device, or the null Device if none 
cannam@124: 	/// was available.
cannam@124: 	//////
cannam@124: 	Device &System::defaultOutputDevice()
cannam@124: 	{
cannam@124: 		PaDeviceIndex index = Pa_GetDefaultOutputDevice();
cannam@124: 		return deviceByIndex(index);
cannam@124: 	}
cannam@124: 
cannam@124: 	//////
cannam@124: 	/// Returns the Device for the given index.
cannam@124: 	/// Will throw a paInternalError equivalent PaException if the given index 
cannam@124: 	/// is out of range.
cannam@124: 	//////
cannam@124: 	Device &System::deviceByIndex(PaDeviceIndex index)
cannam@124: 	{
cannam@124: 		if (index < -1 || index >= deviceCount())
cannam@124: 		{
cannam@124: 			throw PaException(paInternalError);
cannam@124: 		}
cannam@124: 
cannam@124: 		if (index == -1)
cannam@124: 			return System::instance().nullDevice();
cannam@124: 
cannam@124: 		return *devices_[index];
cannam@124: 	}
cannam@124: 
cannam@124: 	int System::deviceCount()
cannam@124: 	{
cannam@124: 		PaDeviceIndex count = Pa_GetDeviceCount();
cannam@124: 
cannam@124: 		if (count < 0)
cannam@124: 			throw PaException(count);
cannam@124: 
cannam@124: 		return count;
cannam@124: 	}
cannam@124: 
cannam@124: 	Device &System::nullDevice()
cannam@124: 	{
cannam@124: 		return *nullDevice_;
cannam@124: 	}
cannam@124: 
cannam@124: 	// -----------------------------------------------------------------------------------
cannam@124: 
cannam@124: 	void System::sleep(long msec)
cannam@124: 	{
cannam@124: 		Pa_Sleep(msec);
cannam@124: 	}
cannam@124: 
cannam@124: 	int System::sizeOfSample(PaSampleFormat format)
cannam@124: 	{
cannam@124: 		PaError err = Pa_GetSampleSize(format);
cannam@124: 		if (err < 0)
cannam@124: 		{
cannam@124: 			throw PaException(err);
cannam@124: 			return 0;
cannam@124: 		}
cannam@124: 
cannam@124: 		return err;
cannam@124: 	}
cannam@124: 
cannam@124: 	// -----------------------------------------------------------------------------------
cannam@124: 
cannam@124: 	System::System()
cannam@124: 	{
cannam@124: 		// (left blank intentionally)
cannam@124: 	}
cannam@124: 
cannam@124: 	System::~System()
cannam@124: 	{
cannam@124: 		// (left blank intentionally)
cannam@124: 	}
cannam@124: 
cannam@124: 	// -----------------------------------------------------------------------------------
cannam@124: 
cannam@124: } // namespace portaudio
cannam@124: