commit
08271709e4
@ -32,10 +32,10 @@
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/cmdline.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/wlog.h>
|
||||
|
||||
#include <freerdp/addin.h>
|
||||
|
||||
#include <winpr/stream.h>
|
||||
#include <freerdp/freerdp.h>
|
||||
#include "audin_main.h"
|
||||
|
||||
@ -71,7 +71,7 @@ struct _AUDIN_CHANNEL_CALLBACK
|
||||
* Open PDU and Format Change PDU
|
||||
*/
|
||||
audinFormat* formats;
|
||||
int formats_count;
|
||||
UINT32 formats_count;
|
||||
};
|
||||
|
||||
typedef struct _AUDIN_PLUGIN AUDIN_PLUGIN;
|
||||
@ -93,37 +93,45 @@ struct _AUDIN_PLUGIN
|
||||
|
||||
rdpContext* rdpcontext;
|
||||
BOOL attached;
|
||||
wLog* log;
|
||||
};
|
||||
|
||||
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
|
||||
|
||||
static UINT audin_write_and_free_stream(AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
UINT error = ERROR_INTERNAL_ERROR;
|
||||
const size_t length = Stream_GetPosition(s);
|
||||
const BYTE* data = Stream_Buffer(s);
|
||||
|
||||
if (callback && callback->channel && callback->channel->Write)
|
||||
error = callback->channel->Write(callback->channel, length, data, NULL);
|
||||
|
||||
Stream_Free(s, TRUE);
|
||||
return error;
|
||||
}
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
|
||||
static UINT audin_process_version(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
UINT error;
|
||||
wStream* out;
|
||||
UINT32 Version;
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
Stream_Read_UINT32(s, Version);
|
||||
DEBUG_DVC("Version=%"PRIu32"", Version);
|
||||
out = Stream_New(NULL, 5);
|
||||
|
||||
if (!out)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
|
||||
return ERROR_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
Stream_Write_UINT8(out, MSG_SNDIN_VERSION);
|
||||
Stream_Write_UINT32(out, Version);
|
||||
error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out),
|
||||
Stream_Buffer(out), NULL);
|
||||
Stream_Free(out, TRUE);
|
||||
return error;
|
||||
return audin_write_and_free_stream(callback, out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,11 +139,13 @@ static UINT audin_process_version(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
static UINT audin_send_incoming_data_pdu(AUDIN_CHANNEL_CALLBACK* callback)
|
||||
{
|
||||
BYTE out_data[1];
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
out_data[0] = MSG_SNDIN_DATA_INCOMING;
|
||||
BYTE out_data[1] = { MSG_SNDIN_DATA_INCOMING };
|
||||
|
||||
if (!callback || !callback->channel || !callback->channel->Write)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
return callback->channel->Write(callback->channel, 1, out_data, NULL);
|
||||
}
|
||||
|
||||
@ -144,23 +154,25 @@ static UINT audin_send_incoming_data_pdu(IWTSVirtualChannelCallback* pChannelCal
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
|
||||
static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
|
||||
UINT32 i;
|
||||
BYTE* fm;
|
||||
UINT error;
|
||||
wStream* out;
|
||||
UINT32 NumFormats;
|
||||
audinFormat format;
|
||||
UINT32 cbSizeFormatsPacket;
|
||||
size_t cbSizeFormatsPacket;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 8)
|
||||
return ERROR_NO_DATA;
|
||||
|
||||
Stream_Read_UINT32(s, NumFormats);
|
||||
DEBUG_DVC("NumFormats %"PRIu32"", NumFormats);
|
||||
|
||||
if ((NumFormats < 1) || (NumFormats > 1000))
|
||||
{
|
||||
WLog_ERR(TAG, "bad NumFormats %"PRIu32"", NumFormats);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "bad NumFormats %"PRIu32"", NumFormats);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -169,7 +181,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
|
||||
if (!callback->formats)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "calloc failed!");
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -178,7 +190,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
if (!out)
|
||||
{
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -187,6 +199,9 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
/* SoundFormats (variable) */
|
||||
for (i = 0; i < NumFormats; i++)
|
||||
{
|
||||
if (Stream_GetRemainingLength(s) < 18)
|
||||
return ERROR_NO_DATA;
|
||||
|
||||
Stream_GetPointer(s, fm);
|
||||
Stream_Read_UINT16(s, format.wFormatTag);
|
||||
Stream_Read_UINT16(s, format.nChannels);
|
||||
@ -196,6 +211,10 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
Stream_Read_UINT16(s, format.wBitsPerSample);
|
||||
Stream_Read_UINT16(s, format.cbSize);
|
||||
format.data = Stream_Pointer(s);
|
||||
|
||||
if (Stream_GetRemainingLength(s) < format.cbSize)
|
||||
return ERROR_NO_DATA;
|
||||
|
||||
Stream_Seek(s, format.cbSize);
|
||||
DEBUG_DVC("wFormatTag=%"PRIu16" nChannels=%"PRIu16" nSamplesPerSec=%"PRIu32" "
|
||||
"nBlockAlign=%"PRIu16" wBitsPerSample=%"PRIu16" cbSize=%"PRIu16"",
|
||||
@ -221,7 +240,7 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
if (!Stream_EnsureRemainingCapacity(out, 18 + format.cbSize))
|
||||
{
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -229,18 +248,19 @@ static UINT audin_process_formats(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = audin_send_incoming_data_pdu(pChannelCallback)))
|
||||
if ((error = audin_send_incoming_data_pdu(callback)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_send_incoming_data_pdu failed!");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cbSizeFormatsPacket = (UINT32) Stream_GetPosition(out);
|
||||
cbSizeFormatsPacket = Stream_GetPosition(out);
|
||||
Stream_SetPosition(out, 0);
|
||||
Stream_Write_UINT8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */
|
||||
Stream_Write_UINT32(out, callback->formats_count); /* NumFormats (4 bytes) */
|
||||
Stream_Write_UINT32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */
|
||||
error = callback->channel->Write(callback->channel, cbSizeFormatsPacket, Stream_Buffer(out), NULL);
|
||||
Stream_SetPosition(out, cbSizeFormatsPacket);
|
||||
error = audin_write_and_free_stream(callback, out);
|
||||
out:
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
@ -249,7 +269,6 @@ out:
|
||||
callback->formats = NULL;
|
||||
}
|
||||
|
||||
Stream_Free(out, TRUE);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -258,25 +277,20 @@ out:
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
static UINT audin_send_format_change_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback,
|
||||
UINT32 NewFormat)
|
||||
{
|
||||
UINT error;
|
||||
wStream* out;
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
out = Stream_New(NULL, 5);
|
||||
wStream* out = Stream_New(NULL, 5);
|
||||
|
||||
if (!out)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
Stream_Write_UINT8(out, MSG_SNDIN_FORMATCHANGE);
|
||||
Stream_Write_UINT32(out, NewFormat);
|
||||
error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL);
|
||||
Stream_Free(out, TRUE);
|
||||
return error;
|
||||
return audin_write_and_free_stream(callback, out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -284,24 +298,20 @@ static UINT audin_send_format_change_pdu(IWTSVirtualChannelCallback* pChannelCal
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_send_open_reply_pdu(IWTSVirtualChannelCallback* pChannelCallback, UINT32 Result)
|
||||
static UINT audin_send_open_reply_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback,
|
||||
UINT32 Result)
|
||||
{
|
||||
UINT error;
|
||||
wStream* out;
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
out = Stream_New(NULL, 5);
|
||||
wStream* out = Stream_New(NULL, 5);
|
||||
|
||||
if (!out)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write_UINT8(out, MSG_SNDIN_OPEN_REPLY);
|
||||
Stream_Write_UINT32(out, Result);
|
||||
error = callback->channel->Write(callback->channel, 5, Stream_Buffer(out), NULL);
|
||||
Stream_Free(out, TRUE);
|
||||
return error;
|
||||
return audin_write_and_free_stream(callback, out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -327,9 +337,9 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data)
|
||||
if (!audin->attached)
|
||||
return CHANNEL_RC_OK;
|
||||
|
||||
if ((error = audin_send_incoming_data_pdu((IWTSVirtualChannelCallback*) callback)))
|
||||
if ((error = audin_send_incoming_data_pdu(callback)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_send_incoming_data_pdu failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_send_incoming_data_pdu failed!");
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -337,16 +347,13 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data)
|
||||
|
||||
if (!out)
|
||||
{
|
||||
WLog_ERR(TAG, "Stream_New failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Stream_New failed!");
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
Stream_Write_UINT8(out, MSG_SNDIN_DATA);
|
||||
Stream_Write(out, data, size);
|
||||
error = callback->channel->Write(callback->channel, (UINT32) Stream_GetPosition(out),
|
||||
Stream_Buffer(out), NULL);
|
||||
Stream_Free(out, TRUE);
|
||||
return error;
|
||||
return audin_write_and_free_stream(callback, out);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -354,14 +361,19 @@ static UINT audin_receive_wave_data(const BYTE* data, int size, void* user_data)
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
|
||||
static UINT audin_process_open(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, wStream* s)
|
||||
{
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
|
||||
audinFormat* format;
|
||||
UINT32 initialFormat;
|
||||
UINT32 FramesPerPacket;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (!audin || !callback || !s)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 8)
|
||||
return ERROR_NO_DATA;
|
||||
|
||||
Stream_Read_UINT32(s, FramesPerPacket);
|
||||
Stream_Read_UINT32(s, initialFormat);
|
||||
DEBUG_DVC("FramesPerPacket=%"PRIu32" initialFormat=%"PRIu32"",
|
||||
@ -369,8 +381,8 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
|
||||
|
||||
if (initialFormat >= (UINT32) callback->formats_count)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid format index %"PRIu32" (total %d)",
|
||||
initialFormat, callback->formats_count);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)",
|
||||
initialFormat, callback->formats_count);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -382,7 +394,7 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "SetFormat failed with errorcode %"PRIu32"", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -390,19 +402,19 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Open failed with errorcode %"PRIu32"", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = audin_send_format_change_pdu(pChannelCallback, initialFormat)))
|
||||
if ((error = audin_send_format_change_pdu(audin, callback, initialFormat)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_send_format_change_pdu failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_send_format_change_pdu failed!");
|
||||
return error;
|
||||
}
|
||||
|
||||
if ((error = audin_send_open_reply_pdu(pChannelCallback, 0)))
|
||||
WLog_ERR(TAG, "audin_send_open_reply_pdu failed!");
|
||||
if ((error = audin_send_open_reply_pdu(audin, callback, 0)))
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_send_open_reply_pdu failed!");
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -412,20 +424,26 @@ static UINT audin_process_open(IWTSVirtualChannelCallback* pChannelCallback, wSt
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
|
||||
static UINT audin_process_format_change(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback,
|
||||
wStream* s)
|
||||
{
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin;
|
||||
UINT32 NewFormat;
|
||||
audinFormat* format;
|
||||
UINT error = CHANNEL_RC_OK;
|
||||
|
||||
if (!audin || !callback || !s)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
if (Stream_GetRemainingLength(s) < 4)
|
||||
return ERROR_NO_DATA;
|
||||
|
||||
Stream_Read_UINT32(s, NewFormat);
|
||||
DEBUG_DVC("NewFormat=%"PRIu32"", NewFormat);
|
||||
|
||||
if (NewFormat >= (UINT32) callback->formats_count)
|
||||
if (NewFormat >= callback->formats_count)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid format index %"PRIu32" (total %d)",
|
||||
NewFormat, callback->formats_count);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)",
|
||||
NewFormat, callback->formats_count);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -437,7 +455,7 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Close failed with errorcode %"PRIu32"", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -445,7 +463,7 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "SetFormat failed with errorcode %"PRIu32"", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -453,13 +471,13 @@ static UINT audin_process_format_change(IWTSVirtualChannelCallback* pChannelCall
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Open failed with errorcode %"PRIu32"", error);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if ((error = audin_send_format_change_pdu(pChannelCallback, NewFormat)))
|
||||
WLog_ERR(TAG, "audin_send_format_change_pdu failed!");
|
||||
if ((error = audin_send_format_change_pdu(audin, callback, NewFormat)))
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_send_format_change_pdu failed!");
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -473,29 +491,43 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
|
||||
{
|
||||
UINT error;
|
||||
BYTE MessageId;
|
||||
AUDIN_PLUGIN* audin;
|
||||
AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback;
|
||||
|
||||
if (!callback || !data)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
|
||||
audin = (AUDIN_PLUGIN*) callback->plugin;
|
||||
|
||||
if (!audin)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
if (Stream_GetRemainingCapacity(data) < 1)
|
||||
return ERROR_NO_DATA;
|
||||
|
||||
Stream_Read_UINT8(data, MessageId);
|
||||
DEBUG_DVC("MessageId=0x%02"PRIx8"", MessageId);
|
||||
|
||||
switch (MessageId)
|
||||
{
|
||||
case MSG_SNDIN_VERSION:
|
||||
error = audin_process_version(pChannelCallback, data);
|
||||
error = audin_process_version(audin, callback, data);
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_FORMATS:
|
||||
error = audin_process_formats(pChannelCallback, data);
|
||||
error = audin_process_formats(audin, callback, data);
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_OPEN:
|
||||
error = audin_process_open(pChannelCallback, data);
|
||||
error = audin_process_open(audin, callback, data);
|
||||
break;
|
||||
|
||||
case MSG_SNDIN_FORMATCHANGE:
|
||||
error = audin_process_format_change(pChannelCallback, data);
|
||||
error = audin_process_format_change(audin, callback, data);
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "unknown MessageId=0x%02"PRIx8"", MessageId);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "unknown MessageId=0x%02"PRIx8"", MessageId);
|
||||
error = ERROR_INVALID_DATA;
|
||||
break;
|
||||
}
|
||||
@ -520,7 +552,7 @@ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback)
|
||||
IFCALLRET(audin->device->Close, error, audin->device);
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Close failed with errorcode %"PRIu32"", error);
|
||||
}
|
||||
|
||||
free(callback->formats);
|
||||
@ -538,13 +570,19 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
|
||||
IWTSVirtualChannelCallback** ppCallback)
|
||||
{
|
||||
AUDIN_CHANNEL_CALLBACK* callback;
|
||||
AUDIN_PLUGIN* audin;
|
||||
AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback;
|
||||
|
||||
if (!listener_callback || !listener_callback->plugin)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
audin = (AUDIN_PLUGIN*) listener_callback->plugin;
|
||||
DEBUG_DVC("...");
|
||||
callback = (AUDIN_CHANNEL_CALLBACK*) calloc(1, sizeof(AUDIN_CHANNEL_CALLBACK));
|
||||
|
||||
if (!callback)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "calloc failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
@ -570,7 +608,7 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag
|
||||
|
||||
if (!audin->listener_callback)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "calloc failed!");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
@ -598,7 +636,7 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin)
|
||||
|
||||
if (error != CHANNEL_RC_OK)
|
||||
{
|
||||
WLog_ERR(TAG, "Free failed with errorcode %"PRIu32"", error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "Free failed with errorcode %"PRIu32"", error);
|
||||
// dont stop on error
|
||||
}
|
||||
|
||||
@ -649,7 +687,7 @@ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
|
||||
|
||||
if (audin->device)
|
||||
{
|
||||
WLog_ERR(TAG, "existing device, abort.");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "existing device, abort.");
|
||||
return ERROR_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
@ -663,38 +701,34 @@ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* devi
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDIN_ARGV* args)
|
||||
static UINT audin_load_device_plugin(AUDIN_PLUGIN* audin, char* name, ADDIN_ARGV* args)
|
||||
{
|
||||
PFREERDP_AUDIN_DEVICE_ENTRY entry;
|
||||
FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints;
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin;
|
||||
UINT error;
|
||||
|
||||
if (!audin_process_addin_args(audin, args))
|
||||
return CHANNEL_RC_INITIALIZATION_ERROR;
|
||||
|
||||
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL,
|
||||
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", name, NULL,
|
||||
0);
|
||||
|
||||
if (entry == NULL)
|
||||
{
|
||||
WLog_ERR(TAG, "freerdp_load_channel_addin_entry did not return any function pointers for %s ",
|
||||
name);
|
||||
WLog_Print(audin->log, WLOG_ERROR,
|
||||
"freerdp_load_channel_addin_entry did not return any function pointers for %s ",
|
||||
name);
|
||||
return ERROR_INVALID_FUNCTION;
|
||||
}
|
||||
|
||||
entryPoints.plugin = pPlugin;
|
||||
entryPoints.plugin = (IWTSPlugin*) audin;
|
||||
entryPoints.pRegisterAudinDevice = audin_register_device_plugin;
|
||||
entryPoints.args = args;
|
||||
entryPoints.rdpcontext = ((AUDIN_PLUGIN*)pPlugin)->rdpcontext;
|
||||
entryPoints.rdpcontext = audin->rdpcontext;
|
||||
|
||||
if ((error = entry(&entryPoints)))
|
||||
{
|
||||
WLog_ERR(TAG, "%s entry returned error %"PRIu32".", name, error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "%s entry returned error %"PRIu32".", name, error);
|
||||
return error;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "Loaded %s backend for audin", name);
|
||||
WLog_Print(audin->log, WLOG_INFO, "Loaded %s backend for audin", name);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -703,14 +737,14 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
|
||||
*
|
||||
* @return 0 on success, otherwise a Win32 error code
|
||||
*/
|
||||
static UINT audin_set_subsystem(AUDIN_PLUGIN* audin, char* subsystem)
|
||||
static UINT audin_set_subsystem(AUDIN_PLUGIN* audin, const char* subsystem)
|
||||
{
|
||||
free(audin->subsystem);
|
||||
audin->subsystem = _strdup(subsystem);
|
||||
|
||||
if (!audin->subsystem)
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "_strdup failed!");
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
@ -729,7 +763,7 @@ static UINT audin_set_device_name(AUDIN_PLUGIN* audin, char* device_name)
|
||||
|
||||
if (!audin->device_name)
|
||||
{
|
||||
WLog_ERR(TAG, "_strdup failed!");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "_strdup failed!");
|
||||
return ERROR_NOT_ENOUGH_MEMORY;
|
||||
}
|
||||
|
||||
@ -776,7 +810,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
|
||||
{
|
||||
if ((error = audin_set_subsystem(audin, arg->Value)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_set_subsystem failed with error %"PRIu32"!", error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem failed with error %"PRIu32"!", error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -784,7 +818,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
|
||||
{
|
||||
if ((error = audin_set_device_name(audin, arg->Value)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_set_device_name failed with error %"PRIu32"!", error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name failed with error %"PRIu32"!", error);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
@ -882,6 +916,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
|
||||
audin->log = WLog_Get(TAG);
|
||||
audin->attached = TRUE;
|
||||
audin->iface.Initialize = audin_plugin_initialize;
|
||||
audin->iface.Connected = NULL;
|
||||
@ -901,10 +936,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
|
||||
if (audin->subsystem)
|
||||
{
|
||||
if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
|
||||
if ((error = audin_load_device_plugin(audin, audin->subsystem, args)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %"PRIu32"!",
|
||||
audin->subsystem, error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!",
|
||||
audin->subsystem, error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -914,18 +949,18 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
{
|
||||
if ((error = audin_set_subsystem(audin, entry->subsystem)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %"PRIu32"!",
|
||||
entry->subsystem, error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem for %s failed with error %"PRIu32"!",
|
||||
entry->subsystem, error);
|
||||
}
|
||||
else if ((error = audin_set_device_name(audin, entry->device)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_set_device_name for %s failed with error %"PRIu32"!",
|
||||
entry->subsystem, error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name for %s failed with error %"PRIu32"!",
|
||||
entry->subsystem, error);
|
||||
}
|
||||
else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
|
||||
else if ((error = audin_load_device_plugin(audin, audin->subsystem, args)))
|
||||
{
|
||||
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %"PRIu32"!",
|
||||
entry->subsystem, error);
|
||||
WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!",
|
||||
entry->subsystem, error);
|
||||
}
|
||||
|
||||
entry++;
|
||||
@ -933,7 +968,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||
}
|
||||
|
||||
if (audin->device == NULL)
|
||||
WLog_ERR(TAG, "no sound device.");
|
||||
WLog_Print(audin->log, WLOG_ERROR, "no sound device.");
|
||||
|
||||
error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
|
||||
out:
|
||||
|
@ -400,14 +400,15 @@ static UINT audin_pulse_close(IAudinDevice* device)
|
||||
{
|
||||
AudinPulseDevice* pulse = (AudinPulseDevice*) device;
|
||||
|
||||
if (!pulse->context || !pulse->stream)
|
||||
return ERROR_INVALID_PARAMETER;
|
||||
if (pulse->stream)
|
||||
{
|
||||
pa_threaded_mainloop_lock(pulse->mainloop);
|
||||
pa_stream_disconnect(pulse->stream);
|
||||
pa_stream_unref(pulse->stream);
|
||||
pulse->stream = NULL;
|
||||
pa_threaded_mainloop_unlock(pulse->mainloop);
|
||||
}
|
||||
|
||||
pa_threaded_mainloop_lock(pulse->mainloop);
|
||||
pa_stream_disconnect(pulse->stream);
|
||||
pa_stream_unref(pulse->stream);
|
||||
pulse->stream = NULL;
|
||||
pa_threaded_mainloop_unlock(pulse->mainloop);
|
||||
pulse->receive = NULL;
|
||||
pulse->user_data = NULL;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user