update source code for tizen 2.1
[platform/core/multimedia/libmm-wfd.git] / src / mm_wfd_priv.c
1 /*
2  * libmm-wfd
3  *
4  * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: JongHyuk Choi <jhchoi.choi@samsung.com>, ByungWook Jang <bw.jang@samsung.com>,
7  * Manoj Kumar K <manojkumar.k@samsung.com>, Hyunil Park <hyunil46.park@samsung.com>
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  * http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */
22
23 #include <gst/gst.h>
24
25 #include "mm_wfd_priv.h"
26
27 static const gchar * __get_state_name ( int state );
28 static int __mmwfd_check_state(mm_wfd_t* wfd, enum PlayerCommandState command);
29 static gboolean __mmwfd_set_state(mm_wfd_t* wfd, int state);
30 static gboolean __mmwfd_gstreamer_init(void);
31
32 void __mmwfd_server_cb(gboolean is_error, void *userdata)
33 {
34   MMMessageParamType msg = {0, };
35   mm_wfd_t* wfd = (mm_wfd_t*)userdata;
36
37   debug_fenter();
38
39   /* check wfd handle */
40   return_if_fail ( wfd);
41   debug_error("posting message to app...");
42
43 //  msg.state.previous = prev_state;
44 //  msg.state.current = new_state;
45   if(is_error)
46     MMWFD_POST_MSG( wfd, MM_MESSAGE_ERROR, &msg );
47 }
48
49 int _mmwfd_create (MMHandleType hwfd) // @
50 {
51   mm_wfd_t* wfd = (mm_wfd_t*)hwfd;
52   debug_fenter();
53
54   return_val_if_fail ( wfd, MM_ERROR_WFD_NOT_INITIALIZED );
55
56   MMTA_ACUM_ITEM_BEGIN("[KPI] media wifi-display service create->playing", FALSE);
57
58   /* initialize wfd state */
59   MMWFD_CURRENT_STATE(wfd)   = MM_WFD_STATE_NONE;
60   MMWFD_PREV_STATE(wfd)     = MM_WFD_STATE_NONE;
61   MMWFD_PENDING_STATE(wfd)   = MM_WFD_STATE_NONE;
62   MMWFD_TARGET_STATE(wfd)    = MM_WFD_STATE_NONE;
63
64     debug_log ("\n\n\ncur : %d, prev : %d, pend : %d, target : %d\n\n\n\n",
65        MMWFD_CURRENT_STATE(wfd),
66        MMWFD_PREV_STATE(wfd),
67        MMWFD_PENDING_STATE(wfd),
68        MMWFD_TARGET_STATE(wfd));
69
70   MMWFD_PRINT_STATE(wfd);
71
72   /* check current state */
73   MMWFD_CHECK_STATE_RETURN_IF_FAIL ( wfd, MMWFD_COMMAND_CREATE );
74
75   /* construct attributes */
76   // TODO: need to decide on attributes
77
78   wfd->attrs = _mmwfd_construct_attribute(wfd);
79   if ( NULL == wfd->attrs)
80   {
81     debug_critical("Failed to construct attributes\n");
82     goto ERROR;
83   }
84
85   /* initialize gstreamer with configured parameter */
86   if ( ! __mmwfd_gstreamer_init() )
87   {
88     debug_critical("Initializing gstreamer failed\n");
89     goto ERROR;
90   }
91
92   /* creates the server object */
93   wfd->server = gst_rtsp_server_new(__mmwfd_server_cb, wfd);
94   if (NULL == wfd->server)
95   {
96     debug_error("Failed to create server...");
97     goto ERROR;
98   }
99
100   /* Gets the media mapping object for the server */
101   wfd->mapping = gst_rtsp_server_get_media_mapping (wfd->server);
102   if (wfd->mapping == NULL)
103   {
104     debug_error ("No media mapping...");
105     goto ERROR;
106   }
107
108   wfd->factory = gst_rtsp_media_factory_new ();
109   if (wfd->factory == NULL)
110   {
111     debug_error ("Failed to create factory...");
112     goto ERROR;
113   }
114
115   /* attach the test factory to the /test url */
116   // TODO: Check why test url name is required.... ???
117     gst_rtsp_media_mapping_add_factory (wfd->mapping, "/wfd1.0", wfd->factory);
118
119   /* set wfd state to ready */
120   MMWFD_SET_STATE(wfd, MM_WFD_STATE_NULL);
121
122   debug_fleave();
123
124   return MM_ERROR_NONE;
125
126 ERROR:
127
128   /* release attributes */
129   _mmwfd_deconstruct_attribute((mm_wfd_t *)wfd);
130
131   return MM_ERROR_WFD_INTERNAL;
132 }
133
134
135 int _mmwfd_destroy (MMHandleType hwfd) // @
136 {
137   mm_wfd_t* wfd = (mm_wfd_t*)hwfd;
138
139   debug_fenter();
140
141   /* check wfd handle */
142   return_val_if_fail ( wfd, MM_ERROR_WFD_NOT_INITIALIZED );
143
144   /* destroy can called at anytime */
145   MMWFD_CHECK_STATE_RETURN_IF_FAIL ( wfd, MMWFD_COMMAND_DESTROY );
146
147   g_object_unref (wfd->client);
148   g_object_unref (wfd->server);
149   g_object_unref (wfd->mapping);
150   g_object_unref (wfd->factory);
151
152   /* release attributes */
153   _mmwfd_deconstruct_attribute( wfd );
154
155   debug_fleave();
156
157   return MM_ERROR_NONE;
158 }
159
160 int _mmwfd_realize (MMHandleType hwfd) // @
161 {
162   mm_wfd_t* wfd =  (mm_wfd_t*)hwfd;
163   char *server_ip =NULL;
164   int backlog_cnt = 1;
165   char *port = 0;
166   MMHandleType attrs = 0;
167   int ret = MM_ERROR_NONE;
168
169   debug_fenter();
170
171   /* check wfd handle */
172   return_val_if_fail ( wfd, MM_ERROR_WFD_NOT_INITIALIZED )
173
174   /* check current state */
175   MMWFD_CHECK_STATE_RETURN_IF_FAIL( wfd, MMWFD_COMMAND_REALIZE );
176
177   attrs = MMWFD_GET_ATTRS(wfd);
178   if ( !attrs )
179   {
180     debug_error("fail to get attributes.\n");
181     return MM_ERROR_WFD_INTERNAL;
182   }
183
184   /* set the server_ip address on WFD-server */
185   mm_attrs_get_string_by_name ( attrs, "server_ip", &server_ip);
186   gst_rtsp_server_set_address(wfd->server, server_ip);
187
188   debug_log ("server_ip : %s", server_ip);
189
190   /* set service address on WFD-server */
191   mm_attrs_get_string_by_name(attrs, "server_port", &port);
192   gst_rtsp_server_set_service (wfd->server, port);
193
194   debug_log ("server_port : %s", port);
195
196   /* set max clients allowed on WFD-server */
197   mm_attrs_get_int_by_name(attrs, "max_client_count", &backlog_cnt);
198   gst_rtsp_server_set_backlog (wfd->server, backlog_cnt);
199
200   debug_log ("max_client_count : %d", backlog_cnt);
201
202   /* attach the server to the default maincontext */
203   if (gst_rtsp_server_attach (wfd->server, NULL) == 0)
204   {
205     debug_error ("Failed to attach server to context");
206     return MM_ERROR_WFD_INTERNAL;
207   }
208
209   MMWFD_SET_STATE ( wfd, MM_WFD_STATE_READY );
210
211   debug_fleave();
212
213   return ret;
214 }
215
216 int _mmwfd_unrealize (MMHandleType hwfd)
217 {
218   mm_wfd_t* wfd =  (mm_wfd_t*)hwfd;
219   void *pool;
220
221   int ret = MM_ERROR_NONE;
222
223   debug_fenter();
224
225   pool = gst_rtsp_server_get_session_pool (wfd->server);
226   gst_rtsp_session_pool_cleanup (pool);
227   g_object_unref (pool);
228
229   debug_fleave();
230
231   return ret;
232 }
233
234 int _mmwfd_connect (MMHandleType hwfd)
235 {
236   mm_wfd_t* wfd =  (mm_wfd_t*)hwfd;
237
238   int ret = MM_ERROR_NONE;
239
240   debug_fenter();
241
242   return_val_if_fail ( wfd, MM_ERROR_WFD_NOT_INITIALIZED );
243
244   /* check current state */
245   MMWFD_CHECK_STATE_RETURN_IF_FAIL( wfd, MMFWD_COMMAND_CONNECT);
246
247   MMWFD_SET_STATE ( wfd, MM_WFD_STATE_CONNECTION_WAIT );
248
249   /* start accepting the client.. this call is a blocking call & keep on waiting on accept () sys API */
250   wfd->client = gst_rtsp_server_accept_client (wfd->server);
251   if (wfd->client == NULL)
252   {
253     debug_error ("Error in client accept");
254     return MM_ERROR_WFD_INTERNAL;
255   }
256
257   if (!gst_rtsp_server_negotiate_client (wfd->server, wfd->client))
258   {
259     debug_error ("Error in starting client");
260     return MM_ERROR_WFD_INTERNAL;
261   }
262
263   MMWFD_SET_STATE ( wfd, MM_WFD_STATE_CONNECTED );
264
265   debug_fleave();
266
267   return ret;
268 }
269
270 int _mmwfd_start (MMHandleType hwfd) // @
271 {
272   mm_wfd_t* wfd = (mm_wfd_t*) hwfd;
273   gint ret = MM_ERROR_NONE;
274
275   debug_fenter();
276
277   return_val_if_fail ( wfd, MM_ERROR_WFD_NOT_INITIALIZED );
278
279   /* check current state */
280   MMWFD_CHECK_STATE_RETURN_IF_FAIL( wfd, MMWFD_COMMAND_START );
281
282   /* set client params */
283   gst_rtsp_server_set_client_params (wfd->server, wfd->client, WFD_INI()->videosrc_element, WFD_INI()->session_mode, WFD_INI()->videobitrate, WFD_INI()->mtu_size,
284       WFD_INI()->infile);
285
286   if (!gst_rtsp_server_start_client (wfd->server, wfd->client))
287   {
288     debug_error ("Error in starting client");
289     return MM_ERROR_WFD_INTERNAL;
290   }
291
292   MMWFD_SET_STATE ( wfd, MM_WFD_STATE_PLAYING );
293
294   debug_fleave();
295
296   return ret;
297 }
298
299 int _mmwfd_pause (MMHandleType hwfd) // @
300 {
301   mm_wfd_t* wfd = (mm_wfd_t*) hwfd;
302   gint ret = MM_ERROR_NONE;
303
304   debug_fenter();
305
306   return_val_if_fail ( wfd, MM_ERROR_WFD_NOT_INITIALIZED );
307
308   /* check current state */
309   //MMWFD_CHECK_STATE_RETURN_IF_FAIL( wfd, MMWFD_COMMAND_PLAY );
310
311   if (!gst_rtsp_server_pause_client (wfd->server, wfd->client))
312   {
313     debug_error ("Error in starting client");
314     return MM_ERROR_WFD_INTERNAL;
315   }
316
317   MMWFD_SET_STATE ( wfd, MM_WFD_STATE_PAUSED);
318
319   debug_fleave();
320
321   return ret;
322 }
323
324 int _mmwfd_resume (MMHandleType hwfd) // @
325 {
326   mm_wfd_t* wfd = (mm_wfd_t*) hwfd;
327   gint ret = MM_ERROR_NONE;
328
329   debug_fenter();
330
331   return_val_if_fail ( wfd, MM_ERROR_WFD_NOT_INITIALIZED );
332
333   /* check current state */
334   //MMWFD_CHECK_STATE_RETURN_IF_FAIL( wfd, MMWFD_COMMAND_PAUSE );
335
336   if (!gst_rtsp_server_resume_client (wfd->server, wfd->client))
337   {
338     debug_error ("Error in starting client");
339     return MM_ERROR_WFD_INTERNAL;
340   }
341
342   MMWFD_SET_STATE ( wfd, MM_WFD_STATE_PLAYING );
343
344   debug_fleave();
345
346   return ret;
347 }
348
349 int _mmwfd_standby (MMHandleType hwfd) // @
350 {
351   mm_wfd_t* wfd = (mm_wfd_t*) hwfd;
352   gint ret = MM_ERROR_NONE;
353
354   debug_fenter();
355   return_val_if_fail ( wfd, MM_ERROR_WFD_NOT_INITIALIZED );
356
357   /* check current state */
358   //MMWFD_CHECK_STATE_RETURN_IF_FAIL( wfd, MMWFD_COMMAND_PLAY );
359
360   if (!gst_rtsp_server_standby_client (wfd->server, wfd->client))
361   {
362     debug_error ("Error in client standby");
363     return MM_ERROR_WFD_INTERNAL;
364   }
365
366   MMWFD_SET_STATE ( wfd, MM_WFD_STATE_PAUSED);
367
368   debug_fleave();
369
370   return ret;
371 }
372
373 int _mmwfd_stop (MMHandleType hwfd) // @
374 {
375   mm_wfd_t* wfd = (mm_wfd_t*) hwfd;
376   gint ret = MM_ERROR_NONE;
377
378   debug_fenter();
379
380   return_val_if_fail ( wfd, MM_ERROR_WFD_NOT_INITIALIZED );
381
382   /* check current state */
383   //MMWFD_CHECK_STATE_RETURN_IF_FAIL( wfd, MMWFD_COMMAND_STOP );
384   if (!gst_rtsp_server_stop_client (wfd->server, wfd->client))
385   {
386     debug_error ("Error in starting client");
387     return MM_ERROR_WFD_INTERNAL;
388   }
389   debug_fleave();
390
391   return ret;
392 }
393
394 int _mmwfd_get_state(MMHandleType hwfd, int *state) // @
395 {
396   mm_wfd_t *wfd = (mm_wfd_t*)hwfd;
397
398   return_val_if_fail(state, MM_ERROR_INVALID_ARGUMENT);
399
400   *state = MMWFD_CURRENT_STATE(wfd);
401
402   return MM_ERROR_NONE;
403 }
404
405 static const gchar *
406 __get_state_name ( int state )
407 {
408   switch ( state )
409   {
410     case MM_WFD_STATE_NULL:
411       return "NULL";
412     case MM_WFD_STATE_READY:
413       return "READY";
414     case MM_WFD_STATE_PAUSED:
415       return "PAUSED";
416     case MM_WFD_STATE_CONNECTION_WAIT:
417       return "WAIT_FOR_CONNECTION";
418     case MM_WFD_STATE_CONNECTED:
419       return "CONNECTED";
420     case MM_WFD_STATE_PLAYING:
421       return "PLAYING";
422     case MM_WFD_STATE_NONE:
423       return "NONE";
424     default:
425       debug_log ("\n\n\nstate value : %d\n\n\n", state);
426       return "INVALID";
427   }
428 }
429
430 static int
431 __mmwfd_check_state(mm_wfd_t* wfd, enum PlayerCommandState command)
432 {
433   MMWfdStateType current_state = MM_WFD_STATE_NUM;
434   MMWfdStateType pending_state = MM_WFD_STATE_NUM;
435   MMWfdStateType target_state = MM_WFD_STATE_NUM;
436   MMWfdStateType prev_state = MM_WFD_STATE_NUM;
437
438   debug_fenter();
439
440   return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
441
442   current_state = MMWFD_CURRENT_STATE(wfd);
443   pending_state = MMWFD_PENDING_STATE(wfd);
444   target_state = MMWFD_TARGET_STATE(wfd);
445   prev_state = MMWFD_PREV_STATE(wfd);
446
447   MMWFD_PRINT_STATE(wfd);
448
449   debug_log("incomming command : %d \n", command );
450
451   switch( command )
452   {
453     case MMWFD_COMMAND_CREATE:
454     {
455       MMWFD_TARGET_STATE(wfd) = MM_WFD_STATE_NULL;
456
457       if ( current_state == MM_WFD_STATE_NULL ||
458         current_state == MM_WFD_STATE_READY ||
459         current_state == MM_WFD_STATE_PAUSED ||
460         current_state == MM_WFD_STATE_CONNECTION_WAIT ||
461         current_state == MM_WFD_STATE_CONNECTED ||
462         current_state == MM_WFD_STATE_PLAYING )
463         goto NO_OP;
464     }
465     break;
466
467     case MMWFD_COMMAND_DESTROY:
468     {
469       /* destroy can called anytime */
470
471       MMWFD_TARGET_STATE(wfd) = MM_WFD_STATE_NONE;
472     }
473     break;
474
475     case MMWFD_COMMAND_REALIZE:
476     {
477       MMWFD_TARGET_STATE(wfd) = MM_WFD_STATE_READY;
478
479       if ( pending_state != MM_WFD_STATE_NONE )
480       {
481         goto INVALID_STATE;
482       }
483       else
484       {
485         /* need ready state to realize */
486         if ( current_state == MM_WFD_STATE_READY )
487           goto NO_OP;
488
489         if ( current_state != MM_WFD_STATE_NULL )
490           goto INVALID_STATE;
491       }
492     }
493     break;
494
495     case MMWFD_COMMAND_UNREALIZE:
496     {
497       MMWFD_TARGET_STATE(wfd) = MM_WFD_STATE_NULL;
498
499       if ( current_state == MM_WFD_STATE_NULL )
500         goto NO_OP;
501     }
502     break;
503
504     case MMFWD_COMMAND_CONNECT:
505     {
506       MMWFD_TARGET_STATE(wfd) = MM_WFD_STATE_CONNECTED;
507
508       // TODO: check any extra error handing is needed
509
510       MMWFD_PRINT_STATE(wfd);
511
512       debug_log ("target state is CONNECTED...");
513     }
514     break;
515
516     case MMWFD_COMMAND_START:
517     {
518       MMWFD_TARGET_STATE(wfd) = MM_WFD_STATE_PLAYING;
519
520       if ( pending_state == MM_WFD_STATE_NONE )
521       {
522         if ( current_state == MM_WFD_STATE_PLAYING )
523           goto NO_OP;
524         else if ( current_state  != MM_WFD_STATE_READY &&
525           current_state != MM_WFD_STATE_PAUSED  && current_state != MM_WFD_STATE_CONNECTED)
526           goto INVALID_STATE;
527       }
528       else if ( pending_state == MM_WFD_STATE_PLAYING )
529       {
530         goto ALREADY_GOING;
531       }
532       else if ( pending_state == MM_WFD_STATE_PAUSED )
533       {
534         debug_log("wfd is going to paused state, just change the pending state as playing.\n");
535       }
536       else
537       {
538         goto INVALID_STATE;
539       }
540     }
541     break;
542
543     case MMWFD_COMMAND_STOP:
544     {
545       {
546         MMWFD_TARGET_STATE(wfd) = MM_WFD_STATE_READY;
547
548         if ( current_state == MM_WFD_STATE_READY )
549           goto NO_OP;
550       }
551
552       /* need playing/paused state to stop */
553       if ( current_state != MM_WFD_STATE_PLAYING &&
554          current_state != MM_WFD_STATE_PAUSED )
555         goto INVALID_STATE;
556     }
557     break;
558
559     case MMWFD_COMMAND_PAUSE:
560     {
561
562       MMWFD_TARGET_STATE(wfd) = MM_WFD_STATE_PAUSED;
563
564       if ( pending_state == MM_WFD_STATE_NONE )
565       {
566         if ( current_state == MM_WFD_STATE_PAUSED )
567           goto NO_OP;
568         else if ( current_state != MM_WFD_STATE_PLAYING && current_state != MM_WFD_STATE_READY ) // support loading state of broswer
569           goto INVALID_STATE;
570       }
571       else if ( pending_state == MM_WFD_STATE_PAUSED )
572       {
573         goto ALREADY_GOING;
574       }
575       else if ( pending_state == MM_WFD_STATE_PLAYING )
576       {
577         if ( current_state == MM_WFD_STATE_PAUSED ) {
578           debug_log("wfd is PAUSED going to PLAYING, just change the pending state as PAUSED.\n");
579         } else {
580           goto INVALID_STATE;
581         }
582       }
583     }
584     break;
585
586     case MMWFD_COMMAND_RESUME:
587     {
588       MMWFD_TARGET_STATE(wfd) = MM_WFD_STATE_PLAYING;
589
590       if ( pending_state == MM_WFD_STATE_NONE )
591       {
592         if ( current_state == MM_WFD_STATE_PLAYING )
593           goto NO_OP;
594         else if (  current_state != MM_WFD_STATE_PAUSED )
595           goto INVALID_STATE;
596       }
597       else if ( pending_state == MM_WFD_STATE_PLAYING )
598       {
599         goto ALREADY_GOING;
600       }
601       else if ( pending_state == MM_WFD_STATE_PAUSED )
602       {
603         debug_log("wfd is going to paused state, just change the pending state as playing.\n");
604       }
605       else
606       {
607         goto INVALID_STATE;
608       }
609     }
610     break;
611
612     default:
613     break;
614   }
615
616   debug_log("status OK\n");
617
618   wfd->cmd = command;
619
620   debug_fleave();
621
622   return MM_ERROR_NONE;
623
624
625 INVALID_STATE:
626   debug_warning("since wfd is in wrong state(%s). it's not able to apply the command(%d)\n",
627     MMWFD_STATE_GET_NAME(current_state), command);
628   return MM_ERROR_WFD_INVALID_STATE;
629
630 NO_OP:
631   debug_warning("wfd is in the desired state(%s). doing nothing\n", MMWFD_STATE_GET_NAME(current_state));
632   return MM_ERROR_WFD_NO_OP;
633
634 ALREADY_GOING:
635   debug_warning("wfd is already going to %s, doing nothing.\n", MMWFD_STATE_GET_NAME(pending_state));
636   return MM_ERROR_WFD_NO_OP;
637 }
638
639 static gboolean
640 __mmwfd_gstreamer_init(void) // @
641 {
642   static gboolean initialized = FALSE;
643   static const int max_argc = 50;
644   gint* argc = NULL;
645   gchar** argv = NULL;
646   GError *err = NULL;
647   int i = 0;
648
649   debug_fenter();
650
651   if ( initialized )
652   {
653     debug_log("gstreamer already initialized.\n");
654     return TRUE;
655   }
656
657   /* alloc */
658   argc = malloc( sizeof(int) );
659   argv = malloc( sizeof(gchar*) * max_argc );
660
661   if ( !argc || !argv )
662     goto ERROR;
663
664   memset( argv, 0, sizeof(gchar*) * max_argc );
665
666   /* add initial */
667   *argc = 1;
668   argv[0] = g_strdup( "mmwfd" );
669
670   /* add gst_param */
671   for ( i = 0; i < 5; i++ ) /* FIXIT : num of param is now fixed to 5. make it dynamic */
672   {
673     if ( strlen( WFD_INI()->gst_param[i] ) > 0 )
674     {
675       argv[*argc] = g_strdup( WFD_INI()->gst_param[i] );
676       (*argc)++;
677     }
678   }
679
680   /* we would not do fork for scanning plugins */
681   argv[*argc] = g_strdup("--gst-disable-registry-fork");
682   (*argc)++;
683
684   /* check disable registry scan */
685   if ( WFD_INI()->skip_rescan )
686   {
687     argv[*argc] = g_strdup("--gst-disable-registry-update");
688     (*argc)++;
689   }
690
691   /* check disable segtrap */
692   if ( WFD_INI()->disable_segtrap )
693   {
694     argv[*argc] = g_strdup("--gst-disable-segtrap");
695     (*argc)++;
696   }
697
698   debug_log("initializing gstreamer with following parameter\n");
699   debug_log("argc : %d\n", *argc);
700
701   for ( i = 0; i < *argc; i++ )
702   {
703     debug_log("argv[%d] : %s\n", i, argv[i]);
704   }
705
706
707   /* initializing gstreamer */
708   __ta__("gst_init time",
709
710     if ( ! gst_init_check (argc, &argv, &err))
711     {
712       debug_error("Could not initialize GStreamer: %s\n", err ? err->message : "unknown error occurred");
713       if (err)
714       {
715         g_error_free (err);
716       }
717
718       goto ERROR;
719     }
720   );
721
722   /* release */
723   for ( i = 0; i < *argc; i++ )
724   {
725     MMWFD_FREEIF( argv[i] );
726   }
727
728   MMWFD_FREEIF( argv );
729   MMWFD_FREEIF( argc );
730
731   /* done */
732   initialized = TRUE;
733
734   debug_fleave();
735
736   return TRUE;
737
738 ERROR:
739
740   MMWFD_FREEIF( argv );
741   MMWFD_FREEIF( argc );
742
743   return FALSE;
744 }
745
746
747 static gboolean
748 __mmwfd_set_state(mm_wfd_t* wfd, int state) // @
749 {
750   MMWfdStateType current_state = MM_WFD_STATE_NONE;
751   MMWfdStateType prev_state = MM_WFD_STATE_NONE;
752   MMWfdStateType target_state = MM_WFD_STATE_NONE;
753   MMWfdStateType pending_state = MM_WFD_STATE_NONE;
754   MMMessageParamType msg = {0, };
755   int asm_result = MM_ERROR_NONE;
756   int new_state = state;
757
758   debug_fenter();
759
760   return_val_if_fail ( wfd, FALSE );
761
762   prev_state = MMWFD_PREV_STATE(wfd);
763   current_state = MMWFD_CURRENT_STATE(wfd);
764   pending_state = MMWFD_PENDING_STATE(wfd);
765   target_state = MMWFD_TARGET_STATE(wfd);
766
767   debug_log ("added");
768   MMWFD_PRINT_STATE(wfd);
769
770   MMWFD_PREV_STATE(wfd) = current_state;
771   MMWFD_CURRENT_STATE(wfd) = new_state;
772
773   if ( pending_state == new_state )
774     MMWFD_PENDING_STATE(wfd) = MM_WFD_STATE_NONE;
775
776   if ( current_state == new_state )
777   {
778     debug_warning("already same state(%s)\n", MMWFD_STATE_GET_NAME(state));
779     return TRUE;
780   }
781
782   MMWFD_PRINT_STATE(wfd);
783
784   if (target_state == new_state)
785   {
786     msg.state.previous = prev_state;
787     msg.state.current = new_state;
788
789     MMWFD_POST_MSG( wfd, MM_MESSAGE_STATE_CHANGED, &msg );
790
791     debug_log ("wfd reach the target state, then do something in each state(%s).\n", MMWFD_STATE_GET_NAME(target_state));
792   }
793   else
794   {
795     debug_log ("intermediate state, do nothing.\n");
796     return TRUE;
797   }
798
799   switch ( target_state )
800   {
801     case MM_WFD_STATE_NULL:
802     case MM_WFD_STATE_READY:
803     case MM_WFD_STATE_CONNECTION_WAIT:
804     case MM_WFD_STATE_CONNECTED:
805     break;
806
807     case MM_WFD_STATE_PAUSED:
808     {
809       /* special care for local playback. normaly we can get some content attribute
810        * when the demuxer is changed to PAUSED. so we are trying it. it will be tried again
811        * when PLAYING state has signalled if failed.
812        * note that this is only happening pause command has come before the state of pipeline
813        * reach to the PLAYING.
814        */
815       //_mmwfd_update_content_attrs( wfd );
816
817     }
818     break;
819
820     case MM_WFD_STATE_PLAYING:
821     {
822       /* update attributes which are only available on playing status */
823       //_mmwfd_update_content_attrs ( wfd );
824
825       if ( wfd->cmd == MMWFD_COMMAND_START )
826       {
827       }
828
829     }
830     break;
831
832     case MM_WFD_STATE_NONE:
833     default:
834       debug_warning("invalid target state, there is nothing to do.\n");
835       break;
836   }
837
838   debug_fleave();
839
840   return TRUE;
841 }
842
843 static int
844 __gst_set_message_callback(mm_wfd_t* wfd, MMMessageCallback callback, gpointer user_param) // @
845 {
846   debug_fenter();
847
848   if ( !wfd )
849   {
850     debug_warning("set_message_callback is called with invalid wfd handle\n");
851     return MM_ERROR_WFD_NOT_INITIALIZED;
852   }
853
854   wfd->msg_cb = callback;
855   wfd->msg_cb_param = user_param;
856
857   debug_log("msg_cb : 0x%x     msg_cb_param : 0x%x\n", (guint)callback, (guint)user_param);
858
859   debug_fleave();
860
861   return MM_ERROR_NONE;
862 }
863
864 int
865 _mmwfd_set_message_callback(MMHandleType hwfd, MMMessageCallback callback, gpointer user_param) // @
866 {
867   mm_wfd_t* wfd = (mm_wfd_t*)hwfd;
868
869       return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
870
871   return __gst_set_message_callback(wfd, callback, user_param);
872 }
873
874 gboolean
875 __mmwfd_post_message(mm_wfd_t* wfd, enum MMMessageType msgtype, MMMessageParamType* param) // @
876 {
877   return_val_if_fail( wfd, FALSE );
878
879   if ( !wfd->msg_cb )
880   {
881     debug_warning("no msg callback. can't post\n");
882     return FALSE;
883   }
884
885   //debug_log("Message (type : %d)  will be posted using msg-cb(%p). \n", msgtype, wfd->msg_cb);
886
887   wfd->msg_cb(msgtype, param, wfd->msg_cb_param);
888
889   return TRUE;
890 }
891
892