#include #include EndpointCallback::EndpointCallback(Endpoint* ep){ this->ep = ep; } ULONG EndpointCallback::AddRef(){ return InterlockedIncrement(&ref); } ULONG EndpointCallback::Release(){ ULONG tempRef = InterlockedDecrement(&ref); if (tempRef == 0) { delete this; } return tempRef; } HRESULT EndpointCallback::QueryInterface(REFIID riid, VOID **ppvInterface) { if (IID_IUnknown == riid) { AddRef(); *ppvInterface = (IUnknown*)this; } else if (__uuidof(IAudioEndpointVolumeCallback) == riid) { AddRef(); *ppvInterface = (IAudioEndpointVolumeCallback*)this; } else { *ppvInterface = NULL; return E_NOINTERFACE; } return S_OK; } HRESULT EndpointCallback::OnNotify(PAUDIO_VOLUME_NOTIFICATION_DATA pNotify) { if (pNotify == NULL) return E_INVALIDARG; float extraChannelVol[pNotify->nChannels]; bool multiChannel = false; AUDIO_VOLUME_NOTIFICATION_DATA eventData = *pNotify; if(pNotify->nChannels > 1) { multiChannel = true; for (UINT i = 0; i < pNotify->nChannels; i++){ extraChannelVol[i] = pNotify->afChannelVolumes[i]; } } NGuid* guid = osh->getGuid(); if (memcmp(guid, &eventData, sizeof(*guid)) == 0) { log_debugcpp("Onnanokotify says You Shall Not Update Thy Interface."); } else { log_debugcpp("Onnanokotify says Stored: " << guid->data1); log_debugcpp("Onnanokotify says Grace of God: " << eventData.guidEventContext.Data1); osh->updateMuteCallback(this->ep->getIndex(), eventData.bMuted); osh->updateVolumeCallback(this->ep->getIndex(), AudioChannel::CHANNEL_MAIN ,eventData.fMasterVolume); log_debugcpp("Onnanokotify says Reported Channel Qty: " << eventData.nChannels); if(multiChannel) for(UINT i = 0; i < eventData.nChannels; i++) { osh->updateVolumeCallback(this->ep->getIndex(), (uint32_t)i, extraChannelVol[i]); } else osh->updateVolumeCallback(this->ep->getIndex(), (uint32_t)0, pNotify->afChannelVolumes[0]); } return S_OK; } /* EndpointCallback::~EndpointCallback(){ * PAUDIO_VOLUME_NOTIFICATION_DATA->Release(); * } */ Endpoint::Endpoint(IMMDevice* ep, uint64_t idx){ this->endpoint = ep; this->idx = idx; if(FAILED(endpoint->Activate(IID_IAudioEndpointVolume, CLSCTX_ALL, NULL, (void**)&endpointVolume))) { log_debugcpp("si"); }; if (FAILED(endpointVolume->GetChannelCount(&channelCount))) log_debugcpp("get channel count fail"); //Obtaining friendly name: IPropertyStore creates PROPVARIANT per field // hr = endpointPtr->GetId(&endpointID); endpoint->OpenPropertyStore(STGM_READ, &properties); PROPVARIANT pv; properties->GetValue(PKEY_Device_FriendlyName , &pv); friendlyName = std::wstring(pv.pwszVal); } void Endpoint::setIndex(uint64_t idx){ this->idx = idx; } uint64_t Endpoint::getIndex(){ return idx; } std::wstring Endpoint::getName(){ return friendlyName; } float Endpoint::getVolume(int channel){ float volume; if (channel == ENDPOINT_MASTER_VOLUME) { if(FAILED(endpointVolume->GetMasterVolumeLevelScalar(&volume))) { log_debugcpp("si");} } else { if(FAILED(endpointVolume->GetChannelVolumeLevelScalar(channel, &volume))) { log_debugcpp("si");} } return volume; } uint32_t Endpoint::getChannelCount(){ return (uint32_t)channelCount; } bool Endpoint::getMute(){ BOOL mut; if(FAILED(endpointVolume->GetMute(&mut))) { log_debugcpp("si"); } log_debugcpp("back BOOL is " << mut); bool mute = (bool)mut; log_debugcpp("translate to bool " << mute); return mute; } /* * float Endpoint::getLeftChannelVolume(){ * float volume; * if(FAILED(endpointVolume-> GetChannelVolumeLevelScalar(0, &volume)) { log_debugcpp("si"); } ); * return volume; * } * * float Endpoint::getRightChannelVolume(){ * float volume; * if(FAILED(endpointVolume-> GetChannelVolumeLevelScalar(1, &volume)) { log_debugcpp("si");} * return volume; * } */ void Endpoint::setVolume(NGuid* guid, int channel, float volume) { GUID tempMsGuid = NGuidToGUID(guid); if (channel == AudioChannel::CHANNEL_MAIN) { if(FAILED(endpointVolume->SetMasterVolumeLevelScalar(volume, &tempMsGuid))) { log_debugcpp("MASTER VOLUME FAILED"); }; } else { log_debugcpp("Windows: Channel being updated: " << channel); if(FAILED(endpointVolume->SetChannelVolumeLevelScalar(channel, volume, &tempMsGuid))) { log_debugcpp("CHANNEL "<< channel <<" VOLUME FAILED"); }; } } void Endpoint::setMute(NGuid* guid, bool muted) { //BOOL mut; //log_debugcpp("bool mute arrives as " << mut); //if(FAILED(endpointVolume->GetMute(&mut))) { log_debugcpp("si"); } //log_debugcpp("translate to BOOL as " << mut); //TODO: use new funcs GUID tempMsGuid = NGuidToGUID(guid); if(FAILED(endpointVolume->SetMute(muted, &tempMsGuid))) { log_debugcpp("MUTE FAILED"); }; } void Endpoint::setCallback(EndpointCallback *epc){ endpointVolume->RegisterControlChangeNotify((IAudioEndpointVolumeCallback*)epc); } void Endpoint::removeCallback(EndpointCallback *epc){ endpointVolume->UnregisterControlChangeNotify((IAudioEndpointVolumeCallback*)epc); } Endpoint::~Endpoint(){ log_debugcpp("cum"); properties->Release(); endpointVolume->Release(); endpoint->Release(); } void Overseer::initCOMLibrary() { if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE))) { log_debugcpp("si"); }; //Retrieving endpoint enumerator //MMDeviceEnumerator es el CLSID de toda la vaina de MMDevicear if(FAILED(CoCreateInstance( __uuidof(MMDeviceEnumerator), NULL, CLSCTX_ALL, __uuidof(IMMDeviceEnumerator), (void**)&deviceEnumerator)) ) { log_debugcpp("si"); }; GUID tempGuid; if(FAILED(CoCreateGuid(&tempGuid))) { log_debugcpp("Failed to obtain GUID: " ); }; this->guid = GUIDToNGuid(&tempGuid); //TODO: Release lpguid? //TODO: Uninitialize COM } void Overseer::reloadEndpoints() { IMMDeviceCollection *deviceCollection; // | DEVICE_STATE_DISABLED | DEVICE_STATE_NOTPRESENT | DEVICE_STATE_UNPLUGGED if(FAILED(deviceEnumerator->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &deviceCollection) )) { log_debugcpp("si"); }; //Counting them if(FAILED(deviceCollection->GetCount(&numPlaybackEndpoints))) { log_debugcpp("si");}; if(numPlaybackEndpoints == 0) { log_debugcpp("si"); }; //Retrieving actual endpoints and storing them on their own class for (unsigned int i = 0; i < numPlaybackEndpoints; i++){ IMMDevice *temp; if(deviceCollection->Item(i, &temp) != 0) { log_debugcpp("si"); }; Endpoint *endpoint = new Endpoint(temp, i); //endpoint->setIndex(i); this->playbackDevices.push_back(endpoint); //TODO: le porblemx std::cout << "ola" << std::endl; } deviceCollection->Release(); } Overseer::Overseer(){ //Initializing COM library log_debugcpp("Initializing Overseer"); initCOMLibrary(); //Obtaining playback endpoint collection on this point in time reloadEndpoints(); } //Overseer::int getDefaultPlaybackEndpoint(Endpoint** defaultEndpoint){ //if (FAILED(deviceEnumerator->GetDefaultAudioEndpoint(eRender, eConsole, &endpointPtr))) // return 1; //return 0; //} //int Overseer::getDefaultCaptureEndpoint(Endpoint** defaultEndpoint); //TODO guid NGuid* Overseer::getGuid() { return &guid; } std::vector Overseer::getPlaybackEndpoints() { return playbackDevices; } Overseer::~Overseer(){ log_debugcpp("cum"); deviceEnumerator->Release(); for(unsigned long long i = 0; i < playbackDevices.size(); i++){ delete(playbackDevices.at(i)); } } //int Overseer::getCaptureEndpoints(std::vector *captureEndpoints); //IMMDeviceEnumerator** Overseer::setOrigin();