|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* FreeRDP: A Remote Desktop Protocol Implementation
|
|
Packit |
1fb8d4 |
* Audio Input Redirection Virtual Channel - Mac OS X implementation
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Copyright (c) 2015 Armin Novak <armin.novak@thincast.com>
|
|
Packit |
1fb8d4 |
* Copyright 2015 Thincast Technologies GmbH
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
Packit |
1fb8d4 |
* you may not use this file except in compliance with the License.
|
|
Packit |
1fb8d4 |
* You may obtain a copy of the License at
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* Unless required by applicable law or agreed to in writing, software
|
|
Packit |
1fb8d4 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
Packit |
1fb8d4 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
Packit |
1fb8d4 |
* See the License for the specific language governing permissions and
|
|
Packit |
1fb8d4 |
* limitations under the License.
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#ifdef HAVE_CONFIG_H
|
|
Packit |
1fb8d4 |
#include "config.h"
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <stdio.h>
|
|
Packit |
1fb8d4 |
#include <stdlib.h>
|
|
Packit |
1fb8d4 |
#include <string.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <winpr/crt.h>
|
|
Packit |
1fb8d4 |
#include <winpr/synch.h>
|
|
Packit |
1fb8d4 |
#include <winpr/string.h>
|
|
Packit |
1fb8d4 |
#include <winpr/thread.h>
|
|
Packit |
1fb8d4 |
#include <winpr/debug.h>
|
|
Packit |
1fb8d4 |
#include <winpr/cmdline.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#define __COREFOUNDATION_CFPLUGINCOM__ 1
|
|
Packit Service |
5a9772 |
#define IUNKNOWN_C_GUTS \
|
|
Packit Service |
5a9772 |
void* _reserved; \
|
|
Packit Service |
5a9772 |
void* QueryInterface; \
|
|
Packit Service |
5a9772 |
void* AddRef; \
|
|
Packit Service |
5a9772 |
void* Release
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <CoreAudio/CoreAudioTypes.h>
|
|
Packit |
1fb8d4 |
#include <CoreAudio/CoreAudio.h>
|
|
Packit |
1fb8d4 |
#include <AudioToolbox/AudioToolbox.h>
|
|
Packit |
1fb8d4 |
#include <AudioToolbox/AudioQueue.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include <freerdp/addin.h>
|
|
Packit |
1fb8d4 |
#include <freerdp/channels/rdpsnd.h>
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#include "audin_main.h"
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
#define MAC_AUDIO_QUEUE_NUM_BUFFERS 100
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/* Fix for #4462: Provide type alias if not declared (Mac OS < 10.10)
|
|
Packit |
1fb8d4 |
* https://developer.apple.com/documentation/coreaudio/audioformatid
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
#ifndef AudioFormatID
|
|
Packit |
1fb8d4 |
typedef UInt32 AudioFormatID;
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#ifndef AudioFormatFlags
|
|
Packit |
1fb8d4 |
typedef UInt32 AudioFormatFlags;
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
typedef struct _AudinMacDevice
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
IAudinDevice iface;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
AUDIO_FORMAT format;
|
|
Packit |
1fb8d4 |
UINT32 FramesPerPacket;
|
|
Packit |
1fb8d4 |
int dev_unit;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
AudinReceive receive;
|
|
Packit |
1fb8d4 |
void* user_data;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
rdpContext* rdpcontext;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
bool isOpen;
|
|
Packit |
1fb8d4 |
AudioQueueRef audioQueue;
|
|
Packit |
1fb8d4 |
AudioStreamBasicDescription audioFormat;
|
|
Packit |
1fb8d4 |
AudioQueueBufferRef audioBuffers[MAC_AUDIO_QUEUE_NUM_BUFFERS];
|
|
Packit |
1fb8d4 |
} AudinMacDevice;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static AudioFormatID audin_mac_get_format(const AUDIO_FORMAT* format)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
switch (format->wFormatTag)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
case WAVE_FORMAT_PCM:
|
|
Packit |
1fb8d4 |
return kAudioFormatLinearPCM;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
default:
|
|
Packit |
1fb8d4 |
return 0;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static AudioFormatFlags audin_mac_get_flags_for_format(const AUDIO_FORMAT* format)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
switch (format->wFormatTag)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
case WAVE_FORMAT_PCM:
|
|
Packit |
1fb8d4 |
return kAudioFormatFlagIsSignedInteger;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
default:
|
|
Packit |
1fb8d4 |
return 0;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static BOOL audin_mac_format_supported(IAudinDevice* device, const AUDIO_FORMAT* format)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
AudioFormatID req_fmt = 0;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (device == NULL || format == NULL)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
req_fmt = audin_mac_get_format(format);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (req_fmt == 0)
|
|
Packit |
1fb8d4 |
return FALSE;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return TRUE;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
/**
|
|
Packit |
1fb8d4 |
* Function description
|
|
Packit |
1fb8d4 |
*
|
|
Packit |
1fb8d4 |
* @return 0 on success, otherwise a Win32 error code
|
|
Packit |
1fb8d4 |
*/
|
|
Packit |
1fb8d4 |
static UINT audin_mac_set_format(IAudinDevice* device, const AUDIO_FORMAT* format,
|
|
Packit |
1fb8d4 |
UINT32 FramesPerPacket)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
AudinMacDevice* mac = (AudinMacDevice*)device;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (device == NULL || format == NULL)
|
|
Packit |
1fb8d4 |
return ERROR_INVALID_PARAMETER;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
mac->FramesPerPacket = FramesPerPacket;
|
|
Packit |
1fb8d4 |
mac->format = *format;
|
|
Packit |
1fb8d4 |
WLog_INFO(TAG, "Audio Format %s [channels=%d, samples=%d, bits=%d]",
|
|
Packit Service |
5a9772 |
audio_format_get_tag_string(format->wFormatTag), format->nChannels,
|
|
Packit Service |
5a9772 |
format->nSamplesPerSec, format->wBitsPerSample);
|
|
Packit |
1fb8d4 |
mac->audioFormat.mBitsPerChannel = format->wBitsPerSample;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (format->wBitsPerSample == 0)
|
|
Packit |
1fb8d4 |
mac->audioFormat.mBitsPerChannel = 16;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
mac->audioFormat.mBytesPerFrame = 0;
|
|
Packit |
1fb8d4 |
mac->audioFormat.mBytesPerPacket = 0;
|
|
Packit |
1fb8d4 |
mac->audioFormat.mChannelsPerFrame = mac->format.nChannels;
|
|
Packit |
1fb8d4 |
mac->audioFormat.mFormatFlags = audin_mac_get_flags_for_format(format);
|
|
Packit |
1fb8d4 |
mac->audioFormat.mFormatID = audin_mac_get_format(format);
|
|
Packit |
1fb8d4 |
mac->audioFormat.mFramesPerPacket = 1;
|
|
Packit |
1fb8d4 |
mac->audioFormat.mReserved = 0;
|
|
Packit |
1fb8d4 |
mac->audioFormat.mSampleRate = mac->format.nSamplesPerSec;
|
|
Packit |
1fb8d4 |
return CHANNEL_RC_OK;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
static void mac_audio_queue_input_cb(void* aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer,
|
|
Packit Service |
5a9772 |
const AudioTimeStamp* inStartTime, UInt32 inNumPackets,
|
|
Packit |
1fb8d4 |
const AudioStreamPacketDescription* inPacketDesc)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
AudinMacDevice* mac = (AudinMacDevice*)aqData;
|
|
Packit |
1fb8d4 |
UINT error = CHANNEL_RC_OK;
|
|
Packit |
1fb8d4 |
const BYTE* buffer = inBuffer->mAudioData;
|
|
Packit |
1fb8d4 |
int buffer_size = inBuffer->mAudioDataByteSize;
|
|
Packit |
1fb8d4 |
(void)inAQ;
|
|
Packit |
1fb8d4 |
(void)inStartTime;
|
|
Packit |
1fb8d4 |
(void)inNumPackets;
|
|
Packit |
1fb8d4 |
(void)inPacketDesc;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (buffer_size > 0)
|
|
Packit |
1fb8d4 |
error = mac->receive(&mac->format, buffer, buffer_size, mac->user_data);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (error)
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "mac->receive failed with error %" PRIu32 "", error);
|
|
Packit |
1fb8d4 |
SetLastError(ERROR_INTERNAL_ERROR);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static UINT audin_mac_close(IAudinDevice* device)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
UINT errCode = CHANNEL_RC_OK;
|
|
Packit |
1fb8d4 |
char errString[1024];
|
|
Packit |
1fb8d4 |
OSStatus devStat;
|
|
Packit |
1fb8d4 |
AudinMacDevice* mac = (AudinMacDevice*)device;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (device == NULL)
|
|
Packit |
1fb8d4 |
return ERROR_INVALID_PARAMETER;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (mac->isOpen)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
devStat = AudioQueueStop(mac->audioQueue, true);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (devStat != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
errCode = GetLastError();
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "AudioQueueStop failed with %s [%" PRIu32 "]",
|
|
Packit |
1fb8d4 |
winpr_strerror(errCode, errString, sizeof(errString)), errCode);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
mac->isOpen = false;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (mac->audioQueue)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
devStat = AudioQueueDispose(mac->audioQueue, true);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (devStat != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
errCode = GetLastError();
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "AudioQueueDispose failed with %s [%" PRIu32 "]",
|
|
Packit |
1fb8d4 |
winpr_strerror(errCode, errString, sizeof(errString)), errCode);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
mac->audioQueue = NULL;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
mac->receive = NULL;
|
|
Packit |
1fb8d4 |
mac->user_data = NULL;
|
|
Packit |
1fb8d4 |
return errCode;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static UINT audin_mac_open(IAudinDevice* device, AudinReceive receive, void* user_data)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
AudinMacDevice* mac = (AudinMacDevice*)device;
|
|
Packit |
1fb8d4 |
DWORD errCode;
|
|
Packit |
1fb8d4 |
char errString[1024];
|
|
Packit |
1fb8d4 |
OSStatus devStat;
|
|
Packit |
1fb8d4 |
size_t index;
|
|
Packit |
1fb8d4 |
mac->receive = receive;
|
|
Packit |
1fb8d4 |
mac->user_data = user_data;
|
|
Packit Service |
5a9772 |
devStat = AudioQueueNewInput(&(mac->audioFormat), mac_audio_queue_input_cb, mac, NULL,
|
|
Packit Service |
5a9772 |
kCFRunLoopCommonModes, 0, &(mac->audioQueue));
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (devStat != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
errCode = GetLastError();
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "AudioQueueNewInput failed with %s [%" PRIu32 "]",
|
|
Packit |
1fb8d4 |
winpr_strerror(errCode, errString, sizeof(errString)), errCode);
|
|
Packit |
1fb8d4 |
goto err_out;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
for (index = 0; index < MAC_AUDIO_QUEUE_NUM_BUFFERS; index++)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
devStat = AudioQueueAllocateBuffer(mac->audioQueue,
|
|
Packit |
1fb8d4 |
mac->FramesPerPacket * 2 * mac->format.nChannels,
|
|
Packit |
1fb8d4 |
&mac->audioBuffers[index]);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (devStat != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
errCode = GetLastError();
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "AudioQueueAllocateBuffer failed with %s [%" PRIu32 "]",
|
|
Packit |
1fb8d4 |
winpr_strerror(errCode, errString, sizeof(errString)), errCode);
|
|
Packit |
1fb8d4 |
goto err_out;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
devStat = AudioQueueEnqueueBuffer(mac->audioQueue, mac->audioBuffers[index], 0, NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (devStat != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
errCode = GetLastError();
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "AudioQueueEnqueueBuffer failed with %s [%" PRIu32 "]",
|
|
Packit |
1fb8d4 |
winpr_strerror(errCode, errString, sizeof(errString)), errCode);
|
|
Packit |
1fb8d4 |
goto err_out;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
devStat = AudioQueueStart(mac->audioQueue, NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (devStat != 0)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
errCode = GetLastError();
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "AudioQueueStart failed with %s [%" PRIu32 "]",
|
|
Packit |
1fb8d4 |
winpr_strerror(errCode, errString, sizeof(errString)), errCode);
|
|
Packit |
1fb8d4 |
goto err_out;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
mac->isOpen = true;
|
|
Packit |
1fb8d4 |
return CHANNEL_RC_OK;
|
|
Packit |
1fb8d4 |
err_out:
|
|
Packit |
1fb8d4 |
audin_mac_close(device);
|
|
Packit |
1fb8d4 |
return CHANNEL_RC_INITIALIZATION_ERROR;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static UINT audin_mac_free(IAudinDevice* device)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
AudinMacDevice* mac = (AudinMacDevice*)device;
|
|
Packit |
1fb8d4 |
int error;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (device == NULL)
|
|
Packit |
1fb8d4 |
return ERROR_INVALID_PARAMETER;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((error = audin_mac_close(device)))
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "audin_oss_close failed with error code %d!", error);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
free(mac);
|
|
Packit |
1fb8d4 |
return CHANNEL_RC_OK;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
static UINT audin_mac_parse_addin_args(AudinMacDevice* device, ADDIN_ARGV* args)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
DWORD errCode;
|
|
Packit |
1fb8d4 |
char errString[1024];
|
|
Packit |
1fb8d4 |
int status;
|
|
Packit Service |
5a9772 |
char *str_num, *eptr;
|
|
Packit |
1fb8d4 |
DWORD flags;
|
|
Packit |
1fb8d4 |
COMMAND_LINE_ARGUMENT_A* arg;
|
|
Packit Service |
5a9772 |
COMMAND_LINE_ARGUMENT_A audin_mac_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>",
|
|
Packit Service |
5a9772 |
NULL, NULL, -1, NULL, "audio device name" },
|
|
Packit Service |
5a9772 |
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } };
|
|
Packit Service |
5a9772 |
|
|
Packit |
1fb8d4 |
AudinMacDevice* mac = (AudinMacDevice*)device;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (args->argc == 1)
|
|
Packit |
1fb8d4 |
return CHANNEL_RC_OK;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
flags =
|
|
Packit Service |
5a9772 |
COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
|
|
Packit Service |
5a9772 |
status =
|
|
Packit Service |
5a9772 |
CommandLineParseArgumentsA(args->argc, args->argv, audin_mac_args, flags, mac, NULL, NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (status < 0)
|
|
Packit |
1fb8d4 |
return ERROR_INVALID_PARAMETER;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
arg = audin_mac_args;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
do
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
|
Packit |
1fb8d4 |
continue;
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dev")
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
str_num = _strdup(arg->Value);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!str_num)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
errCode = GetLastError();
|
|
Packit |
1fb8d4 |
WLog_ERR(TAG, "_strdup failed with %s [%d]",
|
|
Packit |
1fb8d4 |
winpr_strerror(errCode, errString, sizeof(errString)), errCode);
|
|
Packit |
1fb8d4 |
return CHANNEL_RC_NO_MEMORY;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
mac->dev_unit = strtol(str_num, &eptr, 10);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (mac->dev_unit < 0 || *eptr != '\0')
|
|
Packit |
1fb8d4 |
mac->dev_unit = -1;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
free(str_num);
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
CommandLineSwitchEnd(arg)
|
|
Packit Service |
5a9772 |
} while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return CHANNEL_RC_OK;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
#ifdef BUILTIN_CHANNELS
|
|
Packit Service |
5a9772 |
#define freerdp_audin_client_subsystem_entry mac_freerdp_audin_client_subsystem_entry
|
|
Packit |
1fb8d4 |
#else
|
|
Packit Service |
5a9772 |
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
|
Packit |
1fb8d4 |
#endif
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
DWORD errCode;
|
|
Packit |
1fb8d4 |
char errString[1024];
|
|
Packit |
1fb8d4 |
ADDIN_ARGV* args;
|
|
Packit |
1fb8d4 |
AudinMacDevice* mac;
|
|
Packit |
1fb8d4 |
UINT error;
|
|
Packit |
1fb8d4 |
mac = (AudinMacDevice*)calloc(1, sizeof(AudinMacDevice));
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if (!mac)
|
|
Packit |
1fb8d4 |
{
|
|
Packit |
1fb8d4 |
errCode = GetLastError();
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "calloc failed with %s [%" PRIu32 "]",
|
|
Packit |
1fb8d4 |
winpr_strerror(errCode, errString, sizeof(errString)), errCode);
|
|
Packit |
1fb8d4 |
return CHANNEL_RC_NO_MEMORY;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
mac->iface.Open = audin_mac_open;
|
|
Packit |
1fb8d4 |
mac->iface.FormatSupported = audin_mac_format_supported;
|
|
Packit |
1fb8d4 |
mac->iface.SetFormat = audin_mac_set_format;
|
|
Packit |
1fb8d4 |
mac->iface.Close = audin_mac_close;
|
|
Packit |
1fb8d4 |
mac->iface.Free = audin_mac_free;
|
|
Packit |
1fb8d4 |
mac->rdpcontext = pEntryPoints->rdpcontext;
|
|
Packit |
1fb8d4 |
mac->dev_unit = -1;
|
|
Packit |
1fb8d4 |
args = pEntryPoints->args;
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
if ((error = audin_mac_parse_addin_args(mac, args)))
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "audin_mac_parse_addin_args failed with %" PRIu32 "!", error);
|
|
Packit |
1fb8d4 |
goto error_out;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit Service |
5a9772 |
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)mac)))
|
|
Packit |
1fb8d4 |
{
|
|
Packit Service |
5a9772 |
WLog_ERR(TAG, "RegisterAudinDevice failed with error %" PRIu32 "!", error);
|
|
Packit |
1fb8d4 |
goto error_out;
|
|
Packit |
1fb8d4 |
}
|
|
Packit |
1fb8d4 |
|
|
Packit |
1fb8d4 |
return CHANNEL_RC_OK;
|
|
Packit |
1fb8d4 |
error_out:
|
|
Packit |
1fb8d4 |
free(mac);
|
|
Packit |
1fb8d4 |
return error;
|
|
Packit |
1fb8d4 |
}
|