void XCriticalSection::Initialize() { if (m_isDestroyed) { CLog::Log(LOGWARNING, "CRITSEC[%p]: Trying to initialize destroyed section.", (void *)this); return; } if (m_isInitialized) { CLog::Log(LOGWARNING, "CRITSEC[%p]: Trying to initialze initialized section.", (void *)this); return; } // Setup for recursive locks. pthread_mutexattr_t attr; SAFELY(pthread_mutexattr_init(&attr)); SAFELY(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)); // Create the mutexes SAFELY(pthread_mutex_init(&m_mutex, &attr)); SAFELY(pthread_mutex_init(&m_countMutex, &attr)); SAFELY(pthread_mutexattr_destroy(&attr)); m_isInitialized = true; }
bool PlexAudioDevice::computeDeviceSupportsDigital() { bool ret = false; OSStatus err = noErr; UInt32 paramSize = 0; // Retrieve all the output streams. SAFELY(AudioDeviceGetPropertyInfo(m_deviceID, 0, FALSE, kAudioDevicePropertyStreams, ¶mSize, NULL)); if (err == noErr) { int numStreams = paramSize / sizeof(AudioStreamID); AudioStreamID* pStreams = (AudioStreamID *)malloc(paramSize); SAFELY(AudioDeviceGetProperty(m_deviceID, 0, FALSE, kAudioDevicePropertyStreams, ¶mSize, pStreams)); if (err == noErr) { for (int i=0; i<numStreams && ret == false; i++) { if (computeStreamSupportsDigital(pStreams[i])) ret = true; } } free(pStreams); } return ret; }
PlexAudioDevice::PlexAudioDevice(AudioDeviceID deviceID) : m_deviceID(deviceID) , m_isValid(false) , m_supportsDigital(false) { UInt32 paramSize = 0; OSStatus err = noErr; // Retrieve the length of the device name. SAFELY(AudioDeviceGetPropertyInfo(deviceID, 0, false, kAudioDevicePropertyDeviceName, ¶mSize, NULL)); if (err == noErr) { // Retrieve the name of the device. char* pStrName = new char[paramSize]; pStrName[0] = '\0'; SAFELY(AudioDeviceGetProperty(deviceID, 0, false, kAudioDevicePropertyDeviceName, ¶mSize, pStrName)); if (err == noErr) { m_deviceName = pStrName; // See if the device is writable (can output). m_hasOutput = computeHasOutput(); // If the device does have output, see if it supports digital. if (m_hasOutput) m_supportsDigital = computeDeviceSupportsDigital(); m_isValid = true; } delete[] pStrName; } }
bool PlexAudioDevice::computeStreamSupportsDigital(AudioStreamID streamID) { bool ret = false; OSStatus err = noErr; UInt32 paramSize = 0; // Retrieve all the stream formats supported by each output stream. SAFELY(AudioStreamGetPropertyInfo(streamID, 0, kAudioStreamPropertyPhysicalFormats, ¶mSize, NULL)); if (err == noErr) { int numFormats = paramSize / sizeof(AudioStreamBasicDescription); AudioStreamBasicDescription* pFormatList = (AudioStreamBasicDescription *)malloc(paramSize); SAFELY(AudioStreamGetProperty(streamID, 0, kAudioStreamPropertyPhysicalFormats, ¶mSize, pFormatList)); if (err == noErr) { for(int i=0; i<numFormats && ret == false; i++) { if (pFormatList[i].mFormatID == 'IAC3' || pFormatList[i].mFormatID == kAudioFormat60958AC3) ret = true; } } free(pFormatList); } return ret; }
void XCriticalSection::Enter() { if (m_isDestroyed) { #ifdef _DEBUG // This has to be a printf, otherwise we may recurse. printf("CRITSEC[%p]: Trying to enter destroyed section.\n", (void *)this); #endif return; } if (!m_isInitialized) { #ifdef _DEBUG // This has to be a printf, otherwise we may recurse. printf("CRITSEC[%p]: Trying to enter uninitialized section.\n", (void *)this); #endif return; } // Lock the mutex, bump the count. SAFELY(pthread_mutex_lock(&m_mutex)); pthread_mutex_lock(&m_countMutex); // Save the owner, bump the count. m_count++; m_ownerThread = GetCurrentThreadId(); #ifdef __APPLE__ m_ownerThreadMachPort = mach_thread_self(); #endif pthread_mutex_unlock(&m_countMutex); }
void XCriticalSection::Destroy() { if (m_isDestroyed) { CLog::Log(LOGWARNING, "CRITSEC[%p]: Trying to destroy destroyed section.", (void *)this); return; } if (!m_isInitialized) { CLog::Log(LOGWARNING, "CRITSEC[%p]: Trying to destroy uninitialized section.", (void *)this); return; } SAFELY(pthread_mutex_destroy(&m_mutex)); SAFELY(pthread_mutex_destroy(&m_countMutex)); m_isDestroyed = true; }
bool PlexAudioDevice::isAlive() { OSStatus err = noErr; UInt32 alive = 1; UInt32 paramSize = 0; paramSize = sizeof(alive); SAFELY(AudioDeviceGetProperty(m_deviceID, 0, FALSE, kAudioDevicePropertyDeviceIsAlive, ¶mSize, &alive)); return (alive != 0); }
void PlexAudioDevice::reset() { OSStatus err = noErr; UInt32 paramSize = 0; AudioStreamBasicDescription deviceFormat; // Set up the basic default format. deviceFormat.mSampleRate = 48000.0; deviceFormat.mFormatID = kAudioFormatLinearPCM; deviceFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; deviceFormat.mBitsPerChannel = 16; deviceFormat.mChannelsPerFrame = 2; deviceFormat.mFramesPerPacket = 1; deviceFormat.mBytesPerFrame = 4; deviceFormat.mBytesPerPacket = 4; deviceFormat.mReserved = 0; // Retrieve all the output streams. SAFELY(AudioDeviceGetPropertyInfo(m_deviceID, 0, FALSE, kAudioDevicePropertyStreams, ¶mSize, NULL)); if (err == noErr) { int numStreams = paramSize / sizeof(AudioStreamID); AudioStreamID* pStreams = (AudioStreamID *)malloc(paramSize); SAFELY(AudioDeviceGetProperty(m_deviceID, 0, FALSE, kAudioDevicePropertyStreams, ¶mSize, pStreams)); if (err == noErr) { for (int i=0; i<numStreams; i++) { // Change the format. SAFELY(AudioStreamSetProperty(pStreams[i], 0, 0, kAudioStreamPropertyPhysicalFormat, sizeof(AudioStreamBasicDescription), &deviceFormat)); } } free(pStreams); } }
PlexAudioDevicePtr PlexAudioDevices::FindDefault() { PlexAudioDevice* ret = 0; AudioDeviceID defaultDeviceID = 0; UInt32 paramSize = 0; OSStatus err = noErr; // Find the ID of the default Device. paramSize = sizeof(AudioDeviceID); SAFELY(AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, ¶mSize, &defaultDeviceID)); if (err == noErr) ret = new PlexAudioDevice(defaultDeviceID); return PlexAudioDevicePtr(ret); }
void XCriticalSection::Leave() { if (m_isDestroyed) { #ifdef _DEBUG printf("CRITSEC[%p]: Trying to leave destroyed section.\n", (void *)this); #endif return; } if (!m_isInitialized) { #ifdef _DEBUG printf("CRITSEC[%p]: Trying to leave uninitialized section.\n", (void *)this); #endif return; } if (!Owning()) { #ifdef _DEBUG printf("CRITSEC[%p]: Some other thread trying to leave our critical section.\n", (void *)this); #endif return; } pthread_mutex_lock(&m_countMutex); // Decrease the count, unlock mutex. if (m_count > 0) { m_count--; if(m_count == 0) m_ownerThread = 0; SAFELY(pthread_mutex_unlock(&m_mutex)); } else { #ifdef _DEBUG printf("RITSEC[%p]: Trying to leave, already left.\n", (void *)this); #endif } pthread_mutex_unlock(&m_countMutex); }
PlexAudioDevicesPtr PlexAudioDevices::FindAll() { OSStatus err = noErr; UInt32 paramSize = 0; PlexAudioDevices* audioDevices = new PlexAudioDevices(); // Get number of devices. SAFELY(AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, ¶mSize, NULL)); if (err == noErr) { int totalDeviceCount = paramSize / sizeof(AudioDeviceID); if (totalDeviceCount > 0) { CLog::Log(LOGDEBUG, "System has %ld device(s)", totalDeviceCount); // Allocate the device ID array and retreive them. AudioDeviceID* pDevices = (AudioDeviceID* )malloc(paramSize); SAFELY(AudioHardwareGetProperty( kAudioHardwarePropertyDevices, ¶mSize, pDevices)); if (err == noErr) { AudioDeviceID defaultDeviceID = 0; // Find the ID of the default Device. paramSize = sizeof(AudioDeviceID); SAFELY(AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, ¶mSize, &defaultDeviceID)); if (err == noErr) { for (int i=0; i<totalDeviceCount; i++) { PlexAudioDevicePtr audioDevice = PlexAudioDevicePtr(new PlexAudioDevice(pDevices[i])); // Add valid devices that support output. if (audioDevice->isValid() && audioDevice->hasOutput()) { audioDevices->m_audioDevices.push_back(audioDevice); // Set the default device. if (defaultDeviceID == pDevices[i]) audioDevices->m_defaultDevice = audioDevice; // Set the selected device. if (g_guiSettings.GetSetting("audiooutput.audiodevice") && g_guiSettings.GetString("audiooutput.audiodevice") == audioDevice->getName()) audioDevices->m_selectedDevice = audioDevice; } } // If we haven't selected any devices, select the default one. if (!audioDevices->m_selectedDevice) audioDevices->m_selectedDevice = audioDevices->m_defaultDevice; // Check if the selected device is alive and usable. if (audioDevices->m_selectedDevice->isAlive() == false) { CLog::Log(LOGWARNING, "Selected audio device [%s] is not alive, switching to default device", audioDevices->m_selectedDevice->getName().c_str()); audioDevices->m_selectedDevice = audioDevices->m_defaultDevice; } } } free(pDevices); } } // FIXME? Attach a Listener so that we are notified of a change in the Device setup. // AudioHardwareAddPropertyListener( kAudioHardwarePropertyDevices, HardwareListener, (void *)p_aout); return PlexAudioDevicesPtr(audioDevices); }
void PlexAudioDevice::setDefault() { OSStatus err = noErr; SAFELY(AudioHardwareSetProperty(kAudioHardwarePropertyDefaultOutputDevice, sizeof (UInt32), &m_deviceID)); }