Initial commit - from Precise source
[freerdp-ubuntu-pcb-backport.git] / channels / drdynvc / tsmf / tsmf_main.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol client.
3  * Video Redirection Virtual Channel
4  *
5  * Copyright 2010-2011 Vic Lee
6  *
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
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
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.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <freerdp/utils/memory.h>
24 #include <freerdp/utils/stream.h>
25
26 #include "drdynvc_types.h"
27 #include "tsmf_constants.h"
28 #include "tsmf_ifman.h"
29 #include "tsmf_media.h"
30
31 #include "tsmf_main.h"
32
33 typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK;
34
35 typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK;
36
37 typedef struct _TSMF_PLUGIN TSMF_PLUGIN;
38
39 struct _TSMF_LISTENER_CALLBACK
40 {
41         IWTSListenerCallback iface;
42
43         IWTSPlugin* plugin;
44         IWTSVirtualChannelManager* channel_mgr;
45 };
46
47 struct _TSMF_CHANNEL_CALLBACK
48 {
49         IWTSVirtualChannelCallback iface;
50
51         IWTSPlugin* plugin;
52         IWTSVirtualChannelManager* channel_mgr;
53         IWTSVirtualChannel* channel;
54
55         uint8 presentation_id[16];
56         uint32 stream_id;
57 };
58
59 struct _TSMF_PLUGIN
60 {
61         IWTSPlugin iface;
62
63         TSMF_LISTENER_CALLBACK* listener_callback;
64
65         const char* decoder_name;
66         const char* audio_name;
67         const char* audio_device;
68 };
69
70 void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
71         uint32 message_id, uint64 duration, uint32 data_size)
72 {
73         STREAM* s;
74         int error;
75         TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
76
77         s = stream_new(32);
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 */
84         
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);
87         if (error)
88         {
89                 DEBUG_WARN("response error %d", error);
90         }
91         stream_free(s);
92 }
93
94 boolean tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback,
95         RDP_EVENT* event)
96 {
97         int error;
98         TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
99
100         error = callback->channel_mgr->PushEvent(callback->channel_mgr, event);
101         if (error)
102         {
103                 DEBUG_WARN("response error %d", error);
104                 return false;
105         }
106         return true;
107 }
108
109 static int tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
110         uint32 cbSize,
111         uint8* pBuffer)
112 {
113         int length;
114         STREAM* input;
115         STREAM* output;
116         int error = -1;
117         TSMF_IFMAN ifman;
118         uint32 MessageId;
119         uint32 FunctionId;
120         uint32 InterfaceId;
121         TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
122
123         /* 2.2.1 Shared Message Header (SHARED_MSG_HEADER) */
124         if (cbSize < 12)
125         {
126                 DEBUG_WARN("invalid size. cbSize=%d", cbSize);
127                 return 1;
128         }
129         input = stream_new(0);
130         stream_attach(input, (uint8*) pBuffer, cbSize);
131         output = stream_new(256);
132         stream_seek(output, 8);
133
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);
139
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;
148         ifman.input = input;
149         ifman.input_size = cbSize - 12;
150         ifman.output = output;
151         ifman.output_pending = false;
152         ifman.output_interface_id = InterfaceId;
153
154         switch (InterfaceId)
155         {
156                 case TSMF_INTERFACE_CAPABILITIES | STREAM_ID_NONE:
157
158                         switch (FunctionId)
159                         {
160                                 case RIM_EXCHANGE_CAPABILITY_REQUEST:
161                                         error = tsmf_ifman_rim_exchange_capability_request(&ifman);
162                                         break;
163
164                                 default:
165                                         break;
166                         }
167                         break;
168
169                 case TSMF_INTERFACE_DEFAULT | STREAM_ID_PROXY:
170
171                         switch (FunctionId)
172                         {
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;
179                                         error = 0;
180                                         break;
181
182                                 case EXCHANGE_CAPABILITIES_REQ:
183                                         error = tsmf_ifman_exchange_capability_request(&ifman);
184                                         break;
185
186                                 case CHECK_FORMAT_SUPPORT_REQ:
187                                         error = tsmf_ifman_check_format_support_request(&ifman);
188                                         break;
189
190                                 case ON_NEW_PRESENTATION:
191                                         error = tsmf_ifman_on_new_presentation(&ifman);
192                                         break;
193
194                                 case ADD_STREAM:
195                                         error = tsmf_ifman_add_stream(&ifman);
196                                         break;
197
198                                 case SET_TOPOLOGY_REQ:
199                                         error = tsmf_ifman_set_topology_request(&ifman);
200                                         break;
201
202                                 case REMOVE_STREAM:
203                                         error = tsmf_ifman_remove_stream(&ifman);
204                                         break;
205
206                                 case SHUTDOWN_PRESENTATION_REQ:
207                                         error = tsmf_ifman_shutdown_presentation(&ifman);
208                                         break;
209
210                                 case ON_STREAM_VOLUME:
211                                         error = tsmf_ifman_on_stream_volume(&ifman);
212                                         break;
213
214                                 case ON_CHANNEL_VOLUME:
215                                         error = tsmf_ifman_on_channel_volume(&ifman);
216                                         break;
217
218                                 case SET_VIDEO_WINDOW:
219                                         error = tsmf_ifman_set_video_window(&ifman);
220                                         break;
221
222                                 case UPDATE_GEOMETRY_INFO:
223                                         error = tsmf_ifman_update_geometry_info(&ifman);
224                                         break;
225
226                                 case SET_ALLOCATOR:
227                                         error = tsmf_ifman_set_allocator(&ifman);
228                                         break;
229
230                                 case NOTIFY_PREROLL:
231                                         error = tsmf_ifman_notify_preroll(&ifman);
232                                         break;
233
234                                 case ON_SAMPLE:
235                                         error = tsmf_ifman_on_sample(&ifman);
236                                         break;
237
238                                 case ON_FLUSH:
239                                         error = tsmf_ifman_on_flush(&ifman);
240                                         break;
241
242                                 case ON_END_OF_STREAM:
243                                         error = tsmf_ifman_on_end_of_stream(&ifman);
244                                         break;
245
246                                 case ON_PLAYBACK_STARTED:
247                                         error = tsmf_ifman_on_playback_started(&ifman);
248                                         break;
249
250                                 case ON_PLAYBACK_PAUSED:
251                                         error = tsmf_ifman_on_playback_paused(&ifman);
252                                         break;
253
254                                 case ON_PLAYBACK_RESTARTED:
255                                         error = tsmf_ifman_on_playback_restarted(&ifman);
256                                         break;
257
258                                 case ON_PLAYBACK_STOPPED:
259                                         error = tsmf_ifman_on_playback_stopped(&ifman);
260                                         break;
261
262                                 case ON_PLAYBACK_RATE_CHANGED:
263                                         error = tsmf_ifman_on_playback_rate_changed(&ifman);
264                                         break;
265
266                                 default:
267                                         break;
268                         }
269                         break;
270
271                 default:
272                         break;
273         }
274
275         stream_detach(input);
276         stream_free(input);
277         input = NULL;
278         ifman.input = NULL;
279
280         if (error == -1)
281         {
282                 switch (FunctionId)
283                 {
284                         case RIMCALL_RELEASE:
285                                 /* [MS-RDPEXPS] 2.2.2.2 Interface Release (IFACE_RELEASE)
286                                    This message does not require a reply. */
287                                 error = 0;
288                                 ifman.output_pending = 1;
289                                 break;
290
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. */
294                                 error = 0;
295                                 break;
296                 }
297
298                 if (error == -1)
299                 {
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 */
303                 }
304                 error = 0;
305         }
306
307         if (error == 0 && !ifman.output_pending)
308         {
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);
314
315                 DEBUG_DVC("response size %d", length);
316                 error = callback->channel->Write(callback->channel, length, stream_get_head(output), NULL);
317                 if (error)
318                 {
319                         DEBUG_WARN("response error %d", error);
320                 }
321         }
322
323         stream_free(output);
324
325         return error;
326 }
327
328 static int tsmf_on_close(IWTSVirtualChannelCallback* pChannelCallback)
329 {
330         TSMF_STREAM* stream;
331         TSMF_PRESENTATION* presentation;
332         TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) pChannelCallback;
333
334         DEBUG_DVC("");
335
336         if (callback->stream_id)
337         {
338                 presentation = tsmf_presentation_find_by_id(callback->presentation_id);
339                 if (presentation)
340                 {
341                         stream = tsmf_stream_find_by_id(presentation, callback->stream_id);
342                         if (stream)
343                                 tsmf_stream_free(stream);
344                 }
345         }
346         xfree(pChannelCallback);
347
348         return 0;
349 }
350
351 static int tsmf_on_new_channel_connection(IWTSListenerCallback* pListenerCallback,
352         IWTSVirtualChannel* pChannel,
353         uint8* Data,
354         int* pbAccept,
355         IWTSVirtualChannelCallback** ppCallback)
356 {
357         TSMF_CHANNEL_CALLBACK* callback;
358         TSMF_LISTENER_CALLBACK* listener_callback = (TSMF_LISTENER_CALLBACK*) pListenerCallback;
359
360         DEBUG_DVC("");
361
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;
369
370         return 0;
371 }
372
373 static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
374 {
375         TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
376
377         DEBUG_DVC("");
378
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);
385 }
386
387 static int tsmf_plugin_terminated(IWTSPlugin* pPlugin)
388 {
389         TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
390
391         DEBUG_DVC("");
392
393         if (tsmf->listener_callback)
394                 xfree(tsmf->listener_callback);
395         xfree(tsmf);
396
397         return 0;
398 }
399
400 static void tsmf_process_plugin_data(IWTSPlugin* pPlugin, RDP_PLUGIN_DATA* data)
401 {
402         TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
403
404         while (data && data->size > 0)
405         {
406                 if (data->data[0] && ( strcmp((char*)data->data[0], "tsmf") == 0 || strstr((char*)data->data[0], "/tsmf.") != NULL) )
407                 {
408                         if (data->data[1] && strcmp((char*)data->data[1], "decoder") == 0)
409                         {
410                                 tsmf->decoder_name = data->data[2];
411                         }
412                         else if (data->data[1] && strcmp((char*)data->data[1], "audio") == 0)
413                         {
414                                 tsmf->audio_name = data->data[2];
415                                 tsmf->audio_device = data->data[3];
416                         }
417                 }
418                 
419                 data = (RDP_PLUGIN_DATA*)(((void*)data) + data->size);
420         }
421 }
422
423 int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
424 {
425         TSMF_PLUGIN * tsmf;
426         int error = 0;
427
428         tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
429         if (tsmf == NULL)
430         {
431                 tsmf = xnew(TSMF_PLUGIN);
432
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);
438
439                 tsmf_media_init();
440         }
441         if (error == 0)
442         {
443                 tsmf_process_plugin_data((IWTSPlugin*) tsmf,
444                         pEntryPoints->GetPluginData(pEntryPoints));
445         }
446         return error;
447 }
448