Commit 3a823949 authored by Ghislain MARY's avatar Ghislain MARY

Allow build of WASAPI plugin for Windows desktop.

parent 21a6cf45
############################################################################
# CMakeLists.txt
# Copyright (C) 2014 Belledonne Communications, Grenoble France
#
############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
############################################################################
cmake_minimum_required(VERSION 3.0)
project(MSWASAPI CXX)
find_package(Mediastreamer2 REQUIRED)
include_directories(
${MEDIASTREAMER2_INCLUDE_DIRS}
)
file(GLOB SOURCE_FILES "*.h" "*.cpp")
set(LIBS ${MEDIASTREAMER2_LIBRARIES} ws2_32)
# TODO: For Windows Phone, link with phoneaudioses
if(ENABLE_STATIC)
add_library(mswasapi STATIC ${SOURCE_FILES})
else()
add_library(mswasapi SHARED ${SOURCE_FILES})
set_target_properties(mswasapi PROPERTIES VERSION 0)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Debug/libmswasapi.pdb
DESTINATION bin
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
endif()
set_target_properties(mswasapi PROPERTIES PREFIX "lib")
endif()
target_link_libraries(mswasapi ${LIBS})
install(TARGETS mswasapi
RUNTIME DESTINATION lib/mediastreamer/plugins
LIBRARY DESTINATION lib/mediastreamer/plugins
ARCHIVE DESTINATION lib/mediastreamer/plugins
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE
)
/*
mswasapi.c
mswasapi.cpp
mediastreamer2 library - modular sound and video processing and streaming
Windows Audio Session API sound card plugin for mediastreamer2
......@@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msfilter.h"
#include "mediastreamer2/mssndcard.h"
#include "mswasapi.h"
#include "mswasapi_reader.h"
#include "mswasapi_writer.h"
......@@ -32,6 +33,8 @@ const IID IID_IAudioClient2 = __uuidof(IAudioClient2);
const IID IID_IAudioCaptureClient = __uuidof(IAudioCaptureClient);
const IID IID_IAudioRenderClient = __uuidof(IAudioRenderClient);
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
/******************************************************************************
* Methods to (de)initialize and run the WASAPI sound capture filter *
......@@ -296,10 +299,21 @@ static void ms_wasapi_snd_card_detect(MSSndCardManager *m);
static MSFilter *ms_wasapi_snd_card_create_reader(MSSndCard *card);
static MSFilter *ms_wasapi_snd_card_create_writer(MSSndCard *card);
static void ms_wasapi_snd_card_init(MSSndCard *card) {
WasapiSndCard *c = static_cast<WasapiSndCard *>(ms_new0(WasapiSndCard, 1));
card->data = c;
}
static void ms_wasapi_snd_card_uninit(MSSndCard *card) {
WasapiSndCard *c = static_cast<WasapiSndCard *>(card->data);
if (c->id_vector) delete c->id_vector;
ms_free(c);
}
static MSSndCardDesc ms_wasapi_snd_card_desc = {
"MSWASAPISndCard",
"WASAPI",
ms_wasapi_snd_card_detect,
NULL,
ms_wasapi_snd_card_init,
NULL,
NULL,
NULL,
......@@ -307,31 +321,143 @@ static MSSndCardDesc ms_wasapi_snd_card_desc = {
NULL,
ms_wasapi_snd_card_create_reader,
ms_wasapi_snd_card_create_writer,
NULL,
ms_wasapi_snd_card_uninit,
NULL,
NULL
};
static MSSndCard *ms_wasapi_snd_card_new(void) {
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE)
static MSSndCard *ms_wasapi_phone_snd_card_new(void) {
MSSndCard *card = ms_snd_card_new(&ms_wasapi_snd_card_desc);
card->name = ms_strdup("WASAPI sound card");
card->latency = 250;
return card;
}
#endif
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
static MSSndCard *ms_wasapi_snd_card_new(LPWSTR id, const char *name, uint8_t capabilities) {
MSSndCard *card = ms_snd_card_new(&ms_wasapi_snd_card_desc);
WasapiSndCard *wasapicard = static_cast<WasapiSndCard *>(card->data);
card->name = ms_strdup(name);
card->capabilities = capabilities;
wasapicard->id_vector = new std::vector<wchar_t>(wcslen(id) + 1);
wcscpy_s(wasapicard->id_vector->data(), wasapicard->id_vector->size(), id);
wasapicard->id = wasapicard->id_vector->data();
return card;
}
static void add_or_update_card(MSSndCardManager *m, LPWSTR id, LPWSTR wname, EDataFlow data_flow) {
MSSndCard *card;
const MSList *elem = ms_snd_card_manager_get_list(m);
uint8_t capabilities = 0;
char *name;
size_t inputlen;
size_t returnlen;
inputlen = wcslen(wname) + 1;
name = (char *)ms_malloc(inputlen);
if (wcstombs_s(&returnlen, name, inputlen, wname, inputlen) != 0) {
ms_error("mswasapi: Cannot convert card name to multi-byte string.");
return;
}
switch (data_flow) {
case eRender:
capabilities = MS_SND_CARD_CAP_PLAYBACK;
break;
case eCapture:
capabilities = MS_SND_CARD_CAP_CAPTURE;
break;
case eAll:
default:
capabilities = MS_SND_CARD_CAP_PLAYBACK | MS_SND_CARD_CAP_CAPTURE;
break;
}
for (; elem != NULL; elem = elem->next){
card = static_cast<MSSndCard *>(elem->data);
if (strcmp(card->name, name) == 0){
/* Update an existing card. */
WasapiSndCard *d = static_cast<WasapiSndCard *>(card->data);
card->capabilities |= capabilities;
ms_free(name);
return;
}
}
/* Add a new card. */
ms_snd_card_manager_add_card(m, ms_wasapi_snd_card_new(id, name, capabilities));
ms_free(name);
}
static void ms_wasapi_snd_card_detect_with_data_flow(MSSndCardManager *m, EDataFlow data_flow) {
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDeviceCollection *pCollection = NULL;
IMMDevice *pEndpoint = NULL;
IPropertyStore *pProps = NULL;
LPWSTR pwszID = NULL;
HRESULT result = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
REPORT_ERROR("mswasapi: Could not create an instance of the device enumerator", result);
result = pEnumerator->EnumAudioEndpoints(data_flow, DEVICE_STATE_ACTIVE, &pCollection);
REPORT_ERROR("mswasapi: Could not enumerate audio endpoints", result);
UINT count;
result = pCollection->GetCount(&count);
REPORT_ERROR("mswasapi: Could not get the number of audio endpoints", result);
if (count == 0) {
ms_warning("mswasapi: No audio endpoint found");
return;
}
for (ULONG i = 0; i < count; i++) {
result = pCollection->Item(i, &pEndpoint);
REPORT_ERROR("mswasapi: Could not get pointer to audio endpoint", result);
result = pEndpoint->GetId(&pwszID);
REPORT_ERROR("mswasapi: Could not get ID of audio endpoint", result);
result = pEndpoint->OpenPropertyStore(STGM_READ, &pProps);
REPORT_ERROR("mswasapi: Could not open property store", result);
PROPVARIANT varName;
PropVariantInit(&varName);
result = pProps->GetValue(PKEY_Device_FriendlyName, &varName);
REPORT_ERROR("mswasapi: Could not get friendly-name of audio endpoint", result);
add_or_update_card(m, pwszID, varName.pwszVal, data_flow);
CoTaskMemFree(pwszID);
pwszID = NULL;
PropVariantClear(&varName);
SAFE_RELEASE(pProps);
SAFE_RELEASE(pEndpoint);
}
error:
CoTaskMemFree(pwszID);
SAFE_RELEASE(pEnumerator);
SAFE_RELEASE(pCollection);
SAFE_RELEASE(pEndpoint);
SAFE_RELEASE(pProps);
}
#endif
static void ms_wasapi_snd_card_detect(MSSndCardManager *m) {
MSSndCard *card = ms_wasapi_snd_card_new();
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE)
MSSndCard *card = ms_wasapi_phone_snd_card_new();
ms_snd_card_manager_add_card(m, card);
#else
ms_wasapi_snd_card_detect_with_data_flow(m, eCapture);
ms_wasapi_snd_card_detect_with_data_flow(m, eRender);
#endif
}
static MSFilter *ms_wasapi_snd_card_create_reader(MSSndCard *card) {
MS_UNUSED(card);
return ms_filter_new_from_desc(&ms_wasapi_read_desc);
MSFilter *f = ms_filter_new_from_desc(&ms_wasapi_read_desc);
WasapiSndCard *wasapicard = static_cast<WasapiSndCard *>(card->data);
MSWASAPIReader *reader = static_cast<MSWASAPIReader *>(f->data);
reader->init(wasapicard->id);
return f;
}
static MSFilter *ms_wasapi_snd_card_create_writer(MSSndCard *card) {
MS_UNUSED(card);
return ms_filter_new_from_desc(&ms_wasapi_write_desc);
MSFilter *f = ms_filter_new_from_desc(&ms_wasapi_write_desc);
WasapiSndCard *wasapicard = static_cast<WasapiSndCard *>(card->data);
MSWASAPIWriter *writer = static_cast<MSWASAPIWriter *>(f->data);
writer->init(wasapicard->id);
return f;
}
......
/*
mswasapi.cpp
mediastreamer2 library - modular sound and video processing and streaming
Windows Audio Session API sound card plugin for mediastreamer2
Copyright (C) 2010-2013 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#pragma once
#include <vector>
#include <objbase.h>
#include <audioclient.h>
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE)
#include <phoneaudioclient.h>
#else
#include <mmdeviceapi.h>
#include <functiondiscoverykeys_devpkey.h>
#endif
#define REPORT_ERROR(msg, result) \
if (result != S_OK) { \
ms_error(msg, result); \
goto error; \
}
#define SAFE_RELEASE(obj) \
if ((obj) != NULL) { \
(obj)->Release(); \
(obj) = NULL; \
}
typedef struct WasapiSndCard {
std::vector<wchar_t> *id_vector;
LPWSTR id;
} WasapiSndCard;
......@@ -50,11 +50,26 @@ bool MSWASAPIReader::smInstantiated = false;
MSWASAPIReader::MSWASAPIReader()
: mAudioClient(NULL), mAudioCaptureClient(NULL), mBufferFrameCount(0), mIsInitialized(false), mIsActivated(false), mIsStarted(false)
{
}
MSWASAPIReader::~MSWASAPIReader()
{
RELEASE_CLIENT(mAudioClient);
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE)
FREE_PTR(mCaptureId);
#endif
smInstantiated = false;
}
void MSWASAPIReader::init(LPCWSTR id)
{
HRESULT result;
WAVEFORMATEX *pWfx = NULL;
AudioClientProperties properties;
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE)
mCaptureId = GetDefaultAudioCaptureId(Communications);
if (mCaptureId == NULL) {
ms_error("Could not get the CaptureId of the MSWASAPI audio input interface");
......@@ -68,6 +83,16 @@ MSWASAPIReader::MSWASAPIReader()
result = ActivateAudioInterface(mCaptureId, IID_IAudioClient2, (void **)&mAudioClient);
REPORT_ERROR("Could not activate the MSWASAPI audio input interface [%x]", result);
#else
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
result = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
REPORT_ERROR("mswasapi: Could not create an instance of the device enumerator", result);
mCaptureId = id;
result = pEnumerator->GetDevice(mCaptureId, &pDevice);
REPORT_ERROR("mswasapi: Could not get the rendering device", result);
pDevice->Activate(IID_IAudioClient2, CLSCTX_ALL, NULL, (void **)&mAudioClient);
#endif
properties.cbSize = sizeof AudioClientProperties;
properties.bIsOffload = false;
properties.eCategory = AudioCategory_Communications;
......@@ -89,14 +114,6 @@ error:
return;
}
MSWASAPIReader::~MSWASAPIReader()
{
RELEASE_CLIENT(mAudioClient);
FREE_PTR(mCaptureId);
smInstantiated = false;
}
int MSWASAPIReader::activate()
{
HRESULT result;
......
......@@ -26,9 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msfilter.h"
#include <objbase.h>
#include <audioclient.h>
#include <phoneaudioclient.h>
#include "mswasapi.h"
class MSWASAPIReader {
......@@ -36,6 +34,7 @@ public:
MSWASAPIReader();
virtual ~MSWASAPIReader();
void init(LPCWSTR id);
int activate();
int deactivate();
bool isStarted() { return mIsStarted; }
......
......@@ -50,10 +50,24 @@ bool MSWASAPIWriter::smInstantiated = false;
MSWASAPIWriter::MSWASAPIWriter()
: mAudioClient(NULL), mAudioRenderClient(NULL), mBufferFrameCount(0), mIsInitialized(false), mIsActivated(false), mIsStarted(false)
{
}
MSWASAPIWriter::~MSWASAPIWriter()
{
RELEASE_CLIENT(mAudioClient);
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE)
FREE_PTR(mRenderId);
#endif
smInstantiated = false;
}
void MSWASAPIWriter::init(LPCWSTR id) {
HRESULT result;
WAVEFORMATEX *pWfx = NULL;
AudioClientProperties properties;
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE)
mRenderId = GetDefaultAudioRenderId(Communications);
if (mRenderId == NULL) {
ms_error("Could not get the RenderId of the MSWASAPI audio output interface");
......@@ -67,6 +81,16 @@ MSWASAPIWriter::MSWASAPIWriter()
result = ActivateAudioInterface(mRenderId, IID_IAudioClient2, (void **)&mAudioClient);
REPORT_ERROR("Could not activate the MSWASAPI audio output interface [%i]", result);
#else
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
result = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
REPORT_ERROR("mswasapi: Could not create an instance of the device enumerator", result);
mRenderId = id;
result = pEnumerator->GetDevice(mRenderId, &pDevice);
REPORT_ERROR("mswasapi: Could not get the rendering device", result);
pDevice->Activate(IID_IAudioClient2, CLSCTX_ALL, NULL, (void **)&mAudioClient);
#endif
properties.cbSize = sizeof AudioClientProperties;
properties.bIsOffload = false;
properties.eCategory = AudioCategory_Communications;
......@@ -88,14 +112,6 @@ error:
return;
}
MSWASAPIWriter::~MSWASAPIWriter()
{
RELEASE_CLIENT(mAudioClient);
FREE_PTR(mRenderId);
smInstantiated = false;
}
int MSWASAPIWriter::activate()
{
HRESULT result;
......
......@@ -26,9 +26,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mediastreamer2/msfilter.h"
#include <objbase.h>
#include <audioclient.h>
#include <phoneaudioclient.h>
#include "mswasapi.h"
class MSWASAPIWriter {
......@@ -36,6 +34,7 @@ public:
MSWASAPIWriter();
virtual ~MSWASAPIWriter();
void init(LPCWSTR id);
int activate();
int deactivate();
bool isStarted() { return mIsStarted; }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment