Merge pull request #2198 from awakecoding/master

Shadow Pointers, X11 XAllocColor Fix, TSMF Cleanup, Cliprdr Update
This commit is contained in:
Marc-André Moreau
2014-11-11 11:49:28 -05:00
47 changed files with 2109 additions and 1386 deletions

View File

@@ -28,7 +28,6 @@
#include <winpr/crt.h>
#include <freerdp/channels/log.h>
#include <freerdp/utils/event.h>
#include <freerdp/client/tsmf.h>
#include <libavcodec/avcodec.h>
@@ -83,11 +82,11 @@ typedef struct _TSMFFFmpegDecoder
UINT32 decoded_size_max;
} TSMFFFmpegDecoder;
static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder *decoder)
static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder* decoder)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
mdecoder->codec_context = avcodec_alloc_context3(NULL);
if(!mdecoder->codec_context)
if (!mdecoder->codec_context)
{
WLog_ERR(TAG, "avcodec_alloc_context failed.");
return FALSE;
@@ -95,9 +94,9 @@ static BOOL tsmf_ffmpeg_init_context(ITSMFDecoder *decoder)
return TRUE;
}
static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type)
static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
mdecoder->codec_context->width = media_type->Width;
mdecoder->codec_context->height = media_type->Height;
mdecoder->codec_context->bit_rate = media_type->BitRate;
@@ -107,9 +106,9 @@ static BOOL tsmf_ffmpeg_init_video_stream(ITSMFDecoder *decoder, const TS_AM_MED
return TRUE;
}
static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type)
static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
mdecoder->codec_context->sample_rate = media_type->SamplesPerSecond.Numerator;
mdecoder->codec_context->bit_rate = media_type->BitRate;
mdecoder->codec_context->channels = media_type->Channels;
@@ -134,34 +133,34 @@ static BOOL tsmf_ffmpeg_init_audio_stream(ITSMFDecoder *decoder, const TS_AM_MED
return TRUE;
}
static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYPE *media_type)
static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYPE *media_type)
{
BYTE *p;
UINT32 size;
const BYTE *s;
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id);
if(!mdecoder->codec)
if (!mdecoder->codec)
{
WLog_ERR(TAG, "avcodec_find_decoder failed.");
return FALSE;
}
mdecoder->codec_context->codec_id = mdecoder->codec_id;
mdecoder->codec_context->codec_type = mdecoder->media_type;
if(mdecoder->media_type == AVMEDIA_TYPE_VIDEO)
if (mdecoder->media_type == AVMEDIA_TYPE_VIDEO)
{
if(!tsmf_ffmpeg_init_video_stream(decoder, media_type))
if (!tsmf_ffmpeg_init_video_stream(decoder, media_type))
return FALSE;
}
else
if(mdecoder->media_type == AVMEDIA_TYPE_AUDIO)
if (mdecoder->media_type == AVMEDIA_TYPE_AUDIO)
{
if(!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type))
return FALSE;
}
if(media_type->ExtraData)
if (media_type->ExtraData)
{
if(media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
if (media_type->SubType == TSMF_SUB_TYPE_AVC1 &&
media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO)
{
/* The extradata format that FFmpeg uses is following CodecPrivate in Matroska.
@@ -195,15 +194,15 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder *decoder, const TS_AM_MEDIA_TYP
memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8);
}
}
if(mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED)
if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED)
mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED;
return TRUE;
}
static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder *decoder)
static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder* decoder)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0)
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
if (avcodec_open2(mdecoder->codec_context, mdecoder->codec, NULL) < 0)
{
WLog_ERR(TAG, "avcodec_open2 failed.");
return FALSE;
@@ -212,9 +211,9 @@ static BOOL tsmf_ffmpeg_prepare(ITSMFDecoder *decoder)
return TRUE;
}
static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type)
static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE *media_type)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
switch(media_type->MajorType)
{
case TSMF_MAJOR_TYPE_VIDEO:
@@ -254,7 +253,7 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *medi
/* For AAC the pFormat is a HEAACWAVEINFO struct, and the codec data
is at the end of it. See
http://msdn.microsoft.com/en-us/library/dd757806.aspx */
if(media_type->ExtraData)
if (media_type->ExtraData)
{
media_type->ExtraData += 12;
media_type->ExtraDataSize -= 12;
@@ -270,18 +269,18 @@ static BOOL tsmf_ffmpeg_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *medi
default:
return FALSE;
}
if(!tsmf_ffmpeg_init_context(decoder))
if (!tsmf_ffmpeg_init_context(decoder))
return FALSE;
if(!tsmf_ffmpeg_init_stream(decoder, media_type))
if (!tsmf_ffmpeg_init_stream(decoder, media_type))
return FALSE;
if(!tsmf_ffmpeg_prepare(decoder))
if (!tsmf_ffmpeg_prepare(decoder))
return FALSE;
return TRUE;
}
static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
int decoded;
int len;
AVFrame *frame;
@@ -294,12 +293,12 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder *decoder, const BYTE *data, UI
av_init_packet(&pkt);
pkt.data = (BYTE *) data;
pkt.size = data_size;
if(extensions & TSMM_SAMPLE_EXT_CLEANPOINT)
if (extensions & TSMM_SAMPLE_EXT_CLEANPOINT)
pkt.flags |= AV_PKT_FLAG_KEY;
len = avcodec_decode_video2(mdecoder->codec_context, mdecoder->frame, &decoded, &pkt);
}
#endif
if(len < 0)
if (len < 0)
{
WLog_ERR(TAG, "data_size %d, avcodec_decode_video failed (%d)", data_size, len);
ret = FALSE;
@@ -334,9 +333,9 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder *decoder, const BYTE *data, UI
return ret;
}
static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
int len;
int frame_size;
UINT32 src_size;
@@ -349,11 +348,11 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI
for(i = 0; i < data_size; i++)
{
WLog_DBG(TAG, ("%02X ", data[i]));
if(i % 16 == 15)
if (i % 16 == 15)
WLog_DBG(TAG, ("\n"));
}
#endif
if(mdecoder->decoded_size_max == 0)
if (mdecoder->decoded_size_max == 0)
mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16;
mdecoder->decoded_data = malloc(mdecoder->decoded_size_max);
ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size_max);
@@ -365,12 +364,12 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI
while(src_size > 0)
{
/* Ensure enough space for decoding */
if(mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
if (mdecoder->decoded_size_max - mdecoder->decoded_size < MAX_AUDIO_FRAME_SIZE)
{
mdecoder->decoded_size_max = mdecoder->decoded_size_max * 2 + 16;
mdecoder->decoded_data = realloc(mdecoder->decoded_data, mdecoder->decoded_size_max);
dst = (BYTE *)(((uintptr_t)mdecoder->decoded_data + 15) & ~ 0x0F);
if(dst - mdecoder->decoded_data != dst_offset)
if (dst - mdecoder->decoded_data != dst_offset)
{
/* re-align the memory if the alignment has changed after realloc */
memmove(dst, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
@@ -391,7 +390,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI
pkt.data = (BYTE *) src;
pkt.size = src_size;
len = avcodec_decode_audio4(mdecoder->codec_context, decoded_frame, &got_frame, &pkt);
if(len >= 0 && got_frame)
if (len >= 0 && got_frame)
{
frame_size = av_samples_get_buffer_size(NULL, mdecoder->codec_context->channels,
decoded_frame->nb_samples, mdecoder->codec_context->sample_fmt, 1);
@@ -400,7 +399,7 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI
av_free(decoded_frame);
}
#endif
if(len <= 0 || frame_size <= 0)
if (len <= 0 || frame_size <= 0)
{
WLog_ERR(TAG, "error decoding");
break;
@@ -410,13 +409,13 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI
mdecoder->decoded_size += frame_size;
dst += frame_size;
}
if(mdecoder->decoded_size == 0)
if (mdecoder->decoded_size == 0)
{
free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL;
}
else
if(dst_offset)
if (dst_offset)
{
/* move the aligned decoded data to original place */
memmove(mdecoder->decoded_data, mdecoder->decoded_data + dst_offset, mdecoder->decoded_size);
@@ -426,10 +425,10 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder *decoder, const BYTE *data, UI
return TRUE;
}
static BOOL tsmf_ffmpeg_decode(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
static BOOL tsmf_ffmpeg_decode(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(mdecoder->decoded_data)
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
if (mdecoder->decoded_data)
{
free(mdecoder->decoded_data);
mdecoder->decoded_data = NULL;
@@ -447,10 +446,10 @@ static BOOL tsmf_ffmpeg_decode(ITSMFDecoder *decoder, const BYTE *data, UINT32 d
}
}
static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder *decoder, UINT32 *size)
static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder* decoder, UINT32 *size)
{
BYTE *buf;
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
*size = mdecoder->decoded_size;
buf = mdecoder->decoded_data;
mdecoder->decoded_data = NULL;
@@ -458,10 +457,11 @@ static BYTE *tsmf_ffmpeg_get_decoded_data(ITSMFDecoder *decoder, UINT32 *size)
return buf;
}
static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder *decoder)
static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder* decoder)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
switch(mdecoder->codec_context->pix_fmt)
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
switch (mdecoder->codec_context->pix_fmt)
{
case PIX_FMT_YUV420P:
return RDP_PIXFMT_I420;
@@ -472,10 +472,11 @@ static UINT32 tsmf_ffmpeg_get_decoded_format(ITSMFDecoder *decoder)
}
}
static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder *decoder, UINT32 *width, UINT32 *height)
static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder* decoder, UINT32 *width, UINT32 *height)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0)
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
if (mdecoder->codec_context->width > 0 && mdecoder->codec_context->height > 0)
{
*width = mdecoder->codec_context->width;
*height = mdecoder->codec_context->height;
@@ -487,18 +488,18 @@ static BOOL tsmf_ffmpeg_get_decoded_dimension(ITSMFDecoder *decoder, UINT32 *wid
}
}
static void tsmf_ffmpeg_free(ITSMFDecoder *decoder)
static void tsmf_ffmpeg_free(ITSMFDecoder* decoder)
{
TSMFFFmpegDecoder *mdecoder = (TSMFFFmpegDecoder *) decoder;
if(mdecoder->frame)
TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder;
if (mdecoder->frame)
av_free(mdecoder->frame);
if(mdecoder->decoded_data)
if (mdecoder->decoded_data)
free(mdecoder->decoded_data);
if(mdecoder->codec_context)
if (mdecoder->codec_context)
{
if(mdecoder->prepared)
if (mdecoder->prepared)
avcodec_close(mdecoder->codec_context);
if(mdecoder->codec_context->extradata)
if (mdecoder->codec_context->extradata)
free(mdecoder->codec_context->extradata);
av_free(mdecoder->codec_context);
}
@@ -511,23 +512,29 @@ static BOOL initialized = FALSE;
#define freerdp_tsmf_client_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry
#endif
ITSMFDecoder *freerdp_tsmf_client_subsystem_entry(void)
ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void)
{
TSMFFFmpegDecoder *decoder;
if(!initialized)
TSMFFFmpegDecoder* decoder;
if (!initialized)
{
avcodec_register_all();
initialized = TRUE;
}
WLog_DBG(TAG, "TSMFDecoderEntry FFMPEG");
decoder = (TSMFFFmpegDecoder*) malloc(sizeof(TSMFFFmpegDecoder));
ZeroMemory(decoder, sizeof(TSMFFFmpegDecoder));
decoder = (TSMFFFmpegDecoder*) calloc(1, sizeof(TSMFFFmpegDecoder));
if (!decoder)
return NULL;
decoder->iface.SetFormat = tsmf_ffmpeg_set_format;
decoder->iface.Decode = tsmf_ffmpeg_decode;
decoder->iface.GetDecodedData = tsmf_ffmpeg_get_decoded_data;
decoder->iface.GetDecodedFormat = tsmf_ffmpeg_get_decoded_format;
decoder->iface.GetDecodedDimension = tsmf_ffmpeg_get_decoded_dimension;
decoder->iface.Free = tsmf_ffmpeg_free;
return (ITSMFDecoder *) decoder;
return (ITSMFDecoder*) decoder;
}

View File

@@ -18,8 +18,6 @@
* limitations under the License.
*/
#include <assert.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
@@ -61,29 +59,34 @@ struct X11Handle
Window subwin;
};
static const char *get_shm_id()
static const char* get_shm_id()
{
static char shm_id[64];
snprintf(shm_id, sizeof(shm_id), "com.freerdp.xfreerpd.tsmf_%016X", GetCurrentProcessId());
return shm_id;
}
const char *tsmf_platform_get_video_sink(void)
const char* tsmf_platform_get_video_sink(void)
{
return "xvimagesink";
}
const char *tsmf_platform_get_audio_sink(void)
const char* tsmf_platform_get_audio_sink(void)
{
return "autoaudiosink";
}
int tsmf_platform_create(TSMFGstreamerDecoder *decoder)
int tsmf_platform_create(TSMFGstreamerDecoder* decoder)
{
struct X11Handle *hdl;
assert(decoder);
assert(!decoder->platform);
hdl = malloc(sizeof(struct X11Handle));
struct X11Handle* hdl;
if (!decoder)
return -1;
if (decoder->platform)
return -1;
hdl = calloc(1, sizeof(struct X11Handle));
if (!hdl)
{
@@ -91,7 +94,6 @@ int tsmf_platform_create(TSMFGstreamerDecoder *decoder)
return -1;
}
memset(hdl, 0, sizeof(struct X11Handle));
decoder->platform = hdl;
hdl->shmid = shm_open(get_shm_id(), O_RDWR, PROT_READ | PROT_WRITE);;
@@ -101,9 +103,11 @@ int tsmf_platform_create(TSMFGstreamerDecoder *decoder)
return -2;
}
else
{
hdl->xfwin = mmap(0, sizeof(void *), PROT_READ | PROT_WRITE, MAP_SHARED, hdl->shmid, 0);
}
if (hdl->xfwin == (int *)-1)
if (hdl->xfwin == (int*)-1)
{
WLog_ERR(TAG, "shmat failed!");
return -3;
@@ -120,22 +124,30 @@ int tsmf_platform_create(TSMFGstreamerDecoder *decoder)
return 0;
}
int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder)
int tsmf_platform_set_format(TSMFGstreamerDecoder* decoder)
{
assert(decoder);
if (!decoder)
return -1;
if (decoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
{
}
return 0;
}
int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder)
int tsmf_platform_register_handler(TSMFGstreamerDecoder* decoder)
{
assert(decoder);
assert(decoder->pipe);
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe));
GstBus* bus;
if (!decoder)
return -1;
if (!decoder->pipe)
return -1;
bus = gst_pipeline_get_bus(GST_PIPELINE(decoder->pipe));
if (!bus)
{
@@ -146,9 +158,9 @@ int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder)
return 0;
}
int tsmf_platform_free(TSMFGstreamerDecoder *decoder)
int tsmf_platform_free(TSMFGstreamerDecoder* decoder)
{
struct X11Handle *hdl = decoder->platform;
struct X11Handle* hdl = decoder->platform;
if (!hdl)
return -1;
@@ -157,18 +169,21 @@ int tsmf_platform_free(TSMFGstreamerDecoder *decoder)
XCloseDisplay(hdl->disp);
if (hdl->xfwin)
munmap(0, sizeof(void *));
munmap(0, sizeof(void*));
if (hdl->shmid >= 0)
close(hdl->shmid);
free(hdl);
decoder->platform = NULL;
return 0;
}
int tsmf_window_create(TSMFGstreamerDecoder *decoder)
int tsmf_window_create(TSMFGstreamerDecoder* decoder)
{
struct X11Handle* hdl;
if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
{
decoder->ready = TRUE;
@@ -181,9 +196,14 @@ int tsmf_window_create(TSMFGstreamerDecoder *decoder)
#else
GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink);
#endif
struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
assert(decoder);
assert(hdl);
if (!decoder)
return -1;
if (!decoder->platform)
return -1;
hdl = (struct X11Handle*) decoder->platform;
if (!hdl->subwin)
{
@@ -217,11 +237,15 @@ int tsmf_window_create(TSMFGstreamerDecoder *decoder)
}
}
int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, int width,
int tsmf_window_resize(TSMFGstreamerDecoder* decoder, int x, int y, int width,
int height, int nr_rects, RDP_RECT *rects)
{
struct X11Handle* hdl;
if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
{
return -3;
}
else
{
#if GST_VERSION_MAJOR > 0
@@ -229,10 +253,15 @@ int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, int width,
#else
GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink);
#endif
struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
if (!decoder)
return -1;
if (!decoder->platform)
return -1;
hdl = (struct X11Handle*) decoder->platform;
DEBUG_TSMF("resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height);
assert(decoder);
assert(hdl);
#if GST_VERSION_MAJOR > 0
if (!gst_video_overlay_set_render_rectangle(overlay, 0, 0, width, height))
@@ -280,28 +309,37 @@ int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y, int width,
}
}
int tsmf_window_pause(TSMFGstreamerDecoder *decoder)
int tsmf_window_pause(TSMFGstreamerDecoder* decoder)
{
assert(decoder);
if (!decoder)
return -1;
return 0;
}
int tsmf_window_resume(TSMFGstreamerDecoder *decoder)
int tsmf_window_resume(TSMFGstreamerDecoder* decoder)
{
assert(decoder);
if (!decoder)
return -1;
return 0;
}
int tsmf_window_destroy(TSMFGstreamerDecoder *decoder)
int tsmf_window_destroy(TSMFGstreamerDecoder* decoder)
{
struct X11Handle *hdl = (struct X11Handle *)decoder->platform;
struct X11Handle* hdl;
decoder->ready = FALSE;
if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO)
return -3;
assert(decoder);
assert(hdl);
if (!decoder)
return -1;
if (!decoder->platform)
return -1;
hdl = (struct X11Handle*) decoder->platform;
if (hdl->subwin)
{

View File

@@ -43,14 +43,15 @@
#include <inttypes.h>
#endif
static BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder *mdecoder);
static void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder *mdecoder);
static int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder *mdecoder,
static BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder* mdecoder);
static void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder* mdecoder);
static int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder* mdecoder,
GstState desired_state);
const char *get_type(TSMFGstreamerDecoder *mdecoder)
const char* get_type(TSMFGstreamerDecoder* mdecoder)
{
assert(mdecoder);
if (!mdecoder)
return NULL;
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
return "VIDEO";
@@ -60,28 +61,28 @@ const char *get_type(TSMFGstreamerDecoder *mdecoder)
static void tsmf_gstreamer_enough_data(GstAppSrc *src, gpointer user_data)
{
TSMFGstreamerDecoder *mdecoder = user_data;
(void)mdecoder;
TSMFGstreamerDecoder* mdecoder = user_data;
(void) mdecoder;
DEBUG_TSMF("%s", get_type(mdecoder));
}
static void tsmf_gstreamer_need_data(GstAppSrc *src, guint length, gpointer user_data)
{
TSMFGstreamerDecoder *mdecoder = user_data;
(void)mdecoder;
TSMFGstreamerDecoder* mdecoder = user_data;
(void) mdecoder;
DEBUG_TSMF("%s length=%lu", get_type(mdecoder), length);
}
static gboolean tsmf_gstreamer_seek_data(GstAppSrc *src, guint64 offset, gpointer user_data)
{
TSMFGstreamerDecoder *mdecoder = user_data;
(void)mdecoder;
TSMFGstreamerDecoder* mdecoder = user_data;
(void) mdecoder;
DEBUG_TSMF("%s offset=%llu", get_type(mdecoder), offset);
if (!mdecoder->paused)
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED);
gst_app_src_end_of_stream((GstAppSrc *)mdecoder->src);
gst_app_src_end_of_stream((GstAppSrc*) mdecoder->src);
if (!mdecoder->paused)
tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PLAYING);
@@ -100,11 +101,11 @@ static inline const GstClockTime tsmf_gstreamer_timestamp_ms_to_gst(UINT64 ms_ti
return (GstClockTime)(ms_timestamp * 100);
}
int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder *mdecoder, GstState desired_state)
int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder* mdecoder, GstState desired_state)
{
GstStateChangeReturn state_change;
const char *name;
const char *sname = get_type(mdecoder);
const char* name;
const char* sname = get_type(mdecoder);
if (!mdecoder)
return 0;
@@ -120,24 +121,33 @@ int tsmf_gstreamer_pipeline_set_state(TSMFGstreamerDecoder *mdecoder, GstState d
state_change = gst_element_set_state(mdecoder->pipe, desired_state);
if (state_change == GST_STATE_CHANGE_FAILURE)
{
WLog_ERR(TAG, "%s: (%s) GST_STATE_CHANGE_FAILURE.", sname, name);
}
else if (state_change == GST_STATE_CHANGE_ASYNC)
{
WLog_ERR(TAG, "%s: (%s) GST_STATE_CHANGE_ASYNC.", sname, name);
mdecoder->state = desired_state;
}
else
{
mdecoder->state = desired_state;
}
return 0;
}
static GstBuffer *tsmf_get_buffer_from_data(const void *raw_data, gsize size)
static GstBuffer* tsmf_get_buffer_from_data(const void* raw_data, gsize size)
{
GstBuffer *buffer;
GstBuffer* buffer;
gpointer data;
assert(raw_data);
assert(size > 0);
if (!raw_data)
return NULL;
if (size < 1)
return NULL;
data = g_malloc(size);
if (!data)
@@ -146,7 +156,8 @@ static GstBuffer *tsmf_get_buffer_from_data(const void *raw_data, gsize size)
return NULL;
}
memcpy(data, raw_data, size);
CopyMemory(data, raw_data, size);
#if GST_VERSION_MAJOR > 0
buffer = gst_buffer_new_wrapped(data, size);
#else
@@ -163,12 +174,13 @@ static GstBuffer *tsmf_get_buffer_from_data(const void *raw_data, gsize size)
GST_BUFFER_SIZE(buffer) = size;
GST_BUFFER_DATA(buffer) = GST_BUFFER_MALLOCDATA(buffer);
#endif
return buffer;
}
static BOOL tsmf_gstreamer_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *media_type)
static BOOL tsmf_gstreamer_set_format(ITSMFDecoder* decoder, TS_AM_MEDIA_TYPE* media_type)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder*) decoder;
if (!mdecoder)
return FALSE;
@@ -377,7 +389,6 @@ static BOOL tsmf_gstreamer_set_format(ITSMFDecoder *decoder, TS_AM_MEDIA_TYPE *m
void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder* mdecoder)
{
//Cleaning up elements
if (!mdecoder || !mdecoder->pipe)
return;
@@ -393,11 +404,11 @@ void tsmf_gstreamer_clean_up(TSMFGstreamerDecoder* mdecoder)
mdecoder->src = NULL;
}
BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder *mdecoder)
BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder* mdecoder)
{
const char *appsrc = "appsrc name=source ! decodebin name=decoder !";
const char *video = "autovideoconvert ! videoscale !";
const char *audio = "audioconvert ! audiorate ! audioresample ! volume name=audiovolume !";
const char* appsrc = "appsrc name=source ! decodebin name=decoder !";
const char* video = "autovideoconvert ! videoscale !";
const char* audio = "audioconvert ! audiorate ! audioresample ! volume name=audiovolume !";
char pipeline[1024];
if (!mdecoder)
@@ -467,16 +478,16 @@ BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder *mdecoder)
mdecoder->pipeline_start_time_valid = 0;
mdecoder->shutdown = 0;
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(mdecoder->pipe), GST_DEBUG_GRAPH_SHOW_ALL, get_type(mdecoder));
GST_DEBUG_BIN_TO_DOT_FILE(GST_BIN(mdecoder->pipe), GST_DEBUG_GRAPH_SHOW_ALL, get_type(mdecoder));
return TRUE;
}
static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions,
static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder* decoder, const BYTE *data, UINT32 data_size, UINT32 extensions,
UINT64 start_time, UINT64 end_time, UINT64 duration)
{
GstBuffer *gst_buf;
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder;
UINT64 sample_time = tsmf_gstreamer_timestamp_ms_to_gst(start_time);
UINT64 sample_duration = tsmf_gstreamer_timestamp_ms_to_gst(duration);
@@ -570,9 +581,9 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder *decoder, const BYTE *data, UIN
return TRUE;
}
static void tsmf_gstreamer_change_volume(ITSMFDecoder *decoder, UINT32 newVolume, UINT32 muted)
static void tsmf_gstreamer_change_volume(ITSMFDecoder* decoder, UINT32 newVolume, UINT32 muted)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder;
if (!mdecoder || !mdecoder->pipe)
return;
@@ -595,9 +606,9 @@ static void tsmf_gstreamer_change_volume(ITSMFDecoder *decoder, UINT32 newVolume
g_object_set(mdecoder->volume, "volume", mdecoder->gstVolume, NULL);
}
static void tsmf_gstreamer_control(ITSMFDecoder *decoder, ITSMFControlMsg control_msg, UINT32 *arg)
static void tsmf_gstreamer_control(ITSMFDecoder* decoder, ITSMFControlMsg control_msg, UINT32 *arg)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder;
if (!mdecoder)
return;
@@ -659,9 +670,9 @@ static void tsmf_gstreamer_control(ITSMFDecoder *decoder, ITSMFControlMsg contro
WLog_ERR(TAG, "Unknown control message %08x", control_msg);
}
static BOOL tsmf_gstreamer_buffer_filled(ITSMFDecoder *decoder)
static BOOL tsmf_gstreamer_buffer_filled(ITSMFDecoder* decoder)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder;
DEBUG_TSMF("");
if (!mdecoder)
@@ -673,9 +684,9 @@ static BOOL tsmf_gstreamer_buffer_filled(ITSMFDecoder *decoder)
return clbuff >= buff_max ? TRUE : FALSE;
}
static void tsmf_gstreamer_free(ITSMFDecoder *decoder)
static void tsmf_gstreamer_free(ITSMFDecoder* decoder)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder;
DEBUG_TSMF("%s", get_type(mdecoder));
if (mdecoder)
@@ -687,15 +698,15 @@ static void tsmf_gstreamer_free(ITSMFDecoder *decoder)
gst_caps_unref(mdecoder->gst_caps);
tsmf_platform_free(mdecoder);
memset(mdecoder, 0, sizeof(TSMFGstreamerDecoder));
ZeroMemory(mdecoder, sizeof(TSMFGstreamerDecoder));
free(mdecoder);
mdecoder = NULL;
}
}
static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder *decoder)
static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder* decoder)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder;
if (!mdecoder)
return 0;
@@ -716,31 +727,33 @@ static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder *decoder)
return pos/100;
}
static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder *decoder,
static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder* decoder,
int newX, int newY, int newWidth, int newHeight, int numRectangles,
RDP_RECT *rectangles)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder;
DEBUG_TSMF("x=%d, y=%d, w=%d, h=%d, rect=%d", newX, newY, newWidth,
newHeight, numRectangles);
if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO)
{
tsmf_window_resize(mdecoder, newX, newY, newWidth, newHeight,
numRectangles, rectangles);
}
}
BOOL tsmf_gstreamer_ack(ITSMFDecoder *decoder, BOOL (*cb)(void *, BOOL), void *stream)
BOOL tsmf_gstreamer_ack(ITSMFDecoder* decoder, BOOL (*cb)(void *, BOOL), void *stream)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder;
DEBUG_TSMF("");
mdecoder->ack_cb = cb;
mdecoder->stream = stream;
return TRUE;
}
BOOL tsmf_gstreamer_sync(ITSMFDecoder *decoder, void (*cb)(void *), void *stream)
BOOL tsmf_gstreamer_sync(ITSMFDecoder* decoder, void (*cb)(void *), void *stream)
{
TSMFGstreamerDecoder *mdecoder = (TSMFGstreamerDecoder *) decoder;
TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder;
DEBUG_TSMF("");
mdecoder->sync_cb = NULL;
mdecoder->stream = stream;
@@ -751,7 +764,7 @@ BOOL tsmf_gstreamer_sync(ITSMFDecoder *decoder, void (*cb)(void *), void *stream
#define freerdp_tsmf_client_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry
#endif
ITSMFDecoder *freerdp_tsmf_client_subsystem_entry(void)
ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void)
{
TSMFGstreamerDecoder *decoder;
@@ -760,8 +773,11 @@ ITSMFDecoder *freerdp_tsmf_client_subsystem_entry(void)
gst_init(NULL, NULL);
}
decoder = malloc(sizeof(TSMFGstreamerDecoder));
memset(decoder, 0, sizeof(TSMFGstreamerDecoder));
decoder = calloc(1, sizeof(TSMFGstreamerDecoder));
if (!decoder)
return NULL;
decoder->iface.SetFormat = tsmf_gstreamer_set_format;
decoder->iface.Decode = NULL;
decoder->iface.GetDecodedData = NULL;
@@ -780,6 +796,8 @@ ITSMFDecoder *freerdp_tsmf_client_subsystem_entry(void)
decoder->gstVolume = 0.5;
decoder->gstMuted = FALSE;
decoder->state = GST_STATE_VOID_PENDING; /* No real state yet */
tsmf_platform_create(decoder);
return (ITSMFDecoder *) decoder;
return (ITSMFDecoder*) decoder;
}

View File

@@ -59,25 +59,25 @@ typedef struct _TSMFGstreamerDecoder
} TSMFGstreamerDecoder;
const char *get_type(TSMFGstreamerDecoder *mdecoder);
const char* get_type(TSMFGstreamerDecoder* mdecoder);
const char *tsmf_platform_get_video_sink(void);
const char *tsmf_platform_get_audio_sink(void);
const char* tsmf_platform_get_video_sink(void);
const char* tsmf_platform_get_audio_sink(void);
int tsmf_platform_create(TSMFGstreamerDecoder *decoder);
int tsmf_platform_set_format(TSMFGstreamerDecoder *decoder);
int tsmf_platform_register_handler(TSMFGstreamerDecoder *decoder);
int tsmf_platform_free(TSMFGstreamerDecoder *decoder);
int tsmf_platform_create(TSMFGstreamerDecoder* decoder);
int tsmf_platform_set_format(TSMFGstreamerDecoder* decoder);
int tsmf_platform_register_handler(TSMFGstreamerDecoder* decoder);
int tsmf_platform_free(TSMFGstreamerDecoder* decoder);
int tsmf_window_create(TSMFGstreamerDecoder *decoder);
int tsmf_window_resize(TSMFGstreamerDecoder *decoder, int x, int y,
int tsmf_window_create(TSMFGstreamerDecoder* decoder);
int tsmf_window_resize(TSMFGstreamerDecoder* decoder, int x, int y,
int width, int height, int nr_rect, RDP_RECT *visible);
int tsmf_window_destroy(TSMFGstreamerDecoder *decoder);
int tsmf_window_destroy(TSMFGstreamerDecoder* decoder);
int tsmf_window_pause(TSMFGstreamerDecoder *decoder);
int tsmf_window_resume(TSMFGstreamerDecoder *decoder);
int tsmf_window_pause(TSMFGstreamerDecoder* decoder);
int tsmf_window_resume(TSMFGstreamerDecoder* decoder);
BOOL tsmf_gstreamer_add_pad(TSMFGstreamerDecoder *mdecoder);
void tsmf_gstreamer_remove_pad(TSMFGstreamerDecoder *mdecoder);
BOOL tsmf_gstreamer_add_pad(TSMFGstreamerDecoder* mdecoder);
void tsmf_gstreamer_remove_pad(TSMFGstreamerDecoder* mdecoder);
#endif

View File

@@ -34,12 +34,12 @@ static ITSMFAudioDevice* tsmf_load_audio_device_by_name(const char* name, const
entry = (TSMF_AUDIO_DEVICE_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "audio", 0);
if (entry == NULL)
if (!entry)
return NULL;
audio = entry();
if (audio == NULL)
if (!audio)
{
WLog_ERR(TAG, "failed to call export function in %s", name);
return NULL;

View File

@@ -22,13 +22,11 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <winpr/print.h>
#include "tsmf_decoder.h"
#include "tsmf_constants.h"
#include "tsmf_types.h"
@@ -176,40 +174,64 @@ static const TSMFMediaTypeMap tsmf_sub_type_map[] =
},
/* E436EB81-524F-11CE-9F53-0020AF0BA770 */
/*
{
{ 0x81, 0xEB, 0x36, 0xE4, 0x4F, 0x52, 0xCE, 0x11, 0x9F, 0x53, 0x00, 0x20, 0xAF, 0x0B, 0xA7, 0x70 },
"MEDIASUBTYPE_MP1V",
TSMF_SUB_TYPE_MP1V
},
*/
/* 00000050-0000-0010-8000-00AA00389B71 */
/*
{
{ 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
"MEDIASUBTYPE_MP1A",
TSMF_SUB_TYPE_MP1A
},
*/
/* E06D802C-DB46-11CF-B4D1-00805F6CBBEA */
/*
{
{ 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA },
"MEDIASUBTYPE_DOLBY_AC3",
TSMF_SUB_TYPE_AC3
},
*/
/* 32595559-0000-0010-8000-00AA00389B71 */
/*
{
{ 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71 },
"MEDIASUBTYPE_YUY2",
TSMF_SUB_TYPE_YUY2
},
*/
/* Opencodec IDS */
{
{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71},
"MEDIASUBTYPE_FLAC",
TSMF_SUB_TYPE_FLAC
},
{
{0x61, 0x34, 0x70, 0x6D, 0x7A, 0x76, 0x4D, 0x49, 0xB4, 0x78, 0xF2, 0x9D, 0x25, 0xDC, 0x90, 0x37},
"MEDIASUBTYPE_OGG",
TSMF_SUB_TYPE_OGG
},
{
{0x4D, 0x34, 0x53, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71},
"MEDIASUBTYPE_H263",
TSMF_SUB_TYPE_H263
},
/* WebMMF codec IDS */
{
{0x56, 0x50, 0x38, 0x30, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71},
"MEDIASUBTYPE_VP8",
TSMF_SUB_TYPE_VP8
},
{
{0x0B, 0xD1, 0x2F, 0x8D, 0x41, 0x58, 0x6B, 0x4A, 0x89, 0x05, 0x58, 0x8F, 0xEC, 0x1A, 0xDE, 0xD9},
"MEDIASUBTYPE_OGG",
TSMF_SUB_TYPE_OGG
},
{
{ 0 },
@@ -525,13 +547,30 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s)
return ret;
}
BOOL tsmf_codec_check_media_type(wStream* s)
BOOL tsmf_codec_check_media_type(const char* decoder_name, wStream* s)
{
BYTE* m;
BOOL ret;
TS_AM_MEDIA_TYPE mediatype;
Stream_GetPointer(s, m);
ret = tsmf_codec_parse_media_type(&mediatype, s);
Stream_SetPointer(s, m);
if (ret)
{
ITSMFDecoder* decoder = tsmf_load_decoder(decoder_name, &mediatype);
if (!decoder)
{
WLog_WARN(TAG, "Format not supported by decoder %s", decoder_name);
ret = FALSE;
}
else
{
decoder->Free(decoder);
}
}
return ret;
}

View File

@@ -23,7 +23,7 @@
#include "tsmf_types.h"
BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s);
BOOL tsmf_codec_check_media_type(wStream* s);
BOOL tsmf_codec_check_media_type(const char* decoder_name, wStream* s);
#endif

View File

@@ -118,6 +118,13 @@
#define TSMF_SUB_TYPE_MP43 17
#define TSMF_SUB_TYPE_MP4S 18
#define TSMF_SUB_TYPE_MP42 19
#define TSMF_SUB_TYPE_OGG 20
#define TSMF_SUB_TYPE_SPEEX 21
#define TSMF_SUB_TYPE_THEORA 22
#define TSMF_SUB_TYPE_FLAC 23
#define TSMF_SUB_TYPE_VP8 24
#define TSMF_SUB_TYPE_VP9 25
#define TSMF_SUB_TYPE_H263 26
/* FormatType */
#define TSMF_FORMAT_TYPE_UNKNOWN 0

View File

@@ -32,41 +32,51 @@
#include "tsmf_constants.h"
#include "tsmf_decoder.h"
static ITSMFDecoder *tsmf_load_decoder_by_name(const char *name, TS_AM_MEDIA_TYPE *media_type)
static ITSMFDecoder* tsmf_load_decoder_by_name(const char *name, TS_AM_MEDIA_TYPE *media_type)
{
ITSMFDecoder *decoder;
ITSMFDecoder* decoder;
TSMF_DECODER_ENTRY entry;
entry = (TSMF_DECODER_ENTRY) freerdp_load_channel_addin_entry("tsmf", (LPSTR) name, "decoder", 0);
if(entry == NULL)
if (!entry)
return NULL;
decoder = entry();
if(decoder == NULL)
if (!decoder)
{
WLog_ERR(TAG, "failed to call export function in %s", name);
return NULL;
}
if(!decoder->SetFormat(decoder, media_type))
if (!decoder->SetFormat(decoder, media_type))
{
decoder->Free(decoder);
decoder = NULL;
}
return decoder;
}
ITSMFDecoder *tsmf_load_decoder(const char *name, TS_AM_MEDIA_TYPE *media_type)
ITSMFDecoder* tsmf_load_decoder(const char* name, TS_AM_MEDIA_TYPE* media_type)
{
ITSMFDecoder *decoder = NULL;
if(name)
ITSMFDecoder* decoder = NULL;
if (name)
{
decoder = tsmf_load_decoder_by_name(name, media_type);
}
#if defined(WITH_GSTREAMER_1_0) || defined(WITH_GSTREAMER_0_10)
if(!decoder)
if (!decoder)
decoder = tsmf_load_decoder_by_name("gstreamer", media_type);
#endif
#if defined(WITH_FFMPEG)
if(!decoder)
if (!decoder)
decoder = tsmf_load_decoder_by_name("ffmpeg", media_type);
#endif
return decoder;
}

View File

@@ -37,18 +37,22 @@
#include "tsmf_ifman.h"
int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN *ifman)
int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman)
{
UINT32 CapabilityValue;
Stream_Read_UINT32(ifman->input, CapabilityValue);
DEBUG_TSMF("server CapabilityValue %d", CapabilityValue);
Stream_EnsureRemainingCapacity(ifman->output, 8);
Stream_Write_UINT32(ifman->output, 1); /* CapabilityValue */
Stream_Write_UINT32(ifman->output, 0); /* Result */
return 0;
}
int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman)
int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
{
UINT32 i;
UINT32 v;
@@ -56,17 +60,20 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman)
UINT32 CapabilityType;
UINT32 cbCapabilityLength;
UINT32 numHostCapabilities;
pos = Stream_GetPosition(ifman->output);
Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4);
Stream_Copy(ifman->output, ifman->input, ifman->input_size);
Stream_SetPosition(ifman->output, pos);
Stream_Read_UINT32(ifman->output, numHostCapabilities);
for(i = 0; i < numHostCapabilities; i++)
for (i = 0; i < numHostCapabilities; i++)
{
Stream_Read_UINT32(ifman->output, CapabilityType);
Stream_Read_UINT32(ifman->output, cbCapabilityLength);
pos = Stream_GetPosition(ifman->output);
switch(CapabilityType)
switch (CapabilityType)
{
case 1: /* Protocol version request */
Stream_Read_UINT32(ifman->output, v);
@@ -76,8 +83,7 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman)
Stream_Peek_UINT32(ifman->output, v);
DEBUG_TSMF("server supported platform %d", v);
/* Claim that we support both MF and DShow platforms. */
Stream_Write_UINT32(ifman->output,
MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW);
Stream_Write_UINT32(ifman->output, MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW);
break;
default:
WLog_ERR(TAG, "unknown capability type %d", CapabilityType);
@@ -85,63 +91,81 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN *ifman)
}
Stream_SetPosition(ifman->output, pos + cbCapabilityLength);
}
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0;
}
int tsmf_ifman_check_format_support_request(TSMF_IFMAN *ifman)
int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman)
{
UINT32 numMediaType;
UINT32 PlatformCookie;
UINT32 FormatSupported = 1;
Stream_Read_UINT32(ifman->input, PlatformCookie);
Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */
Stream_Read_UINT32(ifman->input, numMediaType);
DEBUG_TSMF("PlatformCookie %d numMediaType %d", PlatformCookie, numMediaType);
if(!tsmf_codec_check_media_type(ifman->input))
if (!tsmf_codec_check_media_type(ifman->decoder_name, ifman->input))
FormatSupported = 0;
if(FormatSupported)
if (FormatSupported)
DEBUG_TSMF("format ok.");
Stream_EnsureRemainingCapacity(ifman->output, 12);
Stream_Write_UINT32(ifman->output, FormatSupported);
Stream_Write_UINT32(ifman->output, PlatformCookie);
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0;
}
int tsmf_ifman_on_new_presentation(TSMF_IFMAN *ifman)
int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman)
{
int status = 0;
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation)
if (presentation)
{
DEBUG_TSMF("Presentation already exists");
ifman->output_pending = FALSE;
return 0;
}
presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback);
if(presentation == NULL)
if (!presentation)
status = 1;
else
tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device);
ifman->output_pending = TRUE;
return status;
}
int tsmf_ifman_add_stream(TSMF_IFMAN *ifman)
int tsmf_ifman_add_stream(TSMF_IFMAN* ifman)
{
UINT32 StreamId;
int status = 0;
TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation;
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
if(presentation == NULL)
if (!presentation)
{
status = 1;
}
@@ -150,14 +174,14 @@ int tsmf_ifman_add_stream(TSMF_IFMAN *ifman)
Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numMediaType */
stream = tsmf_stream_new(presentation, StreamId);
if(stream)
if (stream)
tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input);
}
ifman->output_pending = TRUE;
return status;
}
int tsmf_ifman_set_topology_request(TSMF_IFMAN *ifman)
int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman)
{
DEBUG_TSMF("");
Stream_EnsureRemainingCapacity(ifman->output, 8);
@@ -167,16 +191,20 @@ int tsmf_ifman_set_topology_request(TSMF_IFMAN *ifman)
return 0;
}
int tsmf_ifman_remove_stream(TSMF_IFMAN *ifman)
int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman)
{
int status = 0;
UINT32 StreamId;
TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation;
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
if(presentation == NULL)
if (!presentation)
{
status = 1;
}
@@ -184,12 +212,15 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN *ifman)
{
Stream_Read_UINT32(ifman->input, StreamId);
stream = tsmf_stream_find_by_id(presentation, StreamId);
if(stream)
if (stream)
tsmf_stream_free(stream);
else
status = 1;
}
ifman->output_pending = TRUE;
return status;
}
@@ -202,16 +233,20 @@ float tsmf_stream_read_float(wStream *s)
return fValue;
}
int tsmf_ifman_set_source_video_rect(TSMF_IFMAN *ifman)
int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman)
{
int status = 0;
float Left, Top;
float Right, Bottom;
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
if(!presentation)
if (!presentation)
{
status = 1;
}
@@ -224,31 +259,39 @@ int tsmf_ifman_set_source_video_rect(TSMF_IFMAN *ifman)
DEBUG_TSMF("SetSourceVideoRect: Left: %f Top: %f Right: %f Bottom: %f",
Left, Top, Right, Bottom);
}
ifman->output_pending = TRUE;
return status;
}
int tsmf_ifman_shutdown_presentation(TSMF_IFMAN *ifman)
int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation)
if (presentation)
tsmf_presentation_free(presentation);
else
WLog_ERR(TAG, "unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 4);
Stream_Write_UINT32(ifman->output, 0); /* Result */
ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB;
return 0;
}
int tsmf_ifman_on_stream_volume(TSMF_IFMAN *ifman)
int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("on stream volume");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation)
if (presentation)
{
UINT32 newVolume;
UINT32 muted;
@@ -263,16 +306,21 @@ int tsmf_ifman_on_stream_volume(TSMF_IFMAN *ifman)
{
WLog_ERR(TAG, "unknown presentation id");
}
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_on_channel_volume(TSMF_IFMAN *ifman)
int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("on channel volume");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation)
if (presentation)
{
UINT32 channelVolume;
UINT32 changedChannel;
@@ -282,20 +330,22 @@ int tsmf_ifman_on_channel_volume(TSMF_IFMAN *ifman)
Stream_Read_UINT32(ifman->input, changedChannel);
DEBUG_TSMF("on stream volume: changed channel=[%d]", changedChannel);
}
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_set_video_window(TSMF_IFMAN *ifman)
int tsmf_ifman_set_video_window(TSMF_IFMAN* ifman)
{
DEBUG_TSMF("");
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_update_geometry_info(TSMF_IFMAN *ifman)
int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
UINT32 numGeometryInfo;
UINT32 Left;
UINT32 Top;
@@ -321,17 +371,17 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN *ifman)
num_rects = cbVisibleRect / 16;
DEBUG_TSMF("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d",
numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects);
if(presentation == NULL)
if (presentation == NULL)
{
error = 1;
}
else
{
if(num_rects > 0)
if (num_rects > 0)
{
rects = (RDP_RECT *) malloc(sizeof(RDP_RECT) * num_rects);
ZeroMemory(rects, sizeof(RDP_RECT) * num_rects);
for(i = 0; i < num_rects; i++)
rects = (RDP_RECT*) calloc(num_rects, sizeof(RDP_RECT));
for (i = 0; i < num_rects; i++)
{
Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */
Stream_Seek_UINT16(ifman->input);
@@ -347,36 +397,40 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN *ifman)
rects[i].x, rects[i].y, rects[i].width, rects[i].height);
}
}
tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects);
}
ifman->output_pending = TRUE;
return error;
}
int tsmf_ifman_set_allocator(TSMF_IFMAN *ifman)
int tsmf_ifman_set_allocator(TSMF_IFMAN* ifman)
{
DEBUG_TSMF("");
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_notify_preroll(TSMF_IFMAN *ifman)
int tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman)
{
DEBUG_TSMF("");
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_on_sample(TSMF_IFMAN *ifman)
int tsmf_ifman_on_sample(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION *presentation;
TSMF_STREAM *stream;
TSMF_PRESENTATION* presentation;
TSMF_STREAM* stream;
UINT32 StreamId;
UINT64 SampleStartTime;
UINT64 SampleEndTime;
UINT64 ThrottleDuration;
UINT32 SampleExtensions;
UINT32 cbData;
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId);
Stream_Seek_UINT32(ifman->input); /* numSample */
@@ -386,62 +440,81 @@ int tsmf_ifman_on_sample(TSMF_IFMAN *ifman)
Stream_Seek_UINT32(ifman->input); /* SampleFlags */
Stream_Read_UINT32(ifman->input, SampleExtensions);
Stream_Read_UINT32(ifman->input, cbData);
DEBUG_TSMF("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d "
"ThrottleDuration %d SampleExtensions %d cbData %d",
ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime,
(int)ThrottleDuration, SampleExtensions, cbData);
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
if(presentation == NULL)
if (!presentation)
{
WLog_ERR(TAG, "unknown presentation id");
return 1;
}
stream = tsmf_stream_find_by_id(presentation, StreamId);
if(stream == NULL)
if (!stream)
{
WLog_ERR(TAG, "unknown stream id");
return 1;
}
tsmf_stream_push_sample(stream, ifman->channel_callback,
ifman->message_id, SampleStartTime, SampleEndTime, ThrottleDuration, SampleExtensions,
cbData, Stream_Pointer(ifman->input));
ifman->message_id, SampleStartTime, SampleEndTime,
ThrottleDuration, SampleExtensions, cbData, Stream_Pointer(ifman->input));
tsmf_presentation_sync(presentation);
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_on_flush(TSMF_IFMAN *ifman)
int tsmf_ifman_on_flush(TSMF_IFMAN* ifman)
{
UINT32 StreamId;
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId);
DEBUG_TSMF("StreamId %d", StreamId);
presentation = tsmf_presentation_find_by_id(ifman->presentation_id);
if(presentation == NULL)
if (!presentation)
{
WLog_ERR(TAG, "unknown presentation id");
return 1;
}
tsmf_presentation_flush(presentation);
ifman->output_pending = TRUE;
return 0;
}
int tsmf_ifman_on_end_of_stream(TSMF_IFMAN *ifman)
int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman)
{
UINT32 StreamId;
TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation;
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
Stream_Seek(ifman->input, 16);
Stream_Read_UINT32(ifman->input, StreamId);
if(presentation)
if (presentation)
{
stream = tsmf_stream_find_by_id(presentation, StreamId);
if(stream)
if (stream)
tsmf_stream_end(stream);
}
DEBUG_TSMF("StreamId %d", StreamId);
Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
@@ -449,74 +522,93 @@ int tsmf_ifman_on_end_of_stream(TSMF_IFMAN *ifman)
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_ENDOFSTREAM); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0;
}
int tsmf_ifman_on_playback_started(TSMF_IFMAN *ifman)
int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation)
if (presentation)
tsmf_presentation_start(presentation);
else
WLog_ERR(TAG, "unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, 0); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0;
}
int tsmf_ifman_on_playback_paused(TSMF_IFMAN *ifman)
int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
ifman->output_pending = TRUE;
/* Added pause control so gstreamer pipeline can be paused accordingly */
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation)
if (presentation)
tsmf_presentation_paused(presentation);
else
WLog_ERR(TAG, "unknown presentation id");
return 0;
}
int tsmf_ifman_on_playback_restarted(TSMF_IFMAN *ifman)
int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
ifman->output_pending = TRUE;
/* Added restart control so gstreamer pipeline can be resumed accordingly */
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation)
if (presentation)
tsmf_presentation_restarted(presentation);
else
WLog_ERR(TAG, "unknown presentation id");
return 0;
}
int tsmf_ifman_on_playback_stopped(TSMF_IFMAN *ifman)
int tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman)
{
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
DEBUG_TSMF("");
presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input));
if(presentation)
if (presentation)
tsmf_presentation_stop(presentation);
else
WLog_ERR(TAG, "unknown presentation id");
Stream_EnsureRemainingCapacity(ifman->output, 16);
Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */
Stream_Write_UINT32(ifman->output, 0); /* StreamId */
Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED); /* EventId */
Stream_Write_UINT32(ifman->output, 0); /* cbData */
ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY;
return 0;
}
int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN *ifman)
int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman)
{
DEBUG_TSMF("");
Stream_EnsureRemainingCapacity(ifman->output, 16);

View File

@@ -21,14 +21,11 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <winpr/cmdline.h>
#include <winpr/stream.h>
#include <freerdp/client/tsmf.h>
#include "tsmf_types.h"
#include "tsmf_constants.h"
@@ -37,81 +34,41 @@
#include "tsmf_main.h"
typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK;
typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK;
typedef struct _TSMF_PLUGIN TSMF_PLUGIN;
struct _TSMF_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin *plugin;
IWTSVirtualChannelManager *channel_mgr;
};
struct _TSMF_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
IWTSPlugin *plugin;
IWTSVirtualChannelManager *channel_mgr;
IWTSVirtualChannel *channel;
BYTE presentation_id[GUID_SIZE];
UINT32 stream_id;
};
struct _TSMF_PLUGIN
{
IWTSPlugin iface;
TSMF_LISTENER_CALLBACK *listener_callback;
const char *decoder_name;
const char *audio_name;
const char *audio_device;
};
void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback,
UINT32 message_id, UINT64 duration, UINT32 data_size)
UINT32 message_id, UINT64 duration, UINT32 data_size)
{
wStream *s;
int status = -1;
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
s = Stream_New(NULL, 32);
Stream_Write_UINT32(s, TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY);
Stream_Write_UINT32(s, message_id);
Stream_Write_UINT32(s, PLAYBACK_ACK); /* FunctionId */
Stream_Write_UINT32(s, callback->stream_id); /* StreamId */
Stream_Write_UINT64(s, duration); /* DataDuration */
Stream_Write_UINT64(s, data_size); /* cbData */
DEBUG_TSMF("response size %d", (int) Stream_GetPosition(s));
if(!callback || !callback->channel || !callback->channel->Write)
if (!callback || !callback->channel || !callback->channel->Write)
{
WLog_ERR(TAG, "callback=%p, channel=%p, write=%p", callback,
callback->channel, callback->channel->Write);
}
else
{
status = callback->channel->Write(callback->channel,
Stream_GetPosition(s), Stream_Buffer(s), NULL);
if(status)
{
WLog_ERR(TAG, "response error %d", status);
Stream_GetPosition(s), Stream_Buffer(s), NULL);
}
Stream_Free(s, TRUE);
}
BOOL tsmf_push_event(IWTSVirtualChannelCallback *pChannelCallback, wMessage *event)
{
int status;
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
status = callback->channel_mgr->PushEvent(callback->channel_mgr, event);
if(status)
if (status)
{
WLog_ERR(TAG, "response error %d", status);
return FALSE;
}
return TRUE;
Stream_Free(s, TRUE);
}
static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data)
@@ -128,7 +85,7 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w
UINT32 cbSize = Stream_GetRemainingLength(data);
/* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */
if(cbSize < 12)
if (cbSize < 12)
{
WLog_ERR(TAG, "invalid size. cbSize=%d", cbSize);
return 1;
@@ -137,17 +94,19 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w
input = data;
output = Stream_New(NULL, 256);
Stream_Seek(output, 8);
Stream_Read_UINT32(input, InterfaceId);
Stream_Read_UINT32(input, MessageId);
Stream_Read_UINT32(input, FunctionId);
Stream_Read_UINT32(input, InterfaceId); /* InterfaceId (4 bytes) */
Stream_Read_UINT32(input, MessageId); /* MessageId (4 bytes) */
Stream_Read_UINT32(input, FunctionId); /* FunctionId (4 bytes) */
DEBUG_TSMF("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X",
cbSize, InterfaceId, MessageId, FunctionId);
memset(&ifman, 0, sizeof(TSMF_IFMAN));
ZeroMemory(&ifman, sizeof(TSMF_IFMAN));
ifman.channel_callback = pChannelCallback;
ifman.decoder_name = ((TSMF_PLUGIN *) callback->plugin)->decoder_name;
ifman.audio_name = ((TSMF_PLUGIN *) callback->plugin)->audio_name;
ifman.audio_device = ((TSMF_PLUGIN *) callback->plugin)->audio_device;
memcpy(ifman.presentation_id, callback->presentation_id, GUID_SIZE);
ifman.decoder_name = ((TSMF_PLUGIN*) callback->plugin)->decoder_name;
ifman.audio_name = ((TSMF_PLUGIN*) callback->plugin)->audio_name;
ifman.audio_device = ((TSMF_PLUGIN*) callback->plugin)->audio_device;
CopyMemory(ifman.presentation_id, callback->presentation_id, GUID_SIZE);
ifman.stream_id = callback->stream_id;
ifman.message_id = MessageId;
ifman.input = input;
@@ -155,23 +114,30 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w
ifman.output = output;
ifman.output_pending = FALSE;
ifman.output_interface_id = InterfaceId;
switch(InterfaceId)
//fprintf(stderr, "InterfaceId: 0x%04X MessageId: 0x%04X FunctionId: 0x%04X\n", InterfaceId, MessageId, FunctionId);
switch (InterfaceId)
{
case TSMF_INTERFACE_CAPABILITIES | STREAM_ID_NONE:
switch(FunctionId)
switch (FunctionId)
{
case RIM_EXCHANGE_CAPABILITY_REQUEST:
status = tsmf_ifman_rim_exchange_capability_request(&ifman);
break;
case RIMCALL_RELEASE:
case RIMCALL_QUERYINTERFACE:
break;
default:
break;
}
break;
case TSMF_INTERFACE_DEFAULT | STREAM_ID_PROXY:
switch(FunctionId)
switch (FunctionId)
{
case SET_CHANNEL_PARAMS:
memcpy(callback->presentation_id, Stream_Pointer(input), GUID_SIZE);
CopyMemory(callback->presentation_id, Stream_Pointer(input), GUID_SIZE);
Stream_Seek(input, GUID_SIZE);
Stream_Read_UINT32(input, callback->stream_id);
DEBUG_TSMF("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id);
@@ -244,19 +210,24 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w
case ON_PLAYBACK_RATE_CHANGED:
status = tsmf_ifman_on_playback_rate_changed(&ifman);
break;
case RIMCALL_RELEASE:
case RIMCALL_QUERYINTERFACE:
break;
default:
break;
}
break;
default:
break;
}
input = NULL;
ifman.input = NULL;
if(status == -1)
if (status == -1)
{
switch(FunctionId)
switch (FunctionId)
{
case RIMCALL_RELEASE:
/* [MS-RDPEXPS] 2.2.2.2 Interface Release (IFACE_RELEASE)
@@ -270,15 +241,17 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w
status = 0;
break;
}
if(status == -1)
if (status == -1)
{
WLog_ERR(TAG, "InterfaceId 0x%X FunctionId 0x%X not processed.",
InterfaceId, FunctionId);
WLog_ERR(TAG, "Unknown InterfaceId: 0x%04X MessageId: 0x%04X FunctionId: 0x%04X\n", InterfaceId, MessageId, FunctionId);
/* When a request is not implemented we return empty response indicating error */
}
status = 0;
}
if(status == 0 && !ifman.output_pending)
if (status == 0 && !ifman.output_pending)
{
/* Response packet does not have FunctionId */
length = Stream_GetPosition(output);
@@ -287,31 +260,37 @@ static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, w
Stream_Write_UINT32(output, MessageId);
DEBUG_TSMF("response size %d", length);
status = callback->channel->Write(callback->channel, length, Stream_Buffer(output), NULL);
if(status)
if (status)
{
WLog_ERR(TAG, "response error %d", status);
}
}
Stream_Free(output, TRUE);
return status;
}
static int tsmf_on_close(IWTSVirtualChannelCallback *pChannelCallback)
{
TSMF_STREAM *stream;
TSMF_PRESENTATION *presentation;
TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback;
TSMF_STREAM* stream;
TSMF_PRESENTATION* presentation;
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
DEBUG_TSMF("");
if(callback->stream_id)
if (callback->stream_id)
{
presentation = tsmf_presentation_find_by_id(callback->presentation_id);
if(presentation)
if (presentation)
{
stream = tsmf_stream_find_by_id(presentation, callback->stream_id);
if(stream)
if (stream)
tsmf_stream_free(stream);
}
}
free(pChannelCallback);
return 0;
}
@@ -322,41 +301,63 @@ static int tsmf_on_new_channel_connection(IWTSListenerCallback *pListenerCallbac
int *pbAccept,
IWTSVirtualChannelCallback **ppCallback)
{
TSMF_CHANNEL_CALLBACK *callback;
TSMF_LISTENER_CALLBACK *listener_callback = (TSMF_LISTENER_CALLBACK *) pListenerCallback;
TSMF_CHANNEL_CALLBACK* callback;
TSMF_LISTENER_CALLBACK* listener_callback = (TSMF_LISTENER_CALLBACK*) pListenerCallback;
DEBUG_TSMF("");
callback = (TSMF_CHANNEL_CALLBACK *) malloc(sizeof(TSMF_CHANNEL_CALLBACK));
ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK));
callback = (TSMF_CHANNEL_CALLBACK*) calloc(1, sizeof(TSMF_CHANNEL_CALLBACK));
if (!callback)
return -1;
callback->iface.OnDataReceived = tsmf_on_data_received;
callback->iface.OnClose = tsmf_on_close;
callback->iface.OnOpen = NULL;
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;
*ppCallback = (IWTSVirtualChannelCallback *) callback;
*ppCallback = (IWTSVirtualChannelCallback*) callback;
return 0;
}
static int tsmf_plugin_initialize(IWTSPlugin *pPlugin, IWTSVirtualChannelManager *pChannelMgr)
static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
int status;
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
DEBUG_TSMF("");
tsmf->listener_callback = (TSMF_LISTENER_CALLBACK *) malloc(sizeof(TSMF_LISTENER_CALLBACK));
ZeroMemory(tsmf->listener_callback, sizeof(TSMF_LISTENER_CALLBACK));
tsmf->listener_callback = (TSMF_LISTENER_CALLBACK*) calloc(1, sizeof(TSMF_LISTENER_CALLBACK));
if (!tsmf->listener_callback)
return -1;
tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection;
tsmf->listener_callback->plugin = pPlugin;
tsmf->listener_callback->channel_mgr = pChannelMgr;
return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0,
(IWTSListenerCallback *) tsmf->listener_callback, NULL);
status = pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0,
(IWTSListenerCallback*) tsmf->listener_callback, &(tsmf->listener));
tsmf->listener->pInterface = tsmf->iface.pInterface;
return status;
}
static int tsmf_plugin_terminated(IWTSPlugin *pPlugin)
static int tsmf_plugin_terminated(IWTSPlugin* pPlugin)
{
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
DEBUG_TSMF("");
if(tsmf->listener_callback)
if (tsmf->listener_callback)
free(tsmf->listener_callback);
free(tsmf);
return 0;
}
@@ -372,15 +373,18 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args)
{
int status;
DWORD flags;
COMMAND_LINE_ARGUMENT_A *arg;
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
COMMAND_LINE_ARGUMENT_A* arg;
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
status = CommandLineParseArgumentsA(args->argc, (const char **) args->argv,
tsmf_args, flags, tsmf, NULL, NULL);
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
tsmf_args, flags, tsmf, NULL, NULL);
arg = tsmf_args;
do
{
if(!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
continue;
CommandLineSwitchStart(arg)
CommandLineSwitchCase(arg, "audio")
@@ -400,32 +404,50 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args)
}
CommandLineSwitchEnd(arg)
}
while((arg = CommandLineFindNextArgumentA(arg)) != NULL);
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
}
#ifdef STATIC_CHANNELS
#define DVCPluginEntry tsmf_DVCPluginEntry
#endif
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS *pEntryPoints)
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
int status = 0;
TSMF_PLUGIN *tsmf;
tsmf = (TSMF_PLUGIN *) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
if(tsmf == NULL)
TSMF_PLUGIN* tsmf;
TsmfClientContext* context;
tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
if (!tsmf)
{
tsmf = (TSMF_PLUGIN *) malloc(sizeof(TSMF_PLUGIN));
ZeroMemory(tsmf, sizeof(TSMF_PLUGIN));
tsmf = (TSMF_PLUGIN*) calloc(1, sizeof(TSMF_PLUGIN));
if (!tsmf)
return -1;
tsmf->iface.Initialize = tsmf_plugin_initialize;
tsmf->iface.Connected = NULL;
tsmf->iface.Disconnected = NULL;
tsmf->iface.Terminated = tsmf_plugin_terminated;
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin *) tsmf);
context = (TsmfClientContext*) calloc(1, sizeof(TsmfClientContext));
if (!context)
return -1;
context->handle = (void*) tsmf;
tsmf->iface.pInterface = (void*) context;
tsmf_media_init();
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
}
if(status == 0)
if (status == 0)
{
tsmf_process_addin_args((IWTSPlugin *) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
}
return status;
}

View File

@@ -20,10 +20,46 @@
#ifndef __TSMF_MAIN_H
#define __TSMF_MAIN_H
typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK;
typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK;
typedef struct _TSMF_PLUGIN TSMF_PLUGIN;
struct _TSMF_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
};
struct _TSMF_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
IWTSVirtualChannel* channel;
BYTE presentation_id[GUID_SIZE];
UINT32 stream_id;
};
struct _TSMF_PLUGIN
{
IWTSPlugin iface;
IWTSListener* listener;
TSMF_LISTENER_CALLBACK* listener_callback;
const char* decoder_name;
const char* audio_name;
const char* audio_device;
};
void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
UINT32 message_id, UINT64 duration, UINT32 data_size);
BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback,
wMessage* event);
UINT32 message_id, UINT64 duration, UINT32 data_size);
#endif

View File

@@ -22,8 +22,6 @@
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -43,7 +41,6 @@
#include <winpr/stream.h>
#include <winpr/collections.h>
#include <freerdp/utils/event.h>
#include <freerdp/client/tsmf.h>
#include "tsmf_constants.h"
@@ -87,7 +84,7 @@ struct _TSMF_STREAM
{
UINT32 stream_id;
TSMF_PRESENTATION *presentation;
TSMF_PRESENTATION* presentation;
ITSMFDecoder *decoder;
@@ -127,7 +124,7 @@ struct _TSMF_SAMPLE
UINT32 decoded_size;
UINT32 pixfmt;
TSMF_STREAM *stream;
TSMF_STREAM* stream;
IWTSVirtualChannelCallback *channel_callback;
UINT64 ack_time;
};
@@ -135,8 +132,8 @@ struct _TSMF_SAMPLE
static wArrayList *presentation_list = NULL;
static int TERMINATING = 0;
static void _tsmf_presentation_free(TSMF_PRESENTATION *presentation);
static void _tsmf_stream_free(TSMF_STREAM *stream);
static void _tsmf_presentation_free(TSMF_PRESENTATION* presentation);
static void _tsmf_stream_free(TSMF_STREAM* stream);
static UINT64 get_current_time(void)
{
@@ -145,15 +142,17 @@ static UINT64 get_current_time(void)
return ((UINT64)tp.tv_sec) * 10000000LL + ((UINT64)tp.tv_usec) * 10LL;
}
static TSMF_SAMPLE *tsmf_stream_pop_sample(TSMF_STREAM *stream, int sync)
static TSMF_SAMPLE* tsmf_stream_pop_sample(TSMF_STREAM* stream, int sync)
{
UINT32 index;
UINT32 count;
TSMF_STREAM *s;
TSMF_SAMPLE *sample;
TSMF_SAMPLE* sample;
BOOL pending = FALSE;
TSMF_PRESENTATION *presentation = stream->presentation;
assert(stream);
TSMF_PRESENTATION* presentation = stream->presentation;
if (!stream)
return NULL;
if (Queue_Count(stream->sample_list) < 1)
return NULL;
@@ -211,8 +210,10 @@ static TSMF_SAMPLE *tsmf_stream_pop_sample(TSMF_STREAM *stream, int sync)
static void tsmf_sample_free(void *arg)
{
TSMF_SAMPLE *sample = arg;
assert(sample);
TSMF_SAMPLE* sample = arg;
if (!sample)
return;
if (sample->data)
free(sample->data);
@@ -220,28 +221,37 @@ static void tsmf_sample_free(void *arg)
free(sample);
}
static void tsmf_sample_ack(TSMF_SAMPLE *sample)
static void tsmf_sample_ack(TSMF_SAMPLE* sample)
{
assert(sample);
if (!sample)
return;
tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size);
}
static void tsmf_sample_queue_ack(TSMF_SAMPLE *sample)
static void tsmf_sample_queue_ack(TSMF_SAMPLE* sample)
{
assert(sample);
assert(sample->stream);
if (!sample)
return;
if (!sample->stream)
return;
Queue_Enqueue(sample->stream->sample_ack_list, sample);
}
static BOOL tsmf_stream_process_ack(void *arg, BOOL force)
static BOOL tsmf_stream_process_ack(void* arg, BOOL force)
{
TSMF_STREAM *stream = arg;
TSMF_SAMPLE *sample;
TSMF_STREAM* stream = arg;
TSMF_SAMPLE* sample;
UINT64 ack_time;
BOOL rc = FALSE;
assert(stream);
if (!stream)
return FALSE;
Queue_Lock(stream->sample_ack_list);
sample = (TSMF_SAMPLE *) Queue_Peek(stream->sample_ack_list);
sample = (TSMF_SAMPLE*) Queue_Peek(stream->sample_ack_list);
if (!sample)
goto finally;
@@ -257,17 +267,20 @@ static BOOL tsmf_stream_process_ack(void *arg, BOOL force)
sample = Queue_Dequeue(stream->sample_ack_list);
tsmf_sample_ack(sample);
tsmf_sample_free(sample);
finally:
Queue_Unlock(stream->sample_ack_list);
return rc;
}
TSMF_PRESENTATION *tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback)
TSMF_PRESENTATION* tsmf_presentation_new(const BYTE* guid, IWTSVirtualChannelCallback* pChannelCallback)
{
TSMF_PRESENTATION *presentation;
assert(guid);
assert(pChannelCallback);
presentation = (TSMF_PRESENTATION *) calloc(1, sizeof(TSMF_PRESENTATION));
TSMF_PRESENTATION* presentation;
if (!guid || !pChannelCallback)
return NULL;
presentation = (TSMF_PRESENTATION*) calloc(1, sizeof(TSMF_PRESENTATION));
if (!presentation)
{
@@ -280,15 +293,18 @@ TSMF_PRESENTATION *tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCal
presentation->volume = 5000; /* 50% */
presentation->stream_list = ArrayList_New(TRUE);
ArrayList_Object(presentation->stream_list)->fnObjectFree = (OBJECT_FREE_FN) _tsmf_stream_free;
ArrayList_Add(presentation_list, presentation);
return presentation;
}
static char *guid_to_string(const BYTE *guid, char *str, size_t len)
static char* guid_to_string(const BYTE* guid, char* str, size_t len)
{
int i;
assert(guid);
assert(str);
if (!guid || !str)
return NULL;
for (i=0; i<GUID_SIZE && len > 2*i; i++)
snprintf(str + (2*i), len - 2*i, "%02X", guid[i]);
@@ -296,19 +312,20 @@ static char *guid_to_string(const BYTE *guid, char *str, size_t len)
return str;
}
TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid)
TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE *guid)
{
char guid_str[GUID_SIZE * 2 + 1];
UINT32 index;
UINT32 count;
BOOL found = FALSE;
TSMF_PRESENTATION *presentation;
char guid_str[GUID_SIZE * 2 + 1];
TSMF_PRESENTATION* presentation;
ArrayList_Lock(presentation_list);
count = ArrayList_Count(presentation_list);
for (index = 0; index < count; index++)
{
presentation = (TSMF_PRESENTATION *) ArrayList_GetItem(presentation_list, index);
presentation = (TSMF_PRESENTATION*) ArrayList_GetItem(presentation_list, index);
if (memcmp(presentation->presentation_id, guid, GUID_SIZE) == 0)
{
@@ -325,14 +342,17 @@ TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid)
return (found) ? presentation : NULL;
}
static void tsmf_sample_playback_video(TSMF_SAMPLE *sample)
static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
{
UINT64 t;
RDP_VIDEO_FRAME_EVENT *vevent;
TSMF_STREAM *stream = sample->stream;
TSMF_PRESENTATION *presentation = stream->presentation;
TSMF_VIDEO_FRAME_EVENT event;
TSMF_STREAM* stream = sample->stream;
TSMF_PRESENTATION* presentation = stream->presentation;
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) sample->channel_callback;
TsmfClientContext* tsmf = (TsmfClientContext*) callback->plugin->pInterface;
DEBUG_TSMF("MessageId %d EndTime %d data_size %d consumed.",
sample->sample_id, (int)sample->end_time, sample->data_size);
sample->sample_id, (int) sample->end_time, sample->data_size);
if (sample->data)
{
@@ -346,21 +366,21 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE *sample)
}
stream->next_start_time = t + sample->duration - 50000;
vevent = (RDP_VIDEO_FRAME_EVENT *) freerdp_event_new(TsmfChannel_Class, TsmfChannel_VideoFrame,
NULL, NULL);
vevent->frame_data = sample->data;
vevent->frame_size = sample->decoded_size;
vevent->frame_pixfmt = sample->pixfmt;
vevent->frame_width = sample->stream->width;
vevent->frame_height = sample->stream->height;
ZeroMemory(&event, sizeof(TSMF_VIDEO_FRAME_EVENT));
event.frameData = sample->data;
event.frameSize = sample->decoded_size;
event.framePixFmt = sample->pixfmt;
event.frameWidth = sample->stream->width;
event.frameHeight = sample->stream->height;
/* The frame data ownership is passed to the event object, and is freed after the event is processed. */
sample->data = NULL;
sample->decoded_size = 0;
if (!tsmf_push_event(sample->channel_callback, (wMessage *) vevent))
{
freerdp_event_free((wMessage *) vevent);
}
if (tsmf->FrameEvent)
tsmf->FrameEvent(tsmf, &event);
#if 0
/* Dump a .ppm image for every 30 frames. Assuming the frame is in YUV format, we
@@ -387,17 +407,17 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE *sample)
}
}
static void tsmf_sample_playback_audio(TSMF_SAMPLE *sample)
static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample)
{
UINT64 latency = 0;
TSMF_STREAM *stream = sample->stream;
TSMF_STREAM* stream = sample->stream;
DEBUG_TSMF("MessageId %d EndTime %d consumed.",
sample->sample_id, (int)sample->end_time);
if (sample->stream->audio && sample->data)
{
sample->stream->audio->Play(sample->stream->audio,
sample->data, sample->decoded_size);
sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size);
sample->data = NULL;
sample->decoded_size = 0;
@@ -415,21 +435,25 @@ static void tsmf_sample_playback_audio(TSMF_SAMPLE *sample)
stream->presentation->audio_end_time = sample->end_time + latency;
}
static void tsmf_sample_playback(TSMF_SAMPLE *sample)
static void tsmf_sample_playback(TSMF_SAMPLE* sample)
{
BOOL ret = FALSE;
UINT32 width;
UINT32 height;
UINT32 pixfmt = 0;
TSMF_STREAM *stream = sample->stream;
TSMF_STREAM* stream = sample->stream;
if (stream->decoder)
{
if (stream->decoder->DecodeEx)
{
ret = stream->decoder->DecodeEx(stream->decoder, sample->data, sample->data_size, sample->extensions,
sample->start_time, sample->end_time, sample->duration);
sample->start_time, sample->end_time, sample->duration);
}
else
{
ret = stream->decoder->Decode(stream->decoder, sample->data, sample->data_size, sample->extensions);
}
}
if (!ret)
@@ -456,7 +480,7 @@ static void tsmf_sample_playback(TSMF_SAMPLE *sample)
sample->pixfmt = pixfmt;
}
ret = FALSE ;
ret = FALSE;
if (stream->decoder->GetDecodedDimension)
{
@@ -490,7 +514,7 @@ static void tsmf_sample_playback(TSMF_SAMPLE *sample)
}
else
{
TSMF_STREAM *stream = sample->stream;
TSMF_STREAM* stream = sample->stream;
UINT64 ack_anticipation_time = get_current_time();
UINT64 currentRunningTime = sample->start_time;
BOOL buffer_filled = TRUE;
@@ -521,7 +545,9 @@ static void tsmf_sample_playback(TSMF_SAMPLE *sample)
}
}
else
{
ack_anticipation_time += sample->duration / 2;
}
switch (sample->stream->major_type)
{
@@ -541,11 +567,12 @@ static void tsmf_sample_playback(TSMF_SAMPLE *sample)
}
}
static void *tsmf_stream_ack_func(void *arg)
static void* tsmf_stream_ack_func(void *arg)
{
TSMF_STREAM *stream = (TSMF_STREAM *) arg;
HANDLE hdl[2];
TSMF_STREAM* stream = (TSMF_STREAM*) arg;
DEBUG_TSMF("in %d", stream->stream_id);
hdl[0] = stream->stopEvent;
hdl[1] = Queue_Event(stream->sample_ack_list);
@@ -571,12 +598,13 @@ static void *tsmf_stream_ack_func(void *arg)
return NULL;
}
static void *tsmf_stream_playback_func(void *arg)
static void* tsmf_stream_playback_func(void *arg)
{
HANDLE hdl[2];
TSMF_SAMPLE *sample;
TSMF_STREAM *stream = (TSMF_STREAM *) arg;
TSMF_PRESENTATION *presentation = stream->presentation;
TSMF_SAMPLE* sample;
TSMF_STREAM* stream = (TSMF_STREAM *) arg;
TSMF_PRESENTATION* presentation = stream->presentation;
DEBUG_TSMF("in %d", stream->stream_id);
if (stream->major_type == TSMF_MAJOR_TYPE_AUDIO &&
@@ -587,13 +615,12 @@ static void *tsmf_stream_playback_func(void *arg)
if (stream->decoder->GetDecodedData)
{
stream->audio = tsmf_load_audio_device(
presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL,
presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL);
presentation->audio_name && presentation->audio_name[0] ? presentation->audio_name : NULL,
presentation->audio_device && presentation->audio_device[0] ? presentation->audio_device : NULL);
if (stream->audio)
{
stream->audio->SetFormat(stream->audio,
stream->sample_rate, stream->channels, stream->bits_per_sample);
stream->audio->SetFormat(stream->audio, stream->sample_rate, stream->channels, stream->bits_per_sample);
}
}
}
@@ -621,7 +648,7 @@ static void *tsmf_stream_playback_func(void *arg)
return NULL;
}
static void tsmf_stream_start(TSMF_STREAM *stream)
static void tsmf_stream_start(TSMF_STREAM* stream)
{
if (!stream || !stream->presentation || !stream->decoder)
return;
@@ -632,7 +659,7 @@ static void tsmf_stream_start(TSMF_STREAM *stream)
}
}
static void tsmf_stream_stop(TSMF_STREAM *stream)
static void tsmf_stream_stop(TSMF_STREAM* stream)
{
if (!stream || !stream->decoder)
return;
@@ -643,7 +670,7 @@ static void tsmf_stream_stop(TSMF_STREAM *stream)
}
}
static void tsmf_stream_pause(TSMF_STREAM *stream)
static void tsmf_stream_pause(TSMF_STREAM* stream)
{
if (!stream || !stream->decoder)
return;
@@ -654,7 +681,7 @@ static void tsmf_stream_pause(TSMF_STREAM *stream)
}
}
static void tsmf_stream_restart(TSMF_STREAM *stream)
static void tsmf_stream_restart(TSMF_STREAM* stream)
{
if (!stream || !stream->decoder)
return;
@@ -665,7 +692,7 @@ static void tsmf_stream_restart(TSMF_STREAM *stream)
}
}
static void tsmf_stream_change_volume(TSMF_STREAM *stream, UINT32 newVolume, UINT32 muted)
static void tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UINT32 muted)
{
if (!stream || !stream->decoder)
return;
@@ -680,11 +707,11 @@ static void tsmf_stream_change_volume(TSMF_STREAM *stream, UINT32 newVolume, UIN
}
}
void tsmf_presentation_volume_changed(TSMF_PRESENTATION *presentation, UINT32 newVolume, UINT32 muted)
void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume, UINT32 muted)
{
UINT32 index;
UINT32 count;
TSMF_STREAM *stream;
TSMF_STREAM* stream;
presentation->volume = newVolume;
presentation->muted = muted;
ArrayList_Lock(presentation->stream_list);
@@ -699,11 +726,11 @@ void tsmf_presentation_volume_changed(TSMF_PRESENTATION *presentation, UINT32 ne
ArrayList_Unlock(presentation->stream_list);
}
void tsmf_presentation_paused(TSMF_PRESENTATION *presentation)
void tsmf_presentation_paused(TSMF_PRESENTATION* presentation)
{
UINT32 index;
UINT32 count;
TSMF_STREAM *stream;
TSMF_STREAM* stream;
ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list);
@@ -716,11 +743,11 @@ void tsmf_presentation_paused(TSMF_PRESENTATION *presentation)
ArrayList_Unlock(presentation->stream_list);
}
void tsmf_presentation_restarted(TSMF_PRESENTATION *presentation)
void tsmf_presentation_restarted(TSMF_PRESENTATION* presentation)
{
UINT32 index;
UINT32 count;
TSMF_STREAM *stream;
TSMF_STREAM* stream;
ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list);
@@ -733,11 +760,11 @@ void tsmf_presentation_restarted(TSMF_PRESENTATION *presentation)
ArrayList_Unlock(presentation->stream_list);
}
void tsmf_presentation_start(TSMF_PRESENTATION *presentation)
void tsmf_presentation_start(TSMF_PRESENTATION* presentation)
{
UINT32 index;
UINT32 count;
TSMF_STREAM *stream;
TSMF_STREAM* stream;
ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list);
@@ -750,7 +777,7 @@ void tsmf_presentation_start(TSMF_PRESENTATION *presentation)
ArrayList_Unlock(presentation->stream_list);
}
void tsmf_presentation_sync(TSMF_PRESENTATION *presentation)
void tsmf_presentation_sync(TSMF_PRESENTATION* presentation)
{
UINT32 index;
UINT32 count;
@@ -759,18 +786,18 @@ void tsmf_presentation_sync(TSMF_PRESENTATION *presentation)
for (index = 0; index < count; index++)
{
TSMF_STREAM *stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
TSMF_STREAM* stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
WaitForSingleObject(stream->ready, 500);
}
ArrayList_Unlock(presentation->stream_list);
}
void tsmf_presentation_stop(TSMF_PRESENTATION *presentation)
void tsmf_presentation_stop(TSMF_PRESENTATION* presentation)
{
UINT32 index;
UINT32 count;
TSMF_STREAM *stream;
TSMF_STREAM* stream;
tsmf_presentation_flush(presentation);
ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list);
@@ -784,12 +811,12 @@ void tsmf_presentation_stop(TSMF_PRESENTATION *presentation)
ArrayList_Unlock(presentation->stream_list);
}
void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation,
void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation,
UINT32 x, UINT32 y, UINT32 width, UINT32 height, int num_rects, RDP_RECT *rects)
{
UINT32 index;
UINT32 count;
TSMF_STREAM *stream;
TSMF_STREAM* stream;
/* The server may send messages with invalid width / height.
* Ignore those messages. */
@@ -812,7 +839,7 @@ void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation,
presentation->rects = realloc(presentation->rects, sizeof(RDP_RECT) * num_rects);
if (presentation->rects)
memcpy(presentation->rects, rects, sizeof(RDP_RECT) * num_rects);
CopyMemory(presentation->rects, rects, sizeof(RDP_RECT) * num_rects);
ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list);
@@ -833,13 +860,13 @@ void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation,
ArrayList_Unlock(presentation->stream_list);
}
void tsmf_presentation_set_audio_device(TSMF_PRESENTATION *presentation, const char *name, const char *device)
void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const char *name, const char *device)
{
presentation->audio_name = name;
presentation->audio_device = device;
}
static void tsmf_stream_flush(TSMF_STREAM *stream)
static void tsmf_stream_flush(TSMF_STREAM* stream)
{
//TSMF_SAMPLE* sample;
/* TODO: free lists */
@@ -857,17 +884,17 @@ static void tsmf_stream_flush(TSMF_STREAM *stream)
}
}
void tsmf_presentation_flush(TSMF_PRESENTATION *presentation)
void tsmf_presentation_flush(TSMF_PRESENTATION* presentation)
{
UINT32 index;
UINT32 count;
TSMF_STREAM *stream;
TSMF_STREAM* stream;
ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
tsmf_stream_flush(stream);
}
@@ -877,7 +904,7 @@ void tsmf_presentation_flush(TSMF_PRESENTATION *presentation)
presentation->audio_end_time = 0;
}
void _tsmf_presentation_free(TSMF_PRESENTATION *presentation)
void _tsmf_presentation_free(TSMF_PRESENTATION* presentation)
{
tsmf_presentation_stop(presentation);
ArrayList_Clear(presentation->stream_list);
@@ -886,18 +913,18 @@ void _tsmf_presentation_free(TSMF_PRESENTATION *presentation)
if (presentation->rects)
free(presentation->rects);
memset(presentation, 0, sizeof(TSMF_PRESENTATION));
ZeroMemory(presentation, sizeof(TSMF_PRESENTATION));
free(presentation);
}
void tsmf_presentation_free(TSMF_PRESENTATION *presentation)
void tsmf_presentation_free(TSMF_PRESENTATION* presentation)
{
ArrayList_Remove(presentation_list, presentation);
}
TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id)
TSMF_STREAM* tsmf_stream_new(TSMF_PRESENTATION* presentation, UINT32 stream_id)
{
TSMF_STREAM *stream;
TSMF_STREAM* stream;
stream = tsmf_stream_find_by_id(presentation, stream_id);
if (stream)
@@ -906,7 +933,7 @@ TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id)
return NULL;
}
stream = (TSMF_STREAM *) calloc(1, sizeof(TSMF_STREAM));
stream = (TSMF_STREAM*) calloc(1, sizeof(TSMF_STREAM));
if (!stream)
{
@@ -922,26 +949,27 @@ TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id)
stream->sample_list->object.fnObjectFree = tsmf_sample_free;
stream->sample_ack_list = Queue_New(TRUE, -1, -1);
stream->sample_ack_list->object.fnObjectFree = tsmf_sample_free;
stream->play_thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)tsmf_stream_playback_func, stream, 0, NULL);
stream->ack_thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL);
stream->play_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) tsmf_stream_playback_func, stream, 0, NULL);
stream->ack_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)tsmf_stream_ack_func, stream, 0, NULL);
ArrayList_Add(presentation->stream_list, stream);
return stream;
}
TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stream_id)
TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION* presentation, UINT32 stream_id)
{
UINT32 index;
UINT32 count;
BOOL found = FALSE;
TSMF_STREAM *stream;
TSMF_STREAM* stream;
ArrayList_Lock(presentation->stream_list);
count = ArrayList_Count(presentation->stream_list);
for (index = 0; index < count; index++)
{
stream = (TSMF_STREAM *) ArrayList_GetItem(presentation->stream_list, index);
stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index);
if (stream->stream_id == stream_id)
{
@@ -956,11 +984,11 @@ TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stre
static void tsmf_stream_resync(void *arg)
{
TSMF_STREAM *stream = arg;
TSMF_STREAM* stream = arg;
ResetEvent(stream->ready);
}
void tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s)
void tsmf_stream_set_format(TSMF_STREAM* stream, const char *name, wStream *s)
{
TS_AM_MEDIA_TYPE mediatype;
@@ -1008,16 +1036,20 @@ void tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s)
stream->decoder->SetSyncFunc(stream->decoder, tsmf_stream_resync, stream);
}
void tsmf_stream_end(TSMF_STREAM *stream)
void tsmf_stream_end(TSMF_STREAM* stream)
{
assert(stream);
if (!stream)
return;
stream->eos = 1;
stream->presentation->eos = 1;
}
void _tsmf_stream_free(TSMF_STREAM *stream)
void _tsmf_stream_free(TSMF_STREAM* stream)
{
assert(stream);
if (!stream)
return;
tsmf_stream_stop(stream);
tsmf_stream_flush(stream);
SetEvent(stream->stopEvent);
@@ -1047,27 +1079,27 @@ void _tsmf_stream_free(TSMF_STREAM *stream)
CloseHandle(stream->stopEvent);
CloseHandle(stream->ready);
memset(stream, 0, sizeof(TSMF_STREAM));
ZeroMemory(stream, sizeof(TSMF_STREAM));
free(stream);
}
void tsmf_stream_free(TSMF_STREAM *stream)
void tsmf_stream_free(TSMF_STREAM* stream)
{
TSMF_PRESENTATION *presentation = stream->presentation;
TSMF_PRESENTATION* presentation = stream->presentation;
ArrayList_Remove(presentation->stream_list, stream);
}
void tsmf_stream_push_sample(TSMF_STREAM *stream, IWTSVirtualChannelCallback *pChannelCallback,
UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions,
UINT32 data_size, BYTE *data)
void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback *pChannelCallback,
UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions,
UINT32 data_size, BYTE *data)
{
TSMF_SAMPLE *sample;
TSMF_SAMPLE* sample;
SetEvent(stream->ready);
if (TERMINATING)
return;
sample = (TSMF_SAMPLE *) calloc(1, sizeof(TSMF_SAMPLE));
sample = (TSMF_SAMPLE*) calloc(1, sizeof(TSMF_SAMPLE));
if (!sample)
{

View File

@@ -32,6 +32,7 @@ set(${MODULE_PREFIX}_OBJECTIVE_SOURCES
MRDPCursor.m
MRDPView.m
Keyboard.m
Clipboard.m
PasswordDialog.m)
list(APPEND ${MODULE_PREFIX}_SOURCES ${${MODULE_PREFIX}_OBJECTIVE_SOURCES})
@@ -42,6 +43,7 @@ set(${MODULE_PREFIX}_HEADERS
MRDPCursor.h
MRDPView.h
Keyboard.h
Clipboard.h
PasswordDialog.h)
set(${MODULE_PREFIX}_RESOURCES "en.lproj/InfoPlist.strings")

29
client/Mac/Clipboard.h Normal file
View File

@@ -0,0 +1,29 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "mfreerdp.h"
#import "mf_client.h"
#import "freerdp/freerdp.h"
#import "freerdp/channels/channels.h"
#import "freerdp/client/cliprdr.h"
int mac_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr);
void mac_cliprdr_init(mfContext* mfc, CliprdrClientContext* cliprdr);
void mac_cliprdr_uninit(mfContext* mfc, CliprdrClientContext* cliprdr);

328
client/Mac/Clipboard.m Normal file
View File

@@ -0,0 +1,328 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import "Clipboard.h"
int mac_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr)
{
UINT32 index;
UINT32 formatId;
UINT32 numFormats;
UINT32* pFormatIds;
const char* formatName;
CLIPRDR_FORMAT* formats;
CLIPRDR_FORMAT_LIST formatList;
mfContext* mfc = (mfContext*) cliprdr->custom;
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
pFormatIds = NULL;
numFormats = ClipboardGetFormatIds(mfc->clipboard, &pFormatIds);
formats = (CLIPRDR_FORMAT*) calloc(numFormats, sizeof(CLIPRDR_FORMAT));
if (!formats)
return -1;
for (index = 0; index < numFormats; index++)
{
formatId = pFormatIds[index];
formatName = ClipboardGetFormatName(mfc->clipboard, formatId);
formats[index].formatId = formatId;
formats[index].formatName = NULL;
if ((formatId > CF_MAX) && formatName)
formats[index].formatName = _strdup(formatName);
}
formatList.msgFlags = CB_RESPONSE_OK;
formatList.numFormats = numFormats;
formatList.formats = formats;
mfc->cliprdr->ClientFormatList(mfc->cliprdr, &formatList);
free(pFormatIds);
free(formats);
return 1;
}
int mac_cliprdr_send_client_format_data_request(CliprdrClientContext* cliprdr, UINT32 formatId)
{
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
mfContext* mfc = (mfContext*) cliprdr->custom;
ZeroMemory(&formatDataRequest, sizeof(CLIPRDR_FORMAT_DATA_REQUEST));
formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST;
formatDataRequest.msgFlags = 0;
formatDataRequest.requestedFormatId = formatId;
mfc->requestedFormatId = formatId;
ResetEvent(mfc->clipboardRequestEvent);
cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
return 1;
}
int mac_cliprdr_send_client_capabilities(CliprdrClientContext* cliprdr)
{
CLIPRDR_CAPABILITIES capabilities;
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
capabilities.cCapabilitiesSets = 1;
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet);
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
generalCapabilitySet.capabilitySetLength = 12;
generalCapabilitySet.version = CB_CAPS_VERSION_2;
generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
cliprdr->ClientCapabilities(cliprdr, &capabilities);
return 1;
}
int mac_cliprdr_monitor_ready(CliprdrClientContext* cliprdr, CLIPRDR_MONITOR_READY* monitorReady)
{
mfContext* mfc = (mfContext*) cliprdr->custom;
mfc->clipboardSync = TRUE;
mac_cliprdr_send_client_capabilities(cliprdr);
mac_cliprdr_send_client_format_list(cliprdr);
return 1;
}
int mac_cliprdr_server_capabilities(CliprdrClientContext* cliprdr, CLIPRDR_CAPABILITIES* capabilities)
{
UINT32 index;
CLIPRDR_CAPABILITY_SET* capabilitySet;
mfContext* mfc = (mfContext*) cliprdr->custom;
for (index = 0; index < capabilities->cCapabilitiesSets; index++)
{
capabilitySet = &(capabilities->capabilitySets[index]);
if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
(capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
{
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet
= (CLIPRDR_GENERAL_CAPABILITY_SET*) capabilitySet;
mfc->clipboardCapabilities = generalCapabilitySet->generalFlags;
break;
}
}
return 1;
}
int mac_cliprdr_server_format_list(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST* formatList)
{
UINT32 index;
CLIPRDR_FORMAT* format;
mfContext* mfc = (mfContext*) cliprdr->custom;
if (mfc->serverFormats)
{
for (index = 0; index < mfc->numServerFormats; index++)
{
free(mfc->serverFormats[index].formatName);
}
free(mfc->serverFormats);
mfc->serverFormats = NULL;
mfc->numServerFormats = 0;
}
if (formatList->numFormats < 1)
return 1;
mfc->numServerFormats = formatList->numFormats;
mfc->serverFormats = (CLIPRDR_FORMAT*) calloc(mfc->numServerFormats, sizeof(CLIPRDR_FORMAT));
if (!mfc->serverFormats)
return -1;
for (index = 0; index < mfc->numServerFormats; index++)
{
mfc->serverFormats[index].formatId = formatList->formats[index].formatId;
mfc->serverFormats[index].formatName = NULL;
if (formatList->formats[index].formatName)
mfc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName);
}
for (index = 0; index < mfc->numServerFormats; index++)
{
format = &(mfc->serverFormats[index]);
if (format->formatId == CF_UNICODETEXT)
{
mac_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT);
break;
}
else if (format->formatId == CF_TEXT)
{
mac_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT);
break;
}
}
return 1;
}
int mac_cliprdr_server_format_list_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
{
return 1;
}
int mac_cliprdr_server_lock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
{
return 1;
}
int mac_cliprdr_server_unlock_clipboard_data(CliprdrClientContext* cliprdr, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
{
return 1;
}
int mac_cliprdr_server_format_data_request(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
BYTE* data;
UINT32 size;
UINT32 formatId;
CLIPRDR_FORMAT_DATA_RESPONSE response;
mfContext* mfc = (mfContext*) cliprdr->custom;
ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
formatId = formatDataRequest->requestedFormatId;
data = (BYTE*) ClipboardGetData(mfc->clipboard, formatId, &size);
response.msgFlags = CB_RESPONSE_OK;
response.dataLen = size;
response.requestedFormatData = data;
if (!data)
{
response.msgFlags = CB_RESPONSE_FAIL;
response.dataLen = 0;
response.requestedFormatData = NULL;
}
cliprdr->ClientFormatDataResponse(cliprdr, &response);
free(data);
return 1;
}
int mac_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
BYTE* data;
UINT32 size;
UINT32 index;
UINT32 formatId;
CLIPRDR_FORMAT* format = NULL;
mfContext* mfc = (mfContext*) cliprdr->custom;
MRDPView* view = (MRDPView*) mfc->view;
for (index = 0; index < mfc->numServerFormats; index++)
{
if (mfc->requestedFormatId == mfc->serverFormats[index].formatId)
format = &(mfc->serverFormats[index]);
}
if (!format)
{
SetEvent(mfc->clipboardRequestEvent);
return -1;
}
if (format->formatName)
formatId = ClipboardRegisterFormat(mfc->clipboard, format->formatName);
else
formatId = format->formatId;
size = formatDataResponse->dataLen;
data = (BYTE*) malloc(size);
CopyMemory(data, formatDataResponse->requestedFormatData, size);
ClipboardSetData(mfc->clipboard, formatId, data, size);
SetEvent(mfc->clipboardRequestEvent);
if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT))
{
formatId = ClipboardRegisterFormat(mfc->clipboard, "UTF8_STRING");
data = (void*) ClipboardGetData(mfc->clipboard, formatId, &size);
NSString* str = [[NSString alloc] initWithBytes: (void*) data length:size encoding:NSUTF8StringEncoding];
free(data);
NSArray* types = [[NSArray alloc] initWithObjects:NSStringPboardType, nil];
[view->pasteboard_wr declareTypes:types owner:view];
[view->pasteboard_wr setString:str forType:NSStringPboardType];
}
return 1;
}
int mac_cliprdr_server_file_contents_request(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
return 1;
}
int mac_cliprdr_server_file_contents_response(CliprdrClientContext* cliprdr, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
{
return 1;
}
void mac_cliprdr_init(mfContext* mfc, CliprdrClientContext* cliprdr)
{
cliprdr->custom = (void*) mfc;
mfc->cliprdr = cliprdr;
mfc->clipboard = ClipboardCreate();
mfc->clipboardRequestEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
cliprdr->MonitorReady = mac_cliprdr_monitor_ready;
cliprdr->ServerCapabilities = mac_cliprdr_server_capabilities;
cliprdr->ServerFormatList = mac_cliprdr_server_format_list;
cliprdr->ServerFormatListResponse = mac_cliprdr_server_format_list_response;
cliprdr->ServerLockClipboardData = mac_cliprdr_server_lock_clipboard_data;
cliprdr->ServerUnlockClipboardData = mac_cliprdr_server_unlock_clipboard_data;
cliprdr->ServerFormatDataRequest = mac_cliprdr_server_format_data_request;
cliprdr->ServerFormatDataResponse = mac_cliprdr_server_format_data_response;
cliprdr->ServerFileContentsRequest = mac_cliprdr_server_file_contents_request;
cliprdr->ServerFileContentsResponse = mac_cliprdr_server_file_contents_response;
}
void mac_cliprdr_uninit(mfContext* mfc, CliprdrClientContext* cliprdr)
{
cliprdr->custom = NULL;
mfc->cliprdr = NULL;
ClipboardDestroy(mfc->clipboard);
CloseHandle(mfc->clipboardRequestEvent);
}

View File

@@ -51,8 +51,8 @@
BOOL skipMoveWindowOnce;
@public
NSPasteboard* pasteboard_rd; /* for reading from clipboard */
NSPasteboard* pasteboard_wr; /* for writing to clipboard */
NSPasteboard* pasteboard_rd;
NSPasteboard* pasteboard_wr;
int pasteboard_changecount;
int pasteboard_format;
int is_connected;
@@ -63,6 +63,8 @@
- (void) setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height;
- (void) onPasteboardTimerFired :(NSTimer *) timer;
- (void) pause;
- (void) resume;
- (void) releaseResources;
@property (assign) int is_connected;

View File

@@ -23,6 +23,7 @@
#import "mfreerdp.h"
#import "MRDPView.h"
#import "MRDPCursor.h"
#import "Clipboard.h"
#import "PasswordDialog.h"
#include <winpr/crt.h>
@@ -39,8 +40,6 @@
#import "freerdp/gdi/dc.h"
#import "freerdp/gdi/region.h"
#import "freerdp/graphics.h"
#import "freerdp/utils/event.h"
#import "freerdp/client/cliprdr.h"
#import "freerdp/client/file.h"
#import "freerdp/client/cmdline.h"
#import "freerdp/log.h"
@@ -59,39 +58,9 @@ void mac_desktop_resize(rdpContext* context);
static void update_activity_cb(freerdp* instance);
static void input_activity_cb(freerdp* instance);
static void channel_activity_cb(freerdp* instance);
int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data);
int receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, int flags, int total_size);
void process_cliprdr_event(freerdp* instance, wMessage* event);
void cliprdr_process_cb_format_list_event(freerdp* instance, RDP_CB_FORMAT_LIST_EVENT* event);
void cliprdr_send_data_request(freerdp* instance, UINT32 format);
void cliprdr_process_cb_monitor_ready_event(freerdp* inst);
void cliprdr_process_cb_data_response_event(freerdp* instance, RDP_CB_DATA_RESPONSE_EVENT* event);
void cliprdr_process_text(freerdp* instance, BYTE* data, int len);
void cliprdr_send_supported_format_list(freerdp* instance);
int register_channel_fds(int* fds, int count, freerdp* instance);
DWORD mac_client_thread(void* param);
struct cursor
{
rdpPointer* pointer;
BYTE* cursor_data;
void* bmiRep; /* NSBitmapImageRep */
void* nsCursor; /* NSCursor */
void* nsImage; /* NSImage */
};
struct rgba_data
{
char red;
char green;
char blue;
char alpha;
};
@implementation MRDPView
@synthesize is_connected;
@@ -183,43 +152,6 @@ DWORD mac_client_input_thread(void* param)
return 0;
}
DWORD mac_client_channels_thread(void* param)
{
int status;
wMessage* event;
HANDLE channelsEvent;
rdpChannels* channels;
rdpContext* context = (rdpContext*) param;
channels = context->channels;
channelsEvent = freerdp_channels_get_event_handle(context->instance);
while (WaitForSingleObject(channelsEvent, INFINITE) == WAIT_OBJECT_0)
{
status = freerdp_channels_process_pending_messages(context->instance);
if (!status)
break;
event = freerdp_channels_pop_event(context->channels);
if (event)
{
switch (GetMessageClass(event->id))
{
case CliprdrChannel_Class:
process_cliprdr_event(context->instance, event);
break;
}
freerdp_event_free(event);
}
}
ExitThread(0);
return 0;
}
DWORD mac_client_thread(void* param)
{
@autoreleasepool
@@ -231,7 +163,6 @@ DWORD mac_client_thread(void* param)
HANDLE updateEvent;
HANDLE updateThread;
HANDLE channelsEvent;
HANDLE channelsThread;
DWORD nCount;
rdpContext* context = (rdpContext*) param;
@@ -272,14 +203,7 @@ DWORD mac_client_thread(void* param)
events[nCount++] = inputEvent = freerdp_get_message_queue_event_handle(instance, FREERDP_INPUT_MESSAGE_QUEUE);
}
if (settings->AsyncChannels)
{
channelsThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) mac_client_channels_thread, context, 0, NULL);
}
else
{
events[nCount++] = channelsEvent = freerdp_channels_get_event_handle(instance);
}
events[nCount++] = channelsEvent = freerdp_channels_get_event_handle(instance);
while (1)
{
@@ -307,12 +231,9 @@ DWORD mac_client_thread(void* param)
}
}
if (!settings->AsyncChannels)
if (WaitForSingleObject(channelsEvent, 0) == WAIT_OBJECT_0)
{
if (WaitForSingleObject(channelsEvent, 0) == WAIT_OBJECT_0)
{
channel_activity_cb(instance);
}
freerdp_channels_process_pending_messages(instance);
}
}
@@ -332,12 +253,6 @@ DWORD mac_client_thread(void* param)
CloseHandle(inputThread);
}
if (settings->AsyncChannels)
{
WaitForSingleObject(channelsThread, INFINITE);
CloseHandle(channelsThread);
}
ExitThread(0);
return 0;
}
@@ -798,21 +713,87 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
- (void) onPasteboardTimerFired :(NSTimer*) timer
{
int i;
NSArray* types;
BYTE* data;
UINT32 size;
UINT32 formatId;
BOOL formatMatch;
int changeCount;
NSData* formatData;
const char* formatType;
NSPasteboardItem* item;
i = (int) [pasteboard_rd changeCount];
changeCount = (int) [pasteboard_rd changeCount];
if (i != pasteboard_changecount)
if (changeCount == pasteboard_changecount)
return;
pasteboard_changecount = changeCount;
NSArray* items = [pasteboard_rd pasteboardItems];
if ([items count] < 1)
return;
item = [items objectAtIndex:0];
/**
* System-Declared Uniform Type Identifiers:
* https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html
*/
formatMatch = FALSE;
for (NSString* type in [item types])
{
pasteboard_changecount = i;
types = [NSArray arrayWithObject:NSStringPboardType];
NSString *str = [pasteboard_rd availableTypeFromArray:types];
if (str != nil)
formatType = [type UTF8String];
if (strcmp(formatType, "public.utf8-plain-text") == 0)
{
cliprdr_send_supported_format_list(instance);
formatData = [item dataForType:type];
formatId = ClipboardRegisterFormat(mfc->clipboard, "UTF8_STRING");
size = (UINT32) [formatData length];
data = (BYTE*) malloc(size);
[formatData getBytes:data length:size];
ClipboardSetData(mfc->clipboard, formatId, (void*) data, size);
formatMatch = TRUE;
break;
}
}
if (!formatMatch)
ClipboardEmpty(mfc->clipboard);
if (mfc->clipboardSync)
mac_cliprdr_send_client_format_list(mfc->cliprdr);
}
- (void) pause
{
dispatch_async(dispatch_get_main_queue(), ^{
[self->pasteboard_timer invalidate];
});
NSArray* trackingAreas = self.trackingAreas;
for (NSTrackingArea* ta in trackingAreas)
{
[self removeTrackingArea:ta];
}
}
- (void)resume
{
dispatch_async(dispatch_get_main_queue(), ^{
self->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES];
});
NSTrackingArea * trackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingCursorUpdate | NSTrackingEnabledDuringMouseDrag | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
[trackingArea release];
}
- (void) setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height
@@ -826,6 +807,7 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
void mac_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e)
{
rdpSettings* settings = context->settings;
mfContext* mfc = (mfContext*) context;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
@@ -836,6 +818,10 @@ void mac_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEve
if (settings->SoftwareGdi)
gdi_graphics_pipeline_init(context->gdi, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
{
mac_cliprdr_init(mfc, (CliprdrClientContext*) e->pInterface);
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
@@ -845,6 +831,7 @@ void mac_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEve
void mac_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnectedEventArgs* e)
{
rdpSettings* settings = context->settings;
mfContext* mfc = (mfContext*) context;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
@@ -855,6 +842,10 @@ void mac_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnec
if (settings->SoftwareGdi)
gdi_graphics_pipeline_uninit(context->gdi, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
{
mac_cliprdr_uninit(mfc, (CliprdrClientContext*) e->pInterface);
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
@@ -963,9 +954,12 @@ BOOL mac_post_connect(freerdp* instance)
view->pasteboard_wr = [NSPasteboard generalPasteboard];
/* setup pasteboard for read operations */
view->pasteboard_rd = [NSPasteboard generalPasteboard];
view->pasteboard_changecount = (int) [view->pasteboard_rd changeCount];
view->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:mfc->view selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES];
dispatch_async(dispatch_get_main_queue(), ^{
view->pasteboard_rd = [NSPasteboard generalPasteboard];
view->pasteboard_changecount = -1;
});
[view resume];
mfc->appleKeyboardType = mac_detect_keyboard_type();
@@ -1272,212 +1266,6 @@ static void input_activity_cb(freerdp* instance)
}
}
static void channel_activity_cb(freerdp* instance)
{
wMessage* event;
freerdp_channels_process_pending_messages(instance);
event = freerdp_channels_pop_event(instance->context->channels);
if (event)
{
WLog_DBG(TAG, "channel_activity_cb: message %d", event->id);
switch (GetMessageClass(event->id))
{
case CliprdrChannel_Class:
process_cliprdr_event(instance, event);
break;
}
freerdp_event_free(event);
}
}
int process_plugin_args(rdpSettings* settings, const char* name, RDP_PLUGIN_DATA* plugin_data, void* user_data)
{
rdpChannels* channels = (rdpChannels*) user_data;
freerdp_channels_load_plugin(channels, settings, name, plugin_data);
return 1;
}
/*
* stuff related to clipboard redirection
*/
void cliprdr_process_cb_data_request_event(freerdp* instance)
{
int len;
NSArray* types;
RDP_CB_DATA_RESPONSE_EVENT* event;
mfContext* mfc = (mfContext*) instance->context;
MRDPView* view = (MRDPView*) mfc->view;
event = (RDP_CB_DATA_RESPONSE_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataResponse, NULL, NULL);
types = [NSArray arrayWithObject:NSStringPboardType];
NSString* str = [view->pasteboard_rd availableTypeFromArray:types];
if (str == nil)
{
event->data = NULL;
event->size = 0;
}
else
{
NSString* data = [view->pasteboard_rd stringForType:NSStringPboardType];
len = (int) ([data length] * 2 + 2);
event->data = malloc(len);
[data getCString:(char *) event->data maxLength:len encoding:NSUnicodeStringEncoding];
event->size = len;
}
freerdp_channels_send_event(instance->context->channels, (wMessage*) event);
}
void cliprdr_send_data_request(freerdp* instance, UINT32 format)
{
RDP_CB_DATA_REQUEST_EVENT* event;
event = (RDP_CB_DATA_REQUEST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_DataRequest, NULL, NULL);
event->format = format;
freerdp_channels_send_event(instance->context->channels, (wMessage*) event);
}
/**
* at the moment, only the following formats are supported
* CF_TEXT
* CF_UNICODETEXT
*/
void cliprdr_process_cb_data_response_event(freerdp* instance, RDP_CB_DATA_RESPONSE_EVENT* event)
{
NSString* str;
NSArray* types;
mfContext* mfc = (mfContext*) instance->context;
MRDPView* view = (MRDPView*) mfc->view;
if (event->size == 0)
return;
if (view->pasteboard_format == CF_TEXT || view->pasteboard_format == CF_UNICODETEXT)
{
str = [[NSString alloc] initWithCharacters:(unichar *) event->data length:event->size / 2];
types = [[NSArray alloc] initWithObjects:NSStringPboardType, nil];
[view->pasteboard_wr declareTypes:types owner:mfc->view];
[view->pasteboard_wr setString:str forType:NSStringPboardType];
}
}
void cliprdr_process_cb_monitor_ready_event(freerdp* instance)
{
wMessage* event;
RDP_CB_FORMAT_LIST_EVENT* format_list_event;
event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL);
format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event;
format_list_event->num_formats = 0;
freerdp_channels_send_event(instance->context->channels, event);
}
/**
* list of supported clipboard formats; currently only the following are supported
* CF_TEXT
* CF_UNICODETEXT
*/
void cliprdr_process_cb_format_list_event(freerdp* instance, RDP_CB_FORMAT_LIST_EVENT* event)
{
int i;
mfContext* mfc = (mfContext*) instance->context;
MRDPView* view = (MRDPView*) mfc->view;
if (event->num_formats == 0)
return;
for (i = 0; i < event->num_formats; i++)
{
switch (event->formats[i])
{
case CF_TEXT:
case CF_UNICODETEXT:
view->pasteboard_format = CF_UNICODETEXT;
cliprdr_send_data_request(instance, CF_UNICODETEXT);
return;
break;
}
}
}
void process_cliprdr_event(freerdp* instance, wMessage* event)
{
if (event)
{
switch (GetMessageType(event->id))
{
/*
* Monitor Ready PDU is sent by server to indicate that it has been
* initialized and is ready. This PDU is transmitted by the server after it has sent
* Clipboard Capabilities PDU
*/
case CliprdrChannel_MonitorReady:
cliprdr_process_cb_monitor_ready_event(instance);
break;
/*
* The Format List PDU is sent either by the client or the server when its
* local system clipboard is updated with new clipboard data. This PDU
* contains the Clipboard Format ID and name pairs of the new Clipboard
* Formats on the clipboard
*/
case CliprdrChannel_FormatList:
cliprdr_process_cb_format_list_event(instance, (RDP_CB_FORMAT_LIST_EVENT*) event);
break;
/*
* The Format Data Request PDU is sent by the receipient of the Format List PDU.
* It is used to request the data for one of the formats that was listed in the
* Format List PDU
*/
case CliprdrChannel_DataRequest:
cliprdr_process_cb_data_request_event(instance);
break;
/*
* The Format Data Response PDU is sent as a reply to the Format Data Request PDU.
* It is used to indicate whether processing of the Format Data Request PDU
* was successful. If the processing was successful, the Format Data Response PDU
* includes the contents of the requested clipboard data
*/
case CliprdrChannel_DataResponse:
cliprdr_process_cb_data_response_event(instance, (RDP_CB_DATA_RESPONSE_EVENT*) event);
break;
default:
WLog_ERR(TAG, "process_cliprdr_event: unknown event type %d", GetMessageType(event->id));
break;
}
}
}
void cliprdr_send_supported_format_list(freerdp* instance)
{
RDP_CB_FORMAT_LIST_EVENT* event;
event = (RDP_CB_FORMAT_LIST_EVENT*) freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL);
event->formats = (UINT32*) malloc(sizeof(UINT32) * 1);
event->num_formats = 1;
event->formats[0] = CF_UNICODETEXT;
freerdp_channels_send_event(instance->context->channels, (wMessage*) event);
}
/**
* given a rect with 0,0 at the top left (windows cords)
* convert it to a rect with 0,0 at the bottom left (apple cords)

View File

@@ -99,10 +99,8 @@ int mfreerdp_client_new(freerdp* instance, rdpContext* context)
settings = instance->settings;
settings->AsyncTransport = TRUE;
settings->AsyncUpdate = TRUE;
settings->AsyncInput = TRUE;
settings->AsyncChannels = TRUE;
return 0;
}

View File

@@ -19,11 +19,13 @@ typedef struct mf_context mfContext;
#include <freerdp/client/channels.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/encomsp.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/clipboard.h>
#include "MRDPView.h"
#include "Keyboard.h"
@@ -63,6 +65,15 @@ struct mf_context
DWORD keyboardThreadId;
BOOL disconnect;
BOOL sw_gdi;
BOOL clipboardSync;
wClipboard* clipboard;
UINT32 numServerFormats;
UINT32 requestedFormatId;
HANDLE clipboardRequestEvent;
CLIPRDR_FORMAT* serverFormats;
CliprdrClientContext* cliprdr;
UINT32 clipboardCapabilities;
rdpFile* connectionRdpFile;

View File

@@ -50,28 +50,12 @@
#define TAG CLIENT_TAG("sample")
struct tf_info
{
void* data;
};
typedef struct tf_info tfInfo;
struct tf_context
{
rdpContext _p;
tfInfo* tfi;
};
typedef struct tf_context tfContext;
HANDLE g_sem;
static int g_thread_count = 0;
struct thread_data
{
freerdp* instance;
};
int tf_context_new(freerdp* instance, rdpContext* context)
{
context->channels = freerdp_channels_new();
@@ -97,59 +81,12 @@ void tf_end_paint(rdpContext* context)
return;
}
int tf_receive_channel_data(freerdp* instance, UINT16 channelId, BYTE* data, int size, int flags, int total_size)
{
return freerdp_channels_data(instance, channelId, data, size, flags, total_size);
}
void tf_process_cb_monitor_ready_event(rdpChannels* channels, freerdp* instance)
{
wMessage* event;
RDP_CB_FORMAT_LIST_EVENT* format_list_event;
event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL, NULL);
format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event;
format_list_event->num_formats = 0;
freerdp_channels_send_event(channels, event);
}
void tf_process_channel_event(rdpChannels* channels, freerdp* instance)
{
wMessage* event;
event = freerdp_channels_pop_event(channels);
if (event)
{
switch (GetMessageType(event->id))
{
case CliprdrChannel_MonitorReady:
tf_process_cb_monitor_ready_event(channels, instance);
break;
default:
WLog_ERR(TAG, "unknown event type %d", GetMessageType(event->id));
break;
}
freerdp_event_free(event);
}
}
BOOL tf_pre_connect(freerdp* instance)
{
tfInfo* tfi;
tfContext* context;
tfContext* tfc;
rdpSettings* settings;
context = (tfContext*) instance->context;
tfi = (tfInfo*) malloc(sizeof(tfInfo));
ZeroMemory(tfi, sizeof(tfInfo));
context->tfi = tfi;
tfc = (tfContext*) instance->context;
settings = instance->settings;
@@ -220,12 +157,14 @@ int tfreerdp_run(freerdp* instance)
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
if (!freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount))
{
WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
break;
}
if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
if (!freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount))
{
WLog_ERR(TAG, "Failed to get channel manager file descriptor");
break;
@@ -261,17 +200,17 @@ int tfreerdp_run(freerdp* instance)
}
}
if (freerdp_check_fds(instance) != TRUE)
if (!freerdp_check_fds(instance))
{
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
break;
}
if (freerdp_channels_check_fds(channels, instance) != TRUE)
if (!freerdp_channels_check_fds(channels, instance))
{
WLog_ERR(TAG, "Failed to check channel manager file descriptor");
break;
}
tf_process_channel_event(channels, instance);
}
freerdp_channels_close(channels, instance);
@@ -281,21 +220,89 @@ int tfreerdp_run(freerdp* instance)
return 0;
}
void* thread_func(void* param)
void* tf_client_thread_proc(freerdp* instance)
{
struct thread_data* data;
data = (struct thread_data*) param;
int i;
int fds;
int max_fds;
int rcount;
int wcount;
void* rfds[32];
void* wfds[32];
fd_set rfds_set;
fd_set wfds_set;
rdpChannels* channels;
tfreerdp_run(data->instance);
channels = instance->context->channels;
free(data);
freerdp_connect(instance);
pthread_detach(pthread_self());
while (1)
{
rcount = 0;
wcount = 0;
g_thread_count--;
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
if (g_thread_count < 1)
ReleaseSemaphore(g_sem, 1, NULL);
if (!freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount))
{
WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
break;
}
if (!freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount))
{
WLog_ERR(TAG, "Failed to get channel manager file descriptor");
break;
}
max_fds = 0;
FD_ZERO(&rfds_set);
FD_ZERO(&wfds_set);
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
if (fds > max_fds)
max_fds = fds;
FD_SET(fds, &rfds_set);
}
if (max_fds == 0)
break;
if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1)
{
/* these are not really errors */
if (!((errno == EAGAIN) ||
(errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
{
WLog_ERR(TAG, "tfreerdp_run: select failed");
break;
}
}
if (!freerdp_check_fds(instance))
{
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
break;
}
if (!freerdp_channels_check_fds(channels, instance))
{
WLog_ERR(TAG, "Failed to check channel manager file descriptor");
break;
}
}
freerdp_channels_close(channels, instance);
freerdp_channels_free(channels);
freerdp_free(instance);
ExitThread(0);
return NULL;
@@ -304,17 +311,13 @@ void* thread_func(void* param)
int main(int argc, char* argv[])
{
int status;
pthread_t thread;
HANDLE thread;
freerdp* instance;
rdpChannels* channels;
struct thread_data* data;
g_sem = CreateSemaphore(NULL, 0, 1, NULL);
instance = freerdp_new();
instance->PreConnect = tf_pre_connect;
instance->PostConnect = tf_post_connect;
instance->ReceiveChannelData = tf_receive_channel_data;
instance->ContextSize = sizeof(tfContext);
instance->ContextNew = tf_context_new;
@@ -326,22 +329,16 @@ int main(int argc, char* argv[])
status = freerdp_client_settings_parse_command_line(instance->settings, argc, argv);
if (status < 0)
{
exit(0);
}
freerdp_client_load_addins(instance->context->channels, instance->settings);
data = (struct thread_data*) malloc(sizeof(struct thread_data));
ZeroMemory(data, sizeof(sizeof(struct thread_data)));
thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
tf_client_thread_proc, instance, 0, NULL);
data->instance = instance;
g_thread_count++;
pthread_create(&thread, 0, thread_func, data);
while (g_thread_count > 0)
{
WaitForSingleObject(g_sem, INFINITE);
}
WaitForSingleObject(thread, INFINITE);
return 0;
}

View File

@@ -27,6 +27,7 @@
#include "xfreerdp.h"
#include "xf_gfx.h"
#include "xf_tsmf.h"
#include "xf_cliprdr.h"
void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEventArgs* e)
@@ -38,6 +39,10 @@ void xf_OnChannelConnectedEventHandler(rdpContext* context, ChannelConnectedEven
{
xfc->rdpei = (RdpeiClientContext*) e->pInterface;
}
else if (strcmp(e->name, TSMF_DVC_CHANNEL_NAME) == 0)
{
xf_tsmf_init(xfc, (TsmfClientContext*) e->pInterface);
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
@@ -64,6 +69,10 @@ void xf_OnChannelDisconnectedEventHandler(rdpContext* context, ChannelDisconnect
{
xfc->rdpei = NULL;
}
else if (strcmp(e->name, TSMF_DVC_CHANNEL_NAME) == 0)
{
xf_tsmf_uninit(xfc, (TsmfClientContext*) e->pInterface);
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)

View File

@@ -23,6 +23,7 @@
#include <freerdp/freerdp.h>
#include <freerdp/client/channels.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/tsmf.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/client/encomsp.h>

View File

@@ -104,7 +104,6 @@
#include <freerdp/log.h>
#define TAG CLIENT_TAG("x11")
static long xv_port = 0;
static const size_t password_size = 512;
void xf_transform_window(xfContext *xfc)
@@ -1020,7 +1019,6 @@ BOOL xf_post_connect(freerdp *instance)
xfc->clipboard = xf_clipboard_new(xfc);
freerdp_channels_post_connect(channels, instance);
xf_tsmf_init(xfc, xv_port);
EventArgsInit(&e, "xfreerdp");
e.width = settings->DesktopWidth;
@@ -1121,10 +1119,6 @@ void xf_process_channel_event(rdpChannels* channels, freerdp* instance)
xf_process_rail_event(xfc, channels, event);
break;
case TsmfChannel_Class:
xf_process_tsmf_event(xfc, event);
break;
default:
break;
}
@@ -1195,7 +1189,7 @@ void xf_window_free(xfContext *xfc)
if (xfc->xv_context)
{
xf_tsmf_uninit(xfc);
xf_tsmf_uninit(xfc, NULL);
xfc->xv_context = NULL;
}

View File

@@ -217,28 +217,6 @@ BOOL xf_set_rop3(xfContext* xfc, int rop3)
return TRUE;
}
unsigned long xf_gdi_get_color(xfContext* xfc, GDI_COLOR color)
{
XColor x11_color;
x11_color.flags = DoRed | DoGreen | DoBlue;
GetRGB32(x11_color.red, x11_color.green, x11_color.blue, color);
x11_color.red = x11_color.red << 8;
x11_color.green = x11_color.green << 8;
x11_color.blue = x11_color.blue << 8;
if (XAllocColor(xfc->display, xfc->colormap, &x11_color) != 0)
{
XFreeColors(xfc->display, xfc->colormap, &x11_color.pixel, 1, 0);
}
else
{
x11_color.pixel = BlackPixel(xfc->display, xfc->screen_number);
}
return x11_color.pixel;
}
Pixmap xf_brush_new(xfContext* xfc, int width, int height, int bpp, BYTE* data)
{
GC gc;
@@ -488,9 +466,7 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
xf_set_rop3(xfc, gdi_rop3_code(patblt->bRop));
foreColor = freerdp_convert_gdi_order_color(patblt->foreColor, context->settings->ColorDepth, xfc->format, xfc->palette);
foreColor = xf_gdi_get_color(xfc, foreColor);
backColor = freerdp_convert_gdi_order_color(patblt->backColor, context->settings->ColorDepth, xfc->format, xfc->palette);
backColor = xf_gdi_get_color(xfc, backColor);
if (brush->style == GDI_BS_SOLID)
{
@@ -610,7 +586,6 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
xf_lock_x11(xfc, FALSE);
color = freerdp_convert_gdi_order_color(opaque_rect->color, context->settings->ColorDepth, xfc->format, xfc->palette);
color = xf_gdi_get_color(xfc, color);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
@@ -646,7 +621,6 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult
xf_lock_x11(xfc, FALSE);
color = freerdp_convert_gdi_order_color(multi_opaque_rect->color, context->settings->ColorDepth, xfc->format, xfc->palette);
color = xf_gdi_get_color(xfc, color);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
@@ -689,7 +663,6 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
xf_set_rop2(xfc, line_to->bRop2);
color = freerdp_convert_gdi_order_color(line_to->penColor, context->settings->ColorDepth, xfc->format, xfc->palette);
color = xf_gdi_get_color(xfc, color);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetForeground(xfc->display, xfc->gc, color);
@@ -741,7 +714,6 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
xf_set_rop2(xfc, polyline->bRop2);
color = freerdp_convert_gdi_order_color(polyline->penColor, context->settings->ColorDepth, xfc->format, xfc->palette);
color = xf_gdi_get_color(xfc, color);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetForeground(xfc->display, xfc->gc, color);
@@ -841,9 +813,7 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
bitmap = (xfBitmap*) mem3blt->bitmap;
xf_set_rop3(xfc, gdi_rop3_code(mem3blt->bRop));
foreColor = freerdp_convert_gdi_order_color(mem3blt->foreColor, context->settings->ColorDepth, xfc->format, xfc->palette);
foreColor = xf_gdi_get_color(xfc, foreColor);
backColor = freerdp_convert_gdi_order_color(mem3blt->backColor, context->settings->ColorDepth, xfc->format, xfc->palette);
backColor = xf_gdi_get_color(xfc, backColor);
if (brush->style == GDI_BS_PATTERN)
{
@@ -916,7 +886,6 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
xf_set_rop2(xfc, polygon_sc->bRop2);
brush_color = freerdp_convert_gdi_order_color(polygon_sc->brushColor, context->settings->ColorDepth, xfc->format, xfc->palette);
brush_color = xf_gdi_get_color(xfc, brush_color);
npoints = polygon_sc->numPoints + 1;
points = malloc(sizeof(XPoint) * npoints);
@@ -978,9 +947,7 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
brush = &(polygon_cb->brush);
xf_set_rop2(xfc, polygon_cb->bRop2);
foreColor = freerdp_convert_gdi_order_color(polygon_cb->foreColor, context->settings->ColorDepth, xfc->format, xfc->palette);
foreColor = xf_gdi_get_color(xfc, foreColor);
backColor = freerdp_convert_gdi_order_color(polygon_cb->backColor, context->settings->ColorDepth, xfc->format, xfc->palette);
backColor = xf_gdi_get_color(xfc, backColor);
npoints = polygon_cb->numPoints + 1;
points = malloc(sizeof(XPoint) * npoints);
@@ -1005,7 +972,7 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
break;
default:
WLog_ERR(TAG, "PolygonCB unknown fillMode: %d", polygon_cb->fillMode);
WLog_ERR(TAG, "PolygonCB unknown fillMode: %d", polygon_cb->fillMode);
break;
}

View File

@@ -386,9 +386,6 @@ void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height
xf_lock_x11(xfc, FALSE);
fgcolor = xf_gdi_get_color(xfc, fgcolor);
bgcolor = xf_gdi_get_color(xfc, bgcolor);
XSetFunction(xfc->display, xfc->gc, GXcopy);
if (width && height)

View File

@@ -21,9 +21,7 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <sys/ipc.h>
#include <sys/shm.h>
@@ -33,8 +31,6 @@
#include <X11/Xatom.h>
#include <X11/extensions/XShm.h>
#include <winpr/crt.h>
#include <freerdp/utils/event.h>
#include <freerdp/log.h>
#include <freerdp/client/tsmf.h>
@@ -46,7 +42,7 @@
#include <X11/extensions/Xv.h>
#include <X11/extensions/Xvlib.h>
typedef struct xf_xv_context xfXvContext;
static long xv_port = 0;
struct xf_xv_context
{
@@ -57,15 +53,256 @@ struct xf_xv_context
char* xv_shmaddr;
UINT32* xv_pixfmts;
};
typedef struct xf_xv_context xfXvContext;
#define TAG CLIENT_TAG("x11")
#ifdef WITH_DEBUG_XV
#define DEBUG_XV(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__)
#else
#define DEBUG_XV(fmt, ...) do { } while (0)
#endif
void xf_tsmf_init(xfContext* xfc, long xv_port)
static BOOL xf_tsmf_is_format_supported(xfXvContext* xv, UINT32 pixfmt)
{
int i;
if (!xv->xv_pixfmts)
return FALSE;
for (i = 0; xv->xv_pixfmts[i]; i++)
{
if (xv->xv_pixfmts[i] == pixfmt)
return TRUE;
}
return FALSE;
}
int xf_tsmf_xv_video_frame_event(TsmfClientContext* tsmf, TSMF_VIDEO_FRAME_EVENT* event)
{
int i;
int x, y;
UINT32 width;
UINT32 height;
BYTE* data1;
BYTE* data2;
UINT32 pixfmt;
UINT32 xvpixfmt;
XvImage* image;
int colorkey = 0;
int numRects = 0;
xfContext* xfc;
xfXvContext* xv;
XRectangle* xrects;
XShmSegmentInfo shminfo;
BOOL converti420yv12 = FALSE;
if (!tsmf)
return -1;
xfc = (xfContext*) tsmf->custom;
if (!xfc)
return -1;
xv = (xfXvContext*) xfc->xv_context;
if (!xv)
return -1;
if (xv->xv_port == 0)
return -1001;
/* In case the player is minimized */
if (event->x < -2048 || event->y < -2048 || event->numVisibleRects < 0)
{
return -1002;
}
xrects = NULL;
numRects = event->numVisibleRects;
if (numRects > 0)
{
xrects = (XRectangle*) calloc(numRects, sizeof(XRectangle));
if (!xrects)
return -1;
for (i = 0; i < numRects; i++)
{
x = event->x + event->visibleRects[i].left;
y = event->y + event->visibleRects[i].top;
width = event->visibleRects[i].right - event->visibleRects[i].left;
height = event->visibleRects[i].bottom - event->visibleRects[i].top;
xrects[i].x = x;
xrects[i].y = y;
xrects[i].width = width;
xrects[i].height = height;
}
}
if (xv->xv_colorkey_atom != None)
{
XvGetPortAttribute(xfc->display, xv->xv_port, xv->xv_colorkey_atom, &colorkey);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetForeground(xfc->display, xfc->gc, colorkey);
if (event->numVisibleRects < 1)
{
XSetClipMask(xfc->display, xfc->gc, None);
}
else
{
XFillRectangles(xfc->display, xfc->window->handle, xfc->gc, xrects, numRects);
}
}
else
{
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
if (event->numVisibleRects < 1)
{
XSetClipMask(xfc->display, xfc->gc, None);
}
else
{
XSetClipRectangles(xfc->display, xfc->gc, 0, 0, xrects, numRects, YXBanded);
}
}
pixfmt = event->framePixFmt;
if (xf_tsmf_is_format_supported(xv, pixfmt))
{
xvpixfmt = pixfmt;
}
else if (pixfmt == RDP_PIXFMT_I420 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_YV12))
{
xvpixfmt = RDP_PIXFMT_YV12;
converti420yv12 = TRUE;
}
else if (pixfmt == RDP_PIXFMT_YV12 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_I420))
{
xvpixfmt = RDP_PIXFMT_I420;
converti420yv12 = TRUE;
}
else
{
WLog_DBG(TAG, "pixel format 0x%X not supported by hardware.", pixfmt);
return -1003;
}
image = XvShmCreateImage(xfc->display, xv->xv_port,
xvpixfmt, 0, event->frameWidth, event->frameHeight, &shminfo);
if (xv->xv_image_size != image->data_size)
{
if (xv->xv_image_size > 0)
{
shmdt(xv->xv_shmaddr);
shmctl(xv->xv_shmid, IPC_RMID, NULL);
}
xv->xv_image_size = image->data_size;
xv->xv_shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777);
xv->xv_shmaddr = shmat(xv->xv_shmid, 0, 0);
}
shminfo.shmid = xv->xv_shmid;
shminfo.shmaddr = image->data = xv->xv_shmaddr;
shminfo.readOnly = FALSE;
if (!XShmAttach(xfc->display, &shminfo))
{
XFree(image);
WLog_DBG(TAG, "XShmAttach failed.");
return -1004;
}
/* The video driver may align each line to a different size
and we need to convert our original image data. */
switch (pixfmt)
{
case RDP_PIXFMT_I420:
case RDP_PIXFMT_YV12:
/* Y */
if (image->pitches[0] == event->frameWidth)
{
CopyMemory(image->data + image->offsets[0],
event->frameData,
event->frameWidth * event->frameHeight);
}
else
{
for (i = 0; i < event->frameHeight; i++)
{
CopyMemory(image->data + image->offsets[0] + i * image->pitches[0],
event->frameData + i * event->frameWidth,
event->frameWidth);
}
}
/* UV */
/* Conversion between I420 and YV12 is to simply swap U and V */
if (!converti420yv12)
{
data1 = event->frameData + event->frameWidth * event->frameHeight;
data2 = event->frameData + event->frameWidth * event->frameHeight +
event->frameWidth * event->frameHeight / 4;
}
else
{
data2 = event->frameData + event->frameWidth * event->frameHeight;
data1 = event->frameData + event->frameWidth * event->frameHeight +
event->frameWidth * event->frameHeight / 4;
image->id = pixfmt == RDP_PIXFMT_I420 ? RDP_PIXFMT_YV12 : RDP_PIXFMT_I420;
}
if (image->pitches[1] * 2 == event->frameWidth)
{
CopyMemory(image->data + image->offsets[1],
data1,
event->frameWidth * event->frameHeight / 4);
CopyMemory(image->data + image->offsets[2],
data2,
event->frameWidth * event->frameHeight / 4);
}
else
{
for (i = 0; i < event->frameHeight / 2; i++)
{
CopyMemory(image->data + image->offsets[1] + i * image->pitches[1],
data1 + i * event->frameWidth / 2,
event->frameWidth / 2);
CopyMemory(image->data + image->offsets[2] + i * image->pitches[2],
data2 + i * event->frameWidth / 2,
event->frameWidth / 2);
}
}
break;
default:
CopyMemory(image->data, event->frameData, image->data_size <= event->frameSize ?
image->data_size : event->frameSize);
break;
}
XvShmPutImage(xfc->display, xv->xv_port, xfc->window->handle, xfc->gc,
image, 0, 0, image->width, image->height,
event->x, event->y, event->width, event->height, FALSE);
if (xv->xv_colorkey_atom == None)
XSetClipMask(xfc->display, xfc->gc, None);
XSync(xfc->display, FALSE);
XShmDetach(xfc->display, &shminfo);
XFree(image);
free(xrects);
return 1;
}
int xf_tsmf_xv_init(xfContext* xfc, TsmfClientContext* tsmf)
{
int ret;
unsigned int i;
@@ -80,8 +317,13 @@ void xf_tsmf_init(xfContext* xfc, long xv_port)
XvAttribute* attr;
XvImageFormatValues* fo;
xv = (xfXvContext*) malloc(sizeof(xfXvContext));
ZeroMemory(xv, sizeof(xfXvContext));
if (xfc->xv_context)
return 1; /* context already created */
xv = (xfXvContext*) calloc(1, sizeof(xfXvContext));
if (!xv)
return -1;
xfc->xv_context = xv;
@@ -91,30 +333,34 @@ void xf_tsmf_init(xfContext* xfc, long xv_port)
if (!XShmQueryExtension(xfc->display))
{
DEBUG_XV("no shmem available.");
return;
WLog_DBG(TAG, "no xshm available.");
return -1;
}
ret = XvQueryExtension(xfc->display, &version, &release, &request_base, &event_base, &error_base);
if (ret != Success)
{
DEBUG_XV("XvQueryExtension failed %d.", ret);
return;
WLog_DBG(TAG, "XvQueryExtension failed %d.", ret);
return -1;
}
DEBUG_XV("version %u release %u", version, release);
WLog_DBG(TAG, "version %u release %u", version, release);
ret = XvQueryAdaptors(xfc->display, DefaultRootWindow(xfc->display),
&num_adaptors, &ai);
if (ret != Success)
{
DEBUG_XV("XvQueryAdaptors failed %d.", ret);
return;
WLog_DBG(TAG, "XvQueryAdaptors failed %d.", ret);
return -1;
}
for (i = 0; i < num_adaptors; i++)
{
DEBUG_XV("adapter port %ld-%ld (%s)", ai[i].base_id,
WLog_DBG(TAG, "adapter port %ld-%ld (%s)", ai[i].base_id,
ai[i].base_id + ai[i].num_ports - 1, ai[i].name);
if (xv->xv_port == 0 && i == num_adaptors - 1)
xv->xv_port = ai[i].base_id;
}
@@ -124,12 +370,13 @@ void xf_tsmf_init(xfContext* xfc, long xv_port)
if (xv->xv_port == 0)
{
DEBUG_XV("no adapter selected, video frames will not be processed.");
return;
WLog_DBG(TAG, "no adapter selected, video frames will not be processed.");
return -1;
}
DEBUG_XV("selected %ld", xv->xv_port);
WLog_DBG(TAG, "selected %ld", xv->xv_port);
attr = XvQueryPortAttributes(xfc->display, xv->xv_port, &ret);
for (i = 0; i < (unsigned int)ret; i++)
{
if (strcmp(attr[i].name, "XV_COLORKEY") == 0)
@@ -141,29 +388,36 @@ void xf_tsmf_init(xfContext* xfc, long xv_port)
}
XFree(attr);
#ifdef WITH_DEBUG_XV
WLog_DBG(TAG, "xf_tsmf_init: pixel format ");
#endif
fo = XvListImageFormats(xfc->display, xv->xv_port, &ret);
if (ret > 0)
{
xv->xv_pixfmts = (UINT32*) malloc((ret + 1) * sizeof(UINT32));
ZeroMemory(xv->xv_pixfmts, (ret + 1) * sizeof(UINT32));
xv->xv_pixfmts = (UINT32*) calloc((ret + 1), sizeof(UINT32));
for (i = 0; i < ret; i++)
{
xv->xv_pixfmts[i] = fo[i].id;
#ifdef WITH_DEBUG_XV
WLog_DBG(TAG, "%c%c%c%c ", ((char*)(xv->xv_pixfmts + i))[0], ((char*)(xv->xv_pixfmts + i))[1],
((char*)(xv->xv_pixfmts + i))[2], ((char*)(xv->xv_pixfmts + i))[3]);
#endif
}
xv->xv_pixfmts[i] = 0;
}
XFree(fo);
if (tsmf)
{
xfc->tsmf = tsmf;
tsmf->custom = (void*) xfc;
tsmf->FrameEvent = xf_tsmf_xv_video_frame_event;
}
return 1;
}
void xf_tsmf_uninit(xfContext* xfc)
int xf_tsmf_xv_uninit(xfContext* xfc, TsmfClientContext* tsmf)
{
xfXvContext* xv = (xfXvContext*) xfc->xv_context;
@@ -182,226 +436,33 @@ void xf_tsmf_uninit(xfContext* xfc)
free(xv);
xfc->xv_context = NULL;
}
if (xfc->tsmf)
{
xfc->tsmf->custom = NULL;
xfc->tsmf = NULL;
}
return 1;
}
static BOOL
xf_tsmf_is_format_supported(xfXvContext* xv, UINT32 pixfmt)
#endif
int xf_tsmf_init(xfContext* xfc, TsmfClientContext* tsmf)
{
int i;
#ifdef WITH_XV
return xf_tsmf_xv_init(xfc, tsmf);
#endif
if (!xv->xv_pixfmts)
return FALSE;
for (i = 0; xv->xv_pixfmts[i]; i++)
{
if (xv->xv_pixfmts[i] == pixfmt)
return TRUE;
}
return FALSE;
return 1;
}
static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EVENT* vevent)
int xf_tsmf_uninit(xfContext* xfc, TsmfClientContext* tsmf)
{
int i;
BYTE* data1;
BYTE* data2;
UINT32 pixfmt;
UINT32 xvpixfmt;
BOOL converti420yv12 = FALSE;
XvImage * image;
int colorkey = 0;
XShmSegmentInfo shminfo;
xfXvContext* xv = (xfXvContext*) xfc->xv_context;
#ifdef WITH_XV
return xf_tsmf_xv_uninit(xfc, tsmf);
#endif
if (xv->xv_port == 0)
return;
/* In case the player is minimized */
if (vevent->x < -2048 || vevent->y < -2048 || vevent->num_visible_rects <= 0)
return;
if (xv->xv_colorkey_atom != None)
{
XvGetPortAttribute(xfc->display, xv->xv_port, xv->xv_colorkey_atom, &colorkey);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetForeground(xfc->display, xfc->gc, colorkey);
for (i = 0; i < vevent->num_visible_rects; i++)
{
XFillRectangle(xfc->display, xfc->window->handle, xfc->gc,
vevent->x + vevent->visible_rects[i].x,
vevent->y + vevent->visible_rects[i].y,
vevent->visible_rects[i].width,
vevent->visible_rects[i].height);
}
}
else
{
XSetClipRectangles(xfc->display, xfc->gc, vevent->x, vevent->y,
(XRectangle*) vevent->visible_rects, vevent->num_visible_rects, YXBanded);
}
pixfmt = vevent->frame_pixfmt;
if (xf_tsmf_is_format_supported(xv, pixfmt))
{
xvpixfmt = pixfmt;
}
else if (pixfmt == RDP_PIXFMT_I420 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_YV12))
{
xvpixfmt = RDP_PIXFMT_YV12;
converti420yv12 = TRUE;
}
else if (pixfmt == RDP_PIXFMT_YV12 && xf_tsmf_is_format_supported(xv, RDP_PIXFMT_I420))
{
xvpixfmt = RDP_PIXFMT_I420;
converti420yv12 = TRUE;
}
else
{
DEBUG_XV("pixel format 0x%X not supported by hardware.", pixfmt);
return;
}
image = XvShmCreateImage(xfc->display, xv->xv_port,
xvpixfmt, 0, vevent->frame_width, vevent->frame_height, &shminfo);
if (xv->xv_image_size != image->data_size)
{
if (xv->xv_image_size > 0)
{
shmdt(xv->xv_shmaddr);
shmctl(xv->xv_shmid, IPC_RMID, NULL);
}
xv->xv_image_size = image->data_size;
xv->xv_shmid = shmget(IPC_PRIVATE, image->data_size, IPC_CREAT | 0777);
xv->xv_shmaddr = shmat(xv->xv_shmid, 0, 0);
}
shminfo.shmid = xv->xv_shmid;
shminfo.shmaddr = image->data = xv->xv_shmaddr;
shminfo.readOnly = FALSE;
if (!XShmAttach(xfc->display, &shminfo))
{
XFree(image);
DEBUG_XV("XShmAttach failed.");
return;
}
/* The video driver may align each line to a different size
and we need to convert our original image data. */
switch (pixfmt)
{
case RDP_PIXFMT_I420:
case RDP_PIXFMT_YV12:
/* Y */
if (image->pitches[0] == vevent->frame_width)
{
memcpy(image->data + image->offsets[0],
vevent->frame_data,
vevent->frame_width * vevent->frame_height);
}
else
{
for (i = 0; i < vevent->frame_height; i++)
{
memcpy(image->data + image->offsets[0] + i * image->pitches[0],
vevent->frame_data + i * vevent->frame_width,
vevent->frame_width);
}
}
/* UV */
/* Conversion between I420 and YV12 is to simply swap U and V */
if (converti420yv12 == FALSE)
{
data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height;
data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height +
vevent->frame_width * vevent->frame_height / 4;
}
else
{
data2 = vevent->frame_data + vevent->frame_width * vevent->frame_height;
data1 = vevent->frame_data + vevent->frame_width * vevent->frame_height +
vevent->frame_width * vevent->frame_height / 4;
image->id = pixfmt == RDP_PIXFMT_I420 ? RDP_PIXFMT_YV12 : RDP_PIXFMT_I420;
}
if (image->pitches[1] * 2 == vevent->frame_width)
{
memcpy(image->data + image->offsets[1],
data1,
vevent->frame_width * vevent->frame_height / 4);
memcpy(image->data + image->offsets[2],
data2,
vevent->frame_width * vevent->frame_height / 4);
}
else
{
for (i = 0; i < vevent->frame_height / 2; i++)
{
memcpy(image->data + image->offsets[1] + i * image->pitches[1],
data1 + i * vevent->frame_width / 2,
vevent->frame_width / 2);
memcpy(image->data + image->offsets[2] + i * image->pitches[2],
data2 + i * vevent->frame_width / 2,
vevent->frame_width / 2);
}
}
break;
default:
memcpy(image->data, vevent->frame_data, image->data_size <= vevent->frame_size ?
image->data_size : vevent->frame_size);
break;
}
XvShmPutImage(xfc->display, xv->xv_port, xfc->window->handle, xfc->gc, image,
0, 0, image->width, image->height,
vevent->x, vevent->y, vevent->width, vevent->height, FALSE);
if (xv->xv_colorkey_atom == None)
XSetClipMask(xfc->display, xfc->gc, None);
XSync(xfc->display, FALSE);
XShmDetach(xfc->display, &shminfo);
XFree(image);
return 1;
}
static void xf_process_tsmf_redraw_event(xfContext* xfc, RDP_REDRAW_EVENT* revent)
{
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
revent->x, revent->y, revent->width, revent->height, revent->x, revent->y);
}
void xf_process_tsmf_event(xfContext* xfc, wMessage* event)
{
switch (GetMessageType(event->id))
{
case TsmfChannel_VideoFrame:
xf_process_tsmf_video_frame_event(xfc, (RDP_VIDEO_FRAME_EVENT*) event);
break;
case TsmfChannel_Redraw:
xf_process_tsmf_redraw_event(xfc, (RDP_REDRAW_EVENT*) event);
break;
}
}
#else /* WITH_XV */
void xf_tsmf_init(xfContext* xfc, long xv_port)
{
}
void xf_tsmf_uninit(xfContext* xfc)
{
}
void xf_process_tsmf_event(xfContext* xfc, wMessage* event)
{
}
#endif /* WITH_XV */

View File

@@ -23,8 +23,7 @@
#include "xf_client.h"
#include "xfreerdp.h"
void xf_tsmf_init(xfContext* xfc, long xv_port);
void xf_tsmf_uninit(xfContext* xfc);
void xf_process_tsmf_event(xfContext* xfc, wMessage* event);
int xf_tsmf_init(xfContext* xfc, TsmfClientContext* tsmf);
int xf_tsmf_uninit(xfContext* xfc, TsmfClientContext* tsmf);
#endif /* __XF_TSMF_H */

View File

@@ -158,6 +158,7 @@ struct xf_context
BOOL complex_regions;
VIRTUAL_SCREEN vscreen;
void* xv_context;
TsmfClientContext* tsmf;
xfClipboard* clipboard;
CliprdrClientContext* cliprdr;
@@ -248,8 +249,6 @@ void xf_unlock_x11(xfContext* xfc, BOOL display);
void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale);
void xf_transform_window(xfContext* xfc);
unsigned long xf_gdi_get_color(xfContext* xfc, GDI_COLOR color);
FREERDP_API DWORD xf_exit_code_from_disconnect_reason(DWORD reason);
#endif /* __XFREERDP_H */

View File

@@ -18,46 +18,11 @@
* limitations under the License.
*/
#ifndef _TSMF_H_
#define _TSMF_H_
#ifndef FREERDP_CHANNEL_TSMF_H
#define FREERDP_CHANNEL_TSMF_H
#include <freerdp/types.h>
/* Callback function setup order:
*
* When the channel is loaded, it calls TSMF_REGISTER to register the
* decoder handle with the client.
* The client then stores the handle and calls TSMF_REGISTER_INSTANCE
* to give the channel the current handle to the session necessary
* to call other functions.
* After this initial setup the other functions can be used.
*/
/* Functions called from client -> registered by channel */
#define TSMF_GET_INSTANCE "tsmf_get_instance"
typedef void (*tsmf_get_instance)(void *instance, void *decoder);
#define TSMF_ADD_WINDOW_HANDLE "tsmf_add_window_handle"
typedef void (*tsmf_add_window_handle)(void *instance, void *decoder, void *window);
#define TSMF_DEL_WINDOW_HANDLE "tsmf_del_window_handle"
typedef void (*tsmf_del_window_handle)(void *instance, void *decoder);
/* Functions called from channel -> registered by client */
#define TSMF_REGISTER "tsmf_register"
typedef void (*tsmf_register)(void *instance, void *decoder);
#define TSMF_DESTROY "tsmf_destroy"
typedef void (*tsmf_destroy)(void *instance, void *decoder);
#define TSMF_PLAY "tsmf_play"
typedef void (*tsmf_play)(void *instance, void *decoder);
#define TSMF_PAUSE "tsmf_pause"
typedef void (*tsmf_pause)(void *instance, void *decoder);
#define TSMF_RESIZE_WINDOW "tsmf_resize_window"
typedef void (*tsmf_resize_window)(void *instance, void *decoder, int x, int y, int width,
int height, int nr_rect, RDP_RECT *visible);
#endif
#define TSMF_DVC_CHANNEL_NAME "TSMF"
#endif /* FREERDP_CHANNEL_TSMF_H */

View File

@@ -20,36 +20,45 @@
#ifndef FREERDP_CHANNEL_CLIENT_TSMF_H
#define FREERDP_CHANNEL_CLIENT_TSMF_H
struct _RDP_VIDEO_FRAME_EVENT
{
wMessage event;
BYTE* frame_data;
UINT32 frame_size;
UINT32 frame_pixfmt;
INT16 frame_width;
INT16 frame_height;
INT16 x;
INT16 y;
INT16 width;
INT16 height;
UINT16 num_visible_rects;
RDP_RECT* visible_rects;
};
typedef struct _RDP_VIDEO_FRAME_EVENT RDP_VIDEO_FRAME_EVENT;
#include <freerdp/codec/region.h>
struct _RDP_REDRAW_EVENT
{
wMessage event;
INT16 x;
INT16 y;
INT16 width;
INT16 height;
};
typedef struct _RDP_REDRAW_EVENT RDP_REDRAW_EVENT;
#include <freerdp/channels/tsmf.h>
/* RDP_VIDEO_FRAME_EVENT.frame_pixfmt */
/* http://www.fourcc.org/yuv.php */
#define RDP_PIXFMT_I420 0x30323449
#define RDP_PIXFMT_YV12 0x32315659
struct _TSMF_VIDEO_FRAME_EVENT
{
BYTE* frameData;
UINT32 frameSize;
UINT32 framePixFmt;
INT16 frameWidth;
INT16 frameHeight;
INT16 x;
INT16 y;
INT16 width;
INT16 height;
UINT16 numVisibleRects;
RECTANGLE_16* visibleRects;
};
typedef struct _TSMF_VIDEO_FRAME_EVENT TSMF_VIDEO_FRAME_EVENT;
/**
* Client Interface
*/
typedef struct _tsmf_client_context TsmfClientContext;
typedef int (*pcTsmfFrameEvent)(TsmfClientContext* context, TSMF_VIDEO_FRAME_EVENT* event);
struct _tsmf_client_context
{
void* handle;
void* custom;
pcTsmfFrameEvent FrameEvent;
};
#endif /* FREERDP_CHANNEL_CLIENT_TSMF_H */

View File

@@ -87,6 +87,9 @@ struct rdp_shadow_client
rdpShadowEncoder* encoder;
rdpShadowSubsystem* subsystem;
UINT32 pointerX;
UINT32 pointerY;
HANDLE vcm;
EncomspServerContext* encomsp;
RemdeskServerContext* remdesk;
@@ -145,6 +148,8 @@ struct _RDP_SHADOW_ENTRY_POINTS
REGION16 invalidRegion; \
wMessagePipe* MsgPipe; \
SYNCHRONIZATION_BARRIER barrier; \
UINT32 pointerX; \
UINT32 pointerY; \
\
pfnShadowSynchronizeEvent SynchronizeEvent; \
pfnShadowKeyboardEvent KeyboardEvent; \

View File

@@ -105,7 +105,7 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
if (status != 0)
{
#ifdef _WIN32
WLog_ERR(_T("getaddrinfo error: %s"), gai_strerror(status));
WLog_ERR("getaddrinfo error: %s", gai_strerrorA(status));
#else
WLog_ERR(TAG, "getaddrinfo");
#endif

View File

@@ -1506,9 +1506,25 @@ static void update_send_pointer_system(rdpContext* context, POINTER_SYSTEM_UPDAT
Stream_Release(s);
}
static void update_send_pointer_position(rdpContext* context, POINTER_POSITION_UPDATE* pointerPosition)
{
wStream* s;
rdpRdp* rdp = context->rdp;
s = fastpath_update_pdu_init(rdp->fastpath);
Stream_EnsureRemainingCapacity(s, 16);
Stream_Write_UINT16(s, pointerPosition->xPos); /* xPos (2 bytes) */
Stream_Write_UINT16(s, pointerPosition->yPos); /* yPos (2 bytes) */
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_PTR_POSITION, s, FALSE);
Stream_Release(s);
}
static void update_write_pointer_color(wStream* s, POINTER_COLOR_UPDATE* pointer_color)
{
Stream_EnsureRemainingCapacity(s, 15 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask);
Stream_EnsureRemainingCapacity(s, 32 + (int) pointer_color->lengthAndMask + (int) pointer_color->lengthXorMask);
Stream_Write_UINT16(s, pointer_color->cacheIndex);
Stream_Write_UINT16(s, pointer_color->xPos);
@@ -1544,9 +1560,14 @@ static void update_send_pointer_new(rdpContext* context, POINTER_NEW_UPDATE* poi
rdpRdp* rdp = context->rdp;
s = fastpath_update_pdu_init(rdp->fastpath);
Stream_EnsureRemainingCapacity(s, 16);
Stream_Write_UINT16(s, pointer_new->xorBpp); /* xorBpp (2 bytes) */
update_write_pointer_color(s, &pointer_new->colorPtrAttr);
fastpath_send_update_pdu(rdp->fastpath, FASTPATH_UPDATETYPE_POINTER, s, FALSE);
Stream_Release(s);
}
@@ -1614,14 +1635,14 @@ BOOL update_read_suppress_output(rdpUpdate* update, wStream* s)
static void update_send_set_keyboard_indicators(rdpContext* context, UINT16 led_flags)
{
wStream* s;
rdpRdp* rdp = context->rdp;
wStream* s;
rdpRdp* rdp = context->rdp;
s = rdp_data_pdu_init(rdp);
Stream_Write_UINT16(s, 0); /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.1.1 */
Stream_Write_UINT16(s, led_flags); /* ledFlags (2 bytes) */
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId);
Stream_Release(s);
s = rdp_data_pdu_init(rdp);
Stream_Write_UINT16(s, 0); /* unitId should be 0 according to MS-RDPBCGR 2.2.8.2.1.1 */
Stream_Write_UINT16(s, led_flags); /* ledFlags (2 bytes) */
rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SET_KEYBOARD_INDICATORS, rdp->mcs->userId);
Stream_Release(s);
}
void update_register_server_callbacks(rdpUpdate* update)
@@ -1655,6 +1676,7 @@ void update_register_server_callbacks(rdpUpdate* update)
update->altsec->CreateOffscreenBitmap = update_send_create_offscreen_bitmap_order;
update->altsec->SwitchSurface = update_send_switch_surface_order;
update->pointer->PointerSystem = update_send_pointer_system;
update->pointer->PointerPosition = update_send_pointer_position;
update->pointer->PointerColor = update_send_pointer_color;
update->pointer->PointerNew = update_send_pointer_new;
update->pointer->PointerCached = update_send_pointer_cached;

View File

@@ -528,7 +528,7 @@ static void gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate)
pSrcData = gdi->bitmap_buffer;
}
nSrcStep = nWidth * 4;
nSrcStep = nWidth * gdi->bytesPerPixel;
pDstData = gdi->primary_buffer;
nDstStep = gdi->width * gdi->bytesPerPixel;

View File

@@ -21,16 +21,11 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <freerdp/message.h>
#include <freerdp/utils/event.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/tsmf.h>
#include <freerdp/rail.h>
static wMessage* freerdp_cliprdr_event_new(UINT16 event_type)
@@ -109,33 +104,6 @@ static wMessage* freerdp_cliprdr_event_new(UINT16 event_type)
return event.m;
}
static wMessage* freerdp_tsmf_event_new(UINT16 event_type)
{
union
{
void *v;
wMessage* m;
} event;
event.m = NULL;
switch (event_type)
{
case TsmfChannel_VideoFrame:
event.v = malloc(sizeof(RDP_VIDEO_FRAME_EVENT));
ZeroMemory(event.v, sizeof(RDP_VIDEO_FRAME_EVENT));
event.m->id = MakeMessageId(TsmfChannel, VideoFrame);
break;
case TsmfChannel_Redraw:
event.v = malloc(sizeof(RDP_REDRAW_EVENT));
ZeroMemory(event.v, sizeof(RDP_REDRAW_EVENT));
event.m->id = MakeMessageId(TsmfChannel, Redraw);
break;
}
return event.v;
}
static wMessage* freerdp_rail_event_new(UINT16 event_type)
{
wMessage* event = NULL;
@@ -153,19 +121,10 @@ wMessage* freerdp_event_new(UINT16 event_class, UINT16 event_type,
switch (event_class)
{
case DebugChannel_Class:
event = (wMessage*) malloc(sizeof(wMessage));
ZeroMemory(event, sizeof(wMessage));
break;
case CliprdrChannel_Class:
event = freerdp_cliprdr_event_new(event_type);
break;
case TsmfChannel_Class:
event = freerdp_tsmf_event_new(event_type);
break;
case RailChannel_Class:
event = freerdp_rail_event_new(event_type);
break;
@@ -202,20 +161,6 @@ static void freerdp_cliprdr_event_free(wMessage* event)
}
}
static void freerdp_tsmf_event_free(wMessage* event)
{
switch (GetMessageType(event->id))
{
case TsmfChannel_VideoFrame:
{
RDP_VIDEO_FRAME_EVENT* vevent = (RDP_VIDEO_FRAME_EVENT*)event;
free(vevent->frame_data);
free(vevent->visible_rects);
}
break;
}
}
static void freerdp_rail_event_free(wMessage* event)
{
@@ -234,10 +179,6 @@ void freerdp_event_free(wMessage* event)
freerdp_cliprdr_event_free(event);
break;
case TsmfChannel_Class:
freerdp_tsmf_event_free(event);
break;
case RailChannel_Class:
freerdp_rail_event_free(event);
break;

View File

@@ -231,11 +231,13 @@ void x11_shadow_input_keyboard_event(x11ShadowSubsystem* subsystem, UINT16 flags
XTestGrabControl(subsystem->display, True);
if (flags & KBD_FLAGS_DOWN)
XTestFakeKeyEvent(subsystem->display, keycode, True, 0);
XTestFakeKeyEvent(subsystem->display, keycode, True, CurrentTime);
else if (flags & KBD_FLAGS_RELEASE)
XTestFakeKeyEvent(subsystem->display, keycode, False, 0);
XTestFakeKeyEvent(subsystem->display, keycode, False, CurrentTime);
XTestGrabControl(subsystem->display, False);
XFlush(subsystem->display);
}
#endif
}
@@ -276,13 +278,13 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U
button = (negative) ? 5 : 4;
XTestFakeButtonEvent(subsystem->display, button, True, 0);
XTestFakeButtonEvent(subsystem->display, button, False, 0);
XTestFakeButtonEvent(subsystem->display, button, True, CurrentTime);
XTestFakeButtonEvent(subsystem->display, button, False, CurrentTime);
}
else
{
if (flags & PTR_FLAGS_MOVE)
XTestFakeMotionEvent(subsystem->display, 0, x, y, 0);
XTestFakeMotionEvent(subsystem->display, 0, x, y, CurrentTime);
if (flags & PTR_FLAGS_BUTTON1)
button = 1;
@@ -295,10 +297,12 @@ void x11_shadow_input_mouse_event(x11ShadowSubsystem* subsystem, UINT16 flags, U
down = TRUE;
if (button)
XTestFakeButtonEvent(subsystem->display, button, down, 0);
XTestFakeButtonEvent(subsystem->display, button, down, CurrentTime);
}
XTestGrabControl(subsystem->display, False);
XFlush(subsystem->display);
#endif
}
@@ -335,12 +339,63 @@ void x11_shadow_input_extended_mouse_event(x11ShadowSubsystem* subsystem, UINT16
down = TRUE;
if (button)
XTestFakeButtonEvent(subsystem->display, button, down, 0);
XTestFakeButtonEvent(subsystem->display, button, down, CurrentTime);
XTestGrabControl(subsystem->display, False);
XFlush(subsystem->display);
#endif
}
int x11_shadow_pointer_position_update(x11ShadowSubsystem* subsystem)
{
SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg;
UINT32 msgId = SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID;
wMessagePipe* MsgPipe = subsystem->MsgPipe;
msg = (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*) calloc(1, sizeof(SHADOW_MSG_OUT_POINTER_POSITION_UPDATE));
if (!msg)
return -1;
msg->xPos = subsystem->pointerX;
msg->yPos = subsystem->pointerY;
MessageQueue_Post(MsgPipe->Out, NULL, msgId, (void*) msg, NULL);
return 1;
}
int x11_shadow_pointer_alpha_update(x11ShadowSubsystem* subsystem)
{
SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg;
UINT32 msgId = SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID;
wMessagePipe* MsgPipe = subsystem->MsgPipe;
msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) calloc(1, sizeof(SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE));
if (!msg)
return -1;
msg->xHot = subsystem->cursorHotX;
msg->yHot = subsystem->cursorHotY;
msg->width = subsystem->cursorWidth;
msg->height = subsystem->cursorHeight;
msg->scanline = msg->width * 4;
msg->pixels = (BYTE*) malloc(msg->scanline * msg->height);
if (!msg->pixels)
return -1;
CopyMemory(msg->pixels, subsystem->cursorPixels, msg->scanline * msg->height);
msg->premultiplied = TRUE;
MessageQueue_Post(MsgPipe->Out, NULL, msgId, (void*) msg, NULL);
return 1;
}
int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage)
{
int x, y, n, k;
@@ -358,6 +413,9 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage)
ci = XFixesGetCursorImage(subsystem->display);
if (!ci)
return -1;
x = ci->x;
y = ci->y;
@@ -385,6 +443,8 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage)
}
XFree(ci);
x11_shadow_pointer_alpha_update(subsystem);
#endif
}
else
@@ -404,8 +464,13 @@ int x11_shadow_query_cursor(x11ShadowSubsystem* subsystem, BOOL getImage)
y = root_y;
}
subsystem->cursorX = x;
subsystem->cursorY = y;
if ((x != subsystem->pointerX) || (y != subsystem->pointerY))
{
subsystem->pointerX = x;
subsystem->pointerY = y;
x11_shadow_pointer_position_update(subsystem);
}
return 1;
}
@@ -416,13 +481,16 @@ int x11_shadow_handle_xevent(x11ShadowSubsystem* subsystem, XEvent* xevent)
{
}
#ifdef WITH_XFIXES
if (xevent->type == subsystem->xfixes_cursor_notify_event)
else if (xevent->type == subsystem->xfixes_cursor_notify_event)
{
x11_shadow_query_cursor(subsystem, TRUE);
}
#endif
else
{
}
return 1;
}
@@ -473,8 +541,8 @@ int x11_shadow_blend_cursor(x11ShadowSubsystem* subsystem)
nWidth = subsystem->cursorWidth;
nHeight = subsystem->cursorHeight;
nXDst = subsystem->cursorX - surface->x - subsystem->cursorHotX;
nYDst = subsystem->cursorY - surface->y - subsystem->cursorHotY;
nXDst = subsystem->pointerX - surface->x - subsystem->cursorHotX;
nYDst = subsystem->pointerY - surface->y - subsystem->cursorHotY;
if (nXDst >= surface->width)
return 1;
@@ -633,7 +701,7 @@ int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
(BYTE*) image->data, PIXEL_FORMAT_XRGB32,
image->bytes_per_line, x, y, NULL);
x11_shadow_blend_cursor(subsystem);
//x11_shadow_blend_cursor(subsystem);
count = ArrayList_Count(server->clients);
@@ -767,8 +835,8 @@ void* x11_shadow_subsystem_thread(x11ShadowSubsystem* subsystem)
if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
{
x11_shadow_query_cursor(subsystem, FALSE);
x11_shadow_screen_grab(subsystem);
x11_shadow_query_cursor(subsystem, FALSE);
dwInterval = 1000 / subsystem->captureFrameRate;
frameTime += dwInterval;
@@ -804,7 +872,7 @@ int x11_shadow_subsystem_base_init(x11ShadowSubsystem* subsystem)
subsystem->depth = DefaultDepthOfScreen(subsystem->screen);
subsystem->width = WidthOfScreen(subsystem->screen);
subsystem->height = HeightOfScreen(subsystem->screen);
subsystem->root_window = DefaultRootWindow(subsystem->display);
subsystem->root_window = RootWindow(subsystem->display, subsystem->number);
return 1;
}
@@ -824,7 +892,8 @@ int x11_shadow_xfixes_init(x11ShadowSubsystem* subsystem)
subsystem->xfixes_cursor_notify_event = xfixes_event + XFixesCursorNotify;
XFixesSelectCursorInput(subsystem->display, DefaultRootWindow(subsystem->display), XFixesDisplayCursorNotifyMask);
XFixesSelectCursorInput(subsystem->display, subsystem->root_window,
XFixesDisplayCursorNotifyMask);
return 1;
#else

View File

@@ -80,8 +80,6 @@ struct x11_shadow_subsystem
Window root_window;
XShmSegmentInfo fb_shm_info;
int cursorX;
int cursorY;
int cursorHotX;
int cursorHotY;
int cursorWidth;

View File

@@ -94,10 +94,10 @@ int shadow_capture_compare(BYTE* pData1, int nStep1, int nWidth, int nHeight, BY
BOOL grid[1024][1024];
allEqual = TRUE;
ZeroMemory(rect, sizeof(RECTANGLE_16));
FillMemory(rows, sizeof(rows), 0xFF);
FillMemory(cols, sizeof(cols), 0xFF);
FillMemory(grid, sizeof(grid), 0xFF);
ZeroMemory(rect, sizeof(RECTANGLE_16));
nrow = (nHeight + 15) / 16;
ncol = (nWidth + 15) / 16;

View File

@@ -56,6 +56,8 @@ void shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client)
settings->DrawAllowColorSubsampling = TRUE;
settings->DrawAllowDynamicColorFidelity = TRUE;
settings->CompressionLevel = PACKET_COMPR_TYPE_RDP6;
settings->RdpSecurity = TRUE;
settings->TlsSecurity = TRUE;
settings->NlaSecurity = FALSE;
@@ -162,6 +164,9 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
if (settings->ColorDepth == 24)
settings->ColorDepth = 16; /* disable 24bpp */
if (settings->MultifragMaxRequestSize < 0x3F0000)
settings->NSCodec = FALSE; /* NSCodec compressor does not support fragmentation yet */
WLog_ERR(TAG, "Client from %s is activated (%dx%d@%d)",
peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);
@@ -266,7 +271,7 @@ BOOL shadow_client_activate(freerdp_peer* peer)
rdpSettings* settings = peer->settings;
rdpShadowClient* client = (rdpShadowClient*) peer->context;
if (strcmp(settings->ClientDir, "librdp") == 0)
if (settings->ClientDir && (strcmp(settings->ClientDir, "librdp") == 0))
{
/* Hack for Mac/iOS/Android Microsoft RDP clients */
@@ -595,10 +600,47 @@ int shadow_client_send_bitmap_update(rdpShadowClient* client, rdpShadowSurface*
if (updateSizeEstimate > maxUpdateSize)
{
fprintf(stderr, "update size estimate larger than maximum update size\n");
}
UINT32 i, j;
UINT32 updateSize;
UINT32 newUpdateSize;
BITMAP_DATA* fragBitmapData;
IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
fragBitmapData = (BITMAP_DATA*) malloc(sizeof(BITMAP_DATA) * k);
bitmapUpdate.rectangles = fragBitmapData;
i = j = 0;
updateSize = 1024;
while (i < k)
{
newUpdateSize = updateSize + (bitmapData[i].bitmapLength + 16);
if ((newUpdateSize < maxUpdateSize) && ((i + 1) < k))
{
CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA));
updateSize = newUpdateSize;
}
else
{
if ((i + 1) >= k)
{
CopyMemory(&fragBitmapData[j++], &bitmapData[i++], sizeof(BITMAP_DATA));
updateSize = newUpdateSize;
}
bitmapUpdate.count = bitmapUpdate.number = j;
IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
updateSize = 1024;
j = 0;
}
}
free(fragBitmapData);
}
else
{
IFCALL(update->BitmapUpdate, context, &bitmapUpdate);
}
free(bitmapData);
@@ -696,10 +738,151 @@ int shadow_client_surface_update(rdpShadowClient* client, REGION16* region)
return 1;
}
int shadow_client_convert_alpha_pointer_data(BYTE* pixels, BOOL premultiplied,
UINT32 width, UINT32 height, POINTER_COLOR_UPDATE* pointerColor)
{
UINT32 x, y;
BYTE* pSrc8;
BYTE* pDst8;
int xorStep;
int andStep;
UINT32 andBit;
BYTE* andBits;
UINT32 andPixel;
BYTE A, R, G, B;
xorStep = (width * 3);
xorStep += (xorStep % 2);
andStep = ((width + 7) / 8);
andStep += (andStep % 2);
pointerColor->lengthXorMask = height * xorStep;
pointerColor->xorMaskData = (BYTE*) calloc(1, pointerColor->lengthXorMask);
if (!pointerColor->xorMaskData)
return -1;
pointerColor->lengthAndMask = height * andStep;
pointerColor->andMaskData = (BYTE*) calloc(1, pointerColor->lengthAndMask);
if (!pointerColor->andMaskData)
return -1;
for (y = 0; y < height; y++)
{
pSrc8 = &pixels[(width * 4) * (height - 1 - y)];
pDst8 = &(pointerColor->xorMaskData[y * xorStep]);
andBit = 0x80;
andBits = &(pointerColor->andMaskData[andStep * y]);
for (x = 0; x < width; x++)
{
B = *pSrc8++;
G = *pSrc8++;
R = *pSrc8++;
A = *pSrc8++;
andPixel = 0;
if (A < 64)
A = 0; /* pixel cannot be partially transparent */
if (!A)
{
/* transparent pixel: XOR = black, AND = 1 */
andPixel = 1;
B = G = R = 0;
}
else
{
if (premultiplied)
{
B = (B * 0xFF ) / A;
G = (G * 0xFF ) / A;
R = (R * 0xFF ) / A;
}
}
*pDst8++ = B;
*pDst8++ = G;
*pDst8++ = R;
if (andPixel) *andBits |= andBit;
if (!(andBit >>= 1)) { andBits++; andBit = 0x80; }
}
}
return 1;
}
int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
{
rdpContext* context = (rdpContext*) client;
rdpUpdate* update = context->update;
/* FIXME: the pointer updates appear to be broken when used with bulk compression and mstsc */
if (message->id == SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID)
{
POINTER_POSITION_UPDATE pointerPosition;
SHADOW_MSG_OUT_POINTER_POSITION_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_POSITION_UPDATE*) message->wParam;
pointerPosition.xPos = msg->xPos;
pointerPosition.yPos = msg->yPos;
if ((msg->xPos != client->pointerX) || (msg->yPos != client->pointerY))
{
IFCALL(update->pointer->PointerPosition, context, &pointerPosition);
client->pointerX = msg->xPos;
client->pointerY = msg->yPos;
}
free(msg);
}
else if (message->id == SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID)
{
POINTER_NEW_UPDATE pointerNew;
POINTER_COLOR_UPDATE* pointerColor;
POINTER_CACHED_UPDATE pointerCached;
SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* msg = (SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE*) message->wParam;
ZeroMemory(&pointerNew, sizeof(POINTER_NEW_UPDATE));
pointerNew.xorBpp = 24;
pointerColor = &(pointerNew.colorPtrAttr);
pointerColor->cacheIndex = 0;
pointerColor->xPos = msg->xHot;
pointerColor->yPos = msg->yHot;
pointerColor->width = msg->width;
pointerColor->height = msg->height;
pointerCached.cacheIndex = pointerColor->cacheIndex;
shadow_client_convert_alpha_pointer_data(msg->pixels, msg->premultiplied,
msg->width, msg->height, pointerColor);
IFCALL(update->pointer->PointerNew, context, &pointerNew);
IFCALL(update->pointer->PointerCached, context, &pointerCached);
free(pointerColor->xorMaskData);
free(pointerColor->andMaskData);
free(msg->pixels);
free(msg);
}
return 1;
}
void* shadow_client_thread(rdpShadowClient* client)
{
DWORD status;
DWORD nCount;
wMessage message;
HANDLE events[32];
HANDLE StopEvent;
HANDLE ClientEvent;
@@ -712,6 +895,7 @@ void* shadow_client_thread(rdpShadowClient* client)
rdpShadowScreen* screen;
rdpShadowEncoder* encoder;
rdpShadowSubsystem* subsystem;
wMessagePipe* MsgPipe = client->subsystem->MsgPipe;
server = client->server;
screen = server->screen;
@@ -746,6 +930,7 @@ void* shadow_client_thread(rdpShadowClient* client)
events[nCount++] = UpdateEvent;
events[nCount++] = ClientEvent;
events[nCount++] = ChannelEvent;
events[nCount++] = MessageQueue_Event(MsgPipe->Out);
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
@@ -793,12 +978,23 @@ void* shadow_client_thread(rdpShadowClient* client)
if (WaitForSingleObject(ChannelEvent, 0) == WAIT_OBJECT_0)
{
if (WTSVirtualChannelManagerCheckFileDescriptor(client->vcm) != TRUE)
if (!WTSVirtualChannelManagerCheckFileDescriptor(client->vcm))
{
WLog_ERR(TAG, "WTSVirtualChannelManagerCheckFileDescriptor failure");
break;
}
}
if (WaitForSingleObject(MessageQueue_Event(MsgPipe->Out), 0) == WAIT_OBJECT_0)
{
if (MessageQueue_Peek(MsgPipe->Out, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
shadow_client_subsystem_process_message(client, &message);
}
}
}
peer->Disconnect(peer);

View File

@@ -69,6 +69,21 @@ void shadow_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
rdpShadowClient* client = (rdpShadowClient*) input->context;
rdpShadowSubsystem* subsystem = client->server->subsystem;
if (!(flags & PTR_FLAGS_WHEEL))
{
client->pointerX = x;
client->pointerY = y;
if ((client->pointerX == subsystem->pointerX) &&
(client->pointerY == subsystem->pointerY))
{
flags &= ~PTR_FLAGS_MOVE;
if (!(flags & (PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 | PTR_FLAGS_BUTTON3)))
return;
}
}
if (!client->mayInteract)
return;
@@ -83,6 +98,9 @@ void shadow_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x,
rdpShadowClient* client = (rdpShadowClient*) input->context;
rdpShadowSubsystem* subsystem = client->server->subsystem;
client->pointerX = x;
client->pointerY = y;
if (!client->mayInteract)
return;

View File

@@ -41,6 +41,28 @@ struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT
};
typedef struct _SHADOW_MSG_IN_SUPPRESS_OUTPUT SHADOW_MSG_IN_SUPPRESS_OUTPUT;
#define SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID 2001
#define SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE_ID 2002
struct _SHADOW_MSG_OUT_POINTER_POSITION_UPDATE
{
UINT32 xPos;
UINT32 yPos;
};
typedef struct _SHADOW_MSG_OUT_POINTER_POSITION_UPDATE SHADOW_MSG_OUT_POINTER_POSITION_UPDATE;
struct _SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE
{
UINT32 xHot;
UINT32 yHot;
UINT32 width;
UINT32 height;
BYTE* pixels;
int scanline;
BOOL premultiplied;
};
typedef struct _SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE;
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -23,9 +23,11 @@
#include "config.h"
#endif
#include <winpr/environment.h>
#include <winpr/crt.h>
#include <winpr/error.h>
#include <winpr/environment.h>
#ifndef _WIN32
#define stricmp strcasecmp
@@ -326,7 +328,7 @@ LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge)
if (mergeStringLength == mergeArraySize)
{
mergeArraySize += 128;
mergeStrings = (LPCSTR*) realloc(mergeStrings, mergeArraySize * sizeof(char*));
mergeStrings = (const char**) realloc((void*) mergeStrings, mergeArraySize * sizeof(char*));
if (!mergeStrings)
return NULL;
@@ -441,7 +443,7 @@ LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge)
lpszEnvironmentBlock[offset] = '\0';
free(mergeStrings);
free((void*) mergeStrings);
return lpszEnvironmentBlock;
}

View File

@@ -181,9 +181,6 @@ VOID CloseThreadpool(PTP_POOL ptpp)
if (pCloseThreadpool)
pCloseThreadpool(ptpp);
#else
int index;
HANDLE thread;
SetEvent(ptpp->TerminateEvent);
ArrayList_Free(ptpp->Threads);

View File

@@ -1382,6 +1382,8 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext
{
int i, j;
int* map;
DWORD dwEventState;
BOOL stateChanged = FALSE;
PCSC_DWORD cMappedReaders;
PCSC_SCARD_READERSTATE* states;
LONG status = SCARD_S_SUCCESS;
@@ -1469,11 +1471,7 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext
rgReaderStates[i].dwCurrentState = states[j].dwCurrentState;
rgReaderStates[i].cbAtr = states[j].cbAtr;
CopyMemory(&(rgReaderStates[i].rgbAtr), &(states[j].rgbAtr), PCSC_MAX_ATR_SIZE);
/**
* Why we should interpret and modify the results of pcsc-lite ScardGetStatusChange ?
* Should not we just act as a pass-through between the client and the remote smartcard subsystem ?
*/
#if 0
/* pcsc-lite puts an event count in the higher bits of dwEventState */
states[j].dwEventState &= 0xFFFF;
dwEventState = states[j].dwEventState & ~SCARD_STATE_CHANGED;
@@ -1497,19 +1495,14 @@ WINSCARDAPI LONG WINAPI PCSC_SCardGetStatusChange_Internal(SCARDCONTEXT hContext
if (rgReaderStates[i].dwCurrentState & SCARD_STATE_IGNORE)
rgReaderStates[i].dwEventState = SCARD_STATE_IGNORE;
#endif
rgReaderStates[i].dwEventState = states[j].dwEventState;
}
/**
* Why we should interpret and modify the results of pcsc-lite ScardGetStatusChange ?
* Should not we just act as a pass-through between the client and the remote smartcard subsystem ?
*/
#if 0
if ((status == SCARD_S_SUCCESS) && !stateChanged)
status = SCARD_E_TIMEOUT;
else if ((status == SCARD_E_TIMEOUT) && stateChanged)
return SCARD_S_SUCCESS;
#endif
free(states);
free(map);

View File

@@ -267,7 +267,7 @@ exit:
if (thread->detached || !thread->started)
cleanup_handle(thread);
pthread_exit(thread->dwExitCode);
pthread_exit((void*) (size_t) thread->dwExitCode);
return rc;
}
@@ -426,12 +426,13 @@ VOID ExitThread(DWORD dwExitCode)
{
pthread_t tid = pthread_self();
if (NULL == thread_list)
if (!thread_list)
{
WLog_ERR(TAG, "function called without existing thread list!");
#if defined(WITH_DEBUG_THREADS)
DumpThreadHandles();
#endif
pthread_exit(0);
}
else if (!ListDictionary_Contains(thread_list, &tid))
{
@@ -439,12 +440,15 @@ VOID ExitThread(DWORD dwExitCode)
#if defined(WITH_DEBUG_THREADS)
DumpThreadHandles();
#endif
pthread_exit(0);
}
else
{
WINPR_THREAD *thread;
WINPR_THREAD* thread;
ListDictionary_Lock(thread_list);
thread = ListDictionary_GetItemValue(thread_list, &tid);
assert(thread);
thread->exited = TRUE;
thread->dwExitCode = dwExitCode;
@@ -457,7 +461,7 @@ VOID ExitThread(DWORD dwExitCode)
if (thread->detached || !thread->started)
cleanup_handle(thread);
pthread_exit(thread->dwExitCode);
pthread_exit((void*) (size_t) thread->dwExitCode);
}
}

View File

@@ -689,7 +689,6 @@ BOOL WINAPI Win32_WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLAS
VOID WINAPI Win32_WTSFreeMemory(PVOID pMemory)
{
LocalFree(pMemory);
return TRUE;
}
BOOL WINAPI Win32_WTSFreeMemoryExW(WTS_TYPE_CLASS WTSTypeClass, PVOID pMemory, ULONG NumberOfEntries)