2 * FreeRDP: A Remote Desktop Protocol client.
3 * Video Redirection Virtual Channel
5 * Copyright 2010-2011 Vic Lee
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
23 #include <freerdp/utils/memory.h>
24 #include <freerdp/utils/stream.h>
26 #include "drdynvc_types.h"
27 #include "tsmf_constants.h"
28 #include "tsmf_ifman.h"
29 #include "tsmf_media.h"
31 #include "tsmf_main.h"
33 typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK;
35 typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK;
37 typedef struct _TSMF_PLUGIN TSMF_PLUGIN;
39 struct _TSMF_LISTENER_CALLBACK
41 IWTSListenerCallback iface;
44 IWTSVirtualChannelManager* channel_mgr;
47 struct _TSMF_CHANNEL_CALLBACK
49 IWTSVirtualChannelCallback iface;
52 IWTSVirtualChannelManager* channel_mgr;
53 IWTSVirtualChannel* channel;
55 uint8 presentation_id[16];
63 TSMF_LISTENER_CALLBACK* listener_callback;
65 const char* decoder_name;
66 const char* audio_name;
67 const char* audio_device;
70 void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
71 uint32 message_id, uint64 duration, uint32 data_size)
75 TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
78 stream_write_uint32(s, TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY);
79 stream_write_uint32(s, message_id);
80 stream_write_uint32(s, PLAYBACK_ACK); /* FunctionId */
81 stream_write_uint32(s, callback->stream_id); /* StreamId */
82 stream_write_uint64(s, duration); /* DataDuration */
83 stream_write_uint64(s, data_size); /* cbData */
85 DEBUG_DVC("response size %d", stream_get_length(s));
86 error = callback->channel->Write(callback->channel, stream_get_length(s), stream_get_head(s), NULL);
89 DEBUG_WARN("response error %d", error);
94 boolean tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback,
98 TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
100 error = callback->channel_mgr->PushEvent(callback->channel_mgr, event);
103 DEBUG_WARN("response error %d", error);
109 static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
121 TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
123 /* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */
126 DEBUG_WARN("invalid size. cbSize=%d", cbSize);
129 input = stream_new(0);
130 stream_attach(input, (uint8*) pBuffer, cbSize);
131 output = stream_new(256);
132 stream_seek(output, 8);
134 stream_read_uint32(input, InterfaceId);
135 stream_read_uint32(input, MessageId);
136 stream_read_uint32(input, FunctionId);
137 DEBUG_DVC("cbSize=%d InterfaceId=0x%X MessageId=0x%X FunctionId=0x%X",
138 cbSize, InterfaceId, MessageId, FunctionId);
140 memset(&ifman, 0, sizeof(TSMF_IFMAN));
141 ifman.channel_callback = pChannelCallback;
142 ifman.decoder_name = ((TSMF_PLUGIN*) callback->plugin)->decoder_name;
143 ifman.audio_name = ((TSMF_PLUGIN*) callback->plugin)->audio_name;
144 ifman.audio_device = ((TSMF_PLUGIN*) callback->plugin)->audio_device;
145 memcpy(ifman.presentation_id, callback->presentation_id, 16);
146 ifman.stream_id = callback->stream_id;
147 ifman.message_id = MessageId;
149 ifman.input_size = cbSize - 12;
150 ifman.output = output;
151 ifman.output_pending = false;
152 ifman.output_interface_id = InterfaceId;
156 case TSMF_INTERFACE_CAPABILITIES | STREAM_ID_NONE:
160 case RIM_EXCHANGE_CAPABILITY_REQUEST:
161 error = tsmf_ifman_rim_exchange_capability_request(&ifman);
169 case TSMF_INTERFACE_DEFAULT | STREAM_ID_PROXY:
173 case SET_CHANNEL_PARAMS:
174 memcpy(callback->presentation_id, stream_get_tail(input), 16);
175 stream_seek(input, 16);
176 stream_read_uint32(input, callback->stream_id);
177 DEBUG_DVC("SET_CHANNEL_PARAMS StreamId=%d", callback->stream_id);
178 ifman.output_pending = true;
182 case EXCHANGE_CAPABILITIES_REQ:
183 error = tsmf_ifman_exchange_capability_request(&ifman);
186 case CHECK_FORMAT_SUPPORT_REQ:
187 error = tsmf_ifman_check_format_support_request(&ifman);
190 case ON_NEW_PRESENTATION:
191 error = tsmf_ifman_on_new_presentation(&ifman);
195 error = tsmf_ifman_add_stream(&ifman);
198 case SET_TOPOLOGY_REQ:
199 error = tsmf_ifman_set_topology_request(&ifman);
203 error = tsmf_ifman_remove_stream(&ifman);
206 case SHUTDOWN_PRESENTATION_REQ:
207 error = tsmf_ifman_shutdown_presentation(&ifman);
210 case ON_STREAM_VOLUME:
211 error = tsmf_ifman_on_stream_volume(&ifman);
214 case ON_CHANNEL_VOLUME:
215 error = tsmf_ifman_on_channel_volume(&ifman);
218 case SET_VIDEO_WINDOW:
219 error = tsmf_ifman_set_video_window(&ifman);
222 case UPDATE_GEOMETRY_INFO:
223 error = tsmf_ifman_update_geometry_info(&ifman);
227 error = tsmf_ifman_set_allocator(&ifman);
231 error = tsmf_ifman_notify_preroll(&ifman);
235 error = tsmf_ifman_on_sample(&ifman);
239 error = tsmf_ifman_on_flush(&ifman);
242 case ON_END_OF_STREAM:
243 error = tsmf_ifman_on_end_of_stream(&ifman);
246 case ON_PLAYBACK_STARTED:
247 error = tsmf_ifman_on_playback_started(&ifman);
250 case ON_PLAYBACK_PAUSED:
251 error = tsmf_ifman_on_playback_paused(&ifman);
254 case ON_PLAYBACK_RESTARTED:
255 error = tsmf_ifman_on_playback_restarted(&ifman);
258 case ON_PLAYBACK_STOPPED:
259 error = tsmf_ifman_on_playback_stopped(&ifman);
262 case ON_PLAYBACK_RATE_CHANGED:
263 error = tsmf_ifman_on_playback_rate_changed(&ifman);
275 stream_detach(input);
284 case RIMCALL_RELEASE:
285 /* [MS-RDPEXPS] 2.2.2.2 Interface Release (IFACE_RELEASE)
286 This message does not require a reply. */
288 ifman.output_pending = 1;
291 case RIMCALL_QUERYINTERFACE:
292 /* [MS-RDPEXPS] 2.2.2.1.2 Query Interface Response (QI_RSP)
293 This message is not supported in this channel. */
300 DEBUG_WARN("InterfaceId 0x%X FunctionId 0x%X not processed.",
301 InterfaceId, FunctionId);
302 /* When a request is not implemented we return empty response indicating error */
307 if (error == 0 && !ifman.output_pending)
309 /* Response packet does not have FunctionId */
310 length = stream_get_length(output);
311 stream_set_pos(output, 0);
312 stream_write_uint32(output, ifman.output_interface_id);
313 stream_write_uint32(output, MessageId);
315 DEBUG_DVC("response size %d", length);
316 error = callback->channel->Write(callback->channel, length, stream_get_head(output), NULL);
319 DEBUG_WARN("response error %d", error);
328 static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback)
331 TSMF_PRESENTATION* presentation;
332 TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
336 if (callback->stream_id)
338 presentation = tsmf_presentation_find_by_id(callback->presentation_id);
341 stream = tsmf_stream_find_by_id(presentation, callback->stream_id);
343 tsmf_stream_free(stream);
346 xfree(pChannelCallback);
351 static int tsmf_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
352 IWTSVirtualChannel* pChannel,
355 IWTSVirtualChannelCallback** ppCallback)
357 TSMF_CHANNEL_CALLBACK* callback;
358 TSMF_LISTENER_CALLBACK* listener_callback = (TSMF_LISTENER_CALLBACK*) pListenerCallback;
362 callback = xnew(TSMF_CHANNEL_CALLBACK);
363 callback->iface.OnDataReceived = tsmf_on_data_received;
364 callback->iface.OnClose = tsmf_on_close;
365 callback->plugin = listener_callback->plugin;
366 callback->channel_mgr = listener_callback->channel_mgr;
367 callback->channel = pChannel;
368 *ppCallback = (IWTSVirtualChannelCallback*) callback;
373 static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
375 TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
379 tsmf->listener_callback = xnew(TSMF_LISTENER_CALLBACK);
380 tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection;
381 tsmf->listener_callback->plugin = pPlugin;
382 tsmf->listener_callback->channel_mgr = pChannelMgr;
383 return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0,
384 (IWTSListenerCallback*) tsmf->listener_callback, NULL);
387 static int tsmf_plugin_terminated(IWTSPlugin* pPlugin)
389 TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
393 if (tsmf->listener_callback)
394 xfree(tsmf->listener_callback);
400 static void tsmf_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
402 TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
404 while (data && data->size > 0)
406 if (data->data[0] && ( strcmp((char*)data->data[0], "tsmf") == 0 || strstr((char*)data->data[0], "/tsmf.") != NULL) )
408 if (data->data[1] && strcmp((char*)data->data[1], "decoder") == 0)
410 tsmf->decoder_name = data->data[2];
412 else if (data->data[1] && strcmp((char*)data->data[1], "audio") == 0)
414 tsmf->audio_name = data->data[2];
415 tsmf->audio_device = data->data[3];
419 data = (RDP_PLUGIN_DATA*)(((void*)data) + data->size);
423 int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
428 tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
431 tsmf = xnew(TSMF_PLUGIN);
433 tsmf->iface.Initialize = tsmf_plugin_initialize;
434 tsmf->iface.Connected = NULL;
435 tsmf->iface.Disconnected = NULL;
436 tsmf->iface.Terminated = tsmf_plugin_terminated;
437 error = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
443 tsmf_process_plugin_data((IWTSPlugin*) tsmf,
444 pEntryPoints->GetPluginData(pEntryPoints));