Initial draft of R2 feature 'Secondary Sink'
[platform/core/multimedia/libmm-wfd.git] / src / mm_wfd_sink.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  * Maksym Ukhanov <m.ukhanov@samsung.com>, Hyunjun Ko <zzoon.ko@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_sink.h"
26 #include "mm_wfd_sink_util.h"
27 #include "mm_wfd_sink_priv.h"
28 #include "mm_wfd_sink_dlog.h"
29
30 int mm_wfd_sink_create(MMHandleType *wfd_sink)
31 {
32         mm_wfd_sink_t *new_wfd_sink = NULL;
33         int result = MM_ERROR_NONE;
34
35         wfd_sink_debug_fenter();
36
37         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
38
39         result = _mm_wfd_sink_create(&new_wfd_sink, MM_WFD_SINK_INI_DEFAULT_PATH);
40         if (result != MM_ERROR_NONE) {
41                 wfd_sink_error("fail to create wi-fi display sink handle. ret[%d]", result);
42                 *wfd_sink = (MMHandleType)NULL;
43                 return result;
44         }
45
46         /* init wfd lock */
47         g_mutex_init(&new_wfd_sink->cmd_lock);
48
49         *wfd_sink = (MMHandleType)new_wfd_sink;
50
51         wfd_sink_debug_fleave();
52
53         return result;
54
55 }
56
57 int mm_wfd_sink_create_r2(MMHandleType *wfd_sink)
58 {
59         int result = MM_ERROR_NONE;
60
61         result = mm_wfd_sink_create(wfd_sink);
62         if (result != MM_ERROR_NONE) {
63                 wfd_sink_error("fail to create wi-fi display r2 sink handle. ret[%d]", result);
64                 *wfd_sink = (MMHandleType)NULL;
65                 return result;
66         }
67
68         ((mm_wfd_sink_t *)*wfd_sink)->is_coupled_sink_supported = TRUE;
69
70         return result;
71 }
72
73 int mm_wfd_sink_prepare(MMHandleType wfd_sink_handle)
74 {
75         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
76         int result = MM_ERROR_NONE;
77
78         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
79
80
81         if (wfd_sink->func_table == NULL || wfd_sink->func_table->prepare == NULL) {
82                 MMWFDSINK_CMD_LOCK(wfd_sink);
83                 result = _mm_wfd_sink_prepare(wfd_sink);
84                 MMWFDSINK_CMD_UNLOCK(wfd_sink);
85         } else {
86                 result = wfd_sink->func_table->prepare(wfd_sink_handle);
87         }
88
89         return result;
90 }
91
92 int mm_wfd_sink_connect(MMHandleType wfd_sink_handle, const char *uri)
93 {
94         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
95         int result = MM_ERROR_NONE;
96
97         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
98         wfd_sink_return_val_if_fail(uri, MM_ERROR_WFD_INVALID_ARGUMENT);
99
100         if (wfd_sink->func_table == NULL || wfd_sink->func_table->connect == NULL) {
101                 MMWFDSINK_CMD_LOCK(wfd_sink);
102                 result = _mm_wfd_sink_connect(wfd_sink, uri);
103                 MMWFDSINK_CMD_UNLOCK(wfd_sink);
104         } else {
105                 result = wfd_sink->func_table->connect(wfd_sink_handle, uri);
106         }
107
108         return result;
109 }
110
111 int mm_wfd_sink_start(MMHandleType wfd_sink_handle)
112 {
113         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
114         int result = MM_ERROR_NONE;
115
116         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
117
118         if (wfd_sink->func_table == NULL || wfd_sink->func_table->start == NULL) {
119                 MMWFDSINK_CMD_LOCK(wfd_sink);
120                 result = _mm_wfd_sink_start(wfd_sink);
121                 MMWFDSINK_CMD_UNLOCK(wfd_sink);
122         } else {
123                 result = wfd_sink->func_table->start(wfd_sink_handle);
124         }
125
126         return result;
127 }
128
129 int mm_wfd_sink_pause(MMHandleType wfd_sink_handle)
130 {
131         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
132         int result = MM_ERROR_NONE;
133
134         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
135
136         if (wfd_sink->func_table == NULL || wfd_sink->func_table->pause == NULL) {
137                 MMWFDSINK_CMD_LOCK(wfd_sink);
138                 result = _mm_wfd_sink_pause(wfd_sink);
139                 MMWFDSINK_CMD_UNLOCK(wfd_sink);
140         } else {
141                 result = wfd_sink->func_table->pause(wfd_sink_handle);
142         }
143
144         return result;
145 }
146
147 int mm_wfd_sink_resume(MMHandleType wfd_sink_handle)
148 {
149         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
150         int result = MM_ERROR_NONE;
151
152         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
153
154         if (wfd_sink->func_table == NULL || wfd_sink->func_table->resume == NULL) {
155                 MMWFDSINK_CMD_LOCK(wfd_sink);
156                 result = _mm_wfd_sink_resume(wfd_sink);
157                 MMWFDSINK_CMD_UNLOCK(wfd_sink);
158         } else {
159                 result = wfd_sink->func_table->resume(wfd_sink_handle);
160         }
161
162         return result;
163 }
164
165 int mm_wfd_sink_disconnect(MMHandleType wfd_sink_handle)
166 {
167         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
168         int result = MM_ERROR_NONE;
169
170         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
171
172         if (wfd_sink->func_table == NULL || wfd_sink->func_table->disconnect == NULL) {
173                 MMWFDSINK_CMD_LOCK(wfd_sink);
174                 result = _mm_wfd_sink_disconnect(wfd_sink);
175                 MMWFDSINK_CMD_UNLOCK(wfd_sink);
176         } else {
177                 result = wfd_sink->func_table->disconnect(wfd_sink_handle);
178         }
179
180         return result;
181 }
182
183 int mm_wfd_sink_unprepare(MMHandleType wfd_sink_handle)
184 {
185         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
186         int result = MM_ERROR_NONE;
187
188         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
189
190         if (wfd_sink->func_table == NULL || wfd_sink->func_table->unprepare == NULL) {
191                 MMWFDSINK_CMD_LOCK(wfd_sink);
192                 result = _mm_wfd_sink_unprepare(wfd_sink);
193                 MMWFDSINK_CMD_UNLOCK(wfd_sink);
194         } else {
195                 result = wfd_sink->func_table->unprepare(wfd_sink_handle);
196         }
197
198         return result;
199 }
200
201 int mm_wfd_sink_destroy(MMHandleType wfd_sink_handle)
202 {
203         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
204         mm_wfd_sink_t *handle = NULL;
205         int result = MM_ERROR_NONE;
206
207         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
208
209         MMWFDSINK_CMD_LOCK(wfd_sink);
210         result = _mm_wfd_sink_destroy(wfd_sink);
211         MMWFDSINK_CMD_UNLOCK(wfd_sink);
212
213         g_mutex_clear(&(wfd_sink->cmd_lock));
214
215         /* TODO */
216         handle = (mm_wfd_sink_t *)wfd_sink_handle;
217         MMWFDSINK_FREEIF(handle);
218
219         return result;
220 }
221
222 int mm_wfd_sink_set_message_callback(MMHandleType wfd_sink_handle, MMWFDMessageCallback callback, void *user_data)
223 {
224         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
225         int result = MM_ERROR_NONE;
226
227         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
228
229         MMWFDSINK_CMD_LOCK(wfd_sink);
230         result = _mm_wfd_set_message_callback(wfd_sink, callback, user_data);
231         MMWFDSINK_CMD_UNLOCK(wfd_sink);
232
233         return result;
234 }
235
236 int mm_wfd_sink_set_attribute(MMHandleType wfd_sink_handle,  char **err_attr_name, const char *first_attribute_name, ...)
237 {
238         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
239         int result = MM_ERROR_NONE;
240         va_list var_args;
241
242         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
243         wfd_sink_return_val_if_fail(first_attribute_name, MM_ERROR_WFD_INVALID_ARGUMENT);
244
245         MMWFDSINK_CMD_LOCK(wfd_sink);
246         va_start(var_args, first_attribute_name);
247         result = _mmwfd_set_attribute(MMWFDSINK_GET_ATTRS(wfd_sink), err_attr_name, first_attribute_name, var_args);
248         va_end(var_args);
249         MMWFDSINK_CMD_UNLOCK(wfd_sink);
250
251         return result;
252 }
253
254 int mm_wfd_sink_get_video_resolution(MMHandleType wfd_sink_handle, gint *width, gint *height)
255 {
256         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
257
258         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
259         wfd_sink_return_val_if_fail(width, MM_ERROR_WFD_INVALID_ARGUMENT);
260         wfd_sink_return_val_if_fail(height, MM_ERROR_WFD_INVALID_ARGUMENT);
261
262         *width = wfd_sink->stream_info.video_stream_info.width;
263         *height = wfd_sink->stream_info.video_stream_info.height;
264
265         return MM_ERROR_NONE;
266 }
267
268 int mm_wfd_sink_get_video_framerate(MMHandleType wfd_sink_handle, gint *frame_rate)
269 {
270         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
271
272         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
273         wfd_sink_return_val_if_fail(frame_rate, MM_ERROR_WFD_INVALID_ARGUMENT);
274
275         *frame_rate = wfd_sink->stream_info.video_stream_info.frame_rate;
276
277         return MM_ERROR_NONE;
278 }
279
280 int mm_wfd_sink_set_resolution(MMHandleType wfd_sink_handle,  gint resolution)
281 {
282         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
283         int result = MM_ERROR_NONE;
284
285         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
286
287         MMWFDSINK_CMD_LOCK(wfd_sink);
288         result = _mm_wfd_sink_set_resolution(wfd_sink, resolution);
289         MMWFDSINK_CMD_UNLOCK(wfd_sink);
290
291         return result;
292 }
293
294 int mm_wfd_sink_get_negotiated_video_codec(MMHandleType wfd_sink_handle,  gint *codec)
295 {
296         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
297         MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
298         int result = MM_ERROR_NONE;
299
300         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
301         wfd_sink_return_val_if_fail(codec, MM_ERROR_WFD_INVALID_ARGUMENT);
302
303         MMWFDSINK_CMD_LOCK(wfd_sink);
304
305         MMWFDSINK_PRINT_STATE(wfd_sink);
306         cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
307         if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
308                 cur_state != MM_WFD_SINK_STATE_PLAYING &&
309                 cur_state != MM_WFD_SINK_STATE_PAUSED) {
310
311                 wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
312                 result = MM_ERROR_WFD_INVALID_STATE;
313         } else {
314                 *codec = wfd_sink->stream_info.video_stream_info.codec;
315         }
316
317         MMWFDSINK_CMD_UNLOCK(wfd_sink);
318
319         wfd_sink_debug_fleave();
320
321         return result;
322 }
323
324 int mm_wfd_sink_get_negotiated_video_resolution(MMHandleType wfd_sink,  gint *width, gint *height)
325 {
326         int result = MM_ERROR_NONE;
327         mm_wfd_sink_t *wfd = (mm_wfd_sink_t *)wfd_sink;
328         MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
329
330         wfd_sink_return_val_if_fail(wfd, MM_ERROR_WFD_NOT_INITIALIZED);
331         wfd_sink_return_val_if_fail(width, MM_ERROR_WFD_INVALID_ARGUMENT);
332         wfd_sink_return_val_if_fail(height, MM_ERROR_WFD_INVALID_ARGUMENT);
333
334         MMWFDSINK_CMD_LOCK(wfd);
335
336         MMWFDSINK_PRINT_STATE(wfd);
337         cur_state = MMWFDSINK_CURRENT_STATE(wfd);
338         if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
339                 cur_state != MM_WFD_SINK_STATE_PLAYING &&
340                 cur_state != MM_WFD_SINK_STATE_PAUSED) {
341
342                 wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
343                 result = MM_ERROR_WFD_INVALID_STATE;
344         } else {
345                 *width = wfd->stream_info.video_stream_info.width;
346                 *height = wfd->stream_info.video_stream_info.height;
347         }
348
349         MMWFDSINK_CMD_UNLOCK(wfd);
350
351         wfd_sink_debug_fleave();
352
353         return result;
354 }
355
356 int mm_wfd_sink_get_negotiated_video_frame_rate(MMHandleType wfd_sink_handle,  gint *frame_rate)
357 {
358         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
359         MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
360         int result = MM_ERROR_NONE;
361
362         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
363         wfd_sink_return_val_if_fail(frame_rate, MM_ERROR_WFD_INVALID_ARGUMENT);
364
365         MMWFDSINK_CMD_LOCK(wfd_sink);
366
367         MMWFDSINK_PRINT_STATE(wfd_sink);
368         cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
369         if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
370                 cur_state != MM_WFD_SINK_STATE_PLAYING &&
371                 cur_state != MM_WFD_SINK_STATE_PAUSED) {
372
373                 wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
374                 result = MM_ERROR_WFD_INVALID_STATE;
375         } else {
376                 *frame_rate = wfd_sink->stream_info.video_stream_info.frame_rate;
377         }
378
379         MMWFDSINK_CMD_UNLOCK(wfd_sink);
380
381         wfd_sink_debug_fleave();
382
383         return result;
384 }
385
386 int mm_wfd_sink_get_negotiated_audio_codec(MMHandleType wfd_sink_handle,  gint *codec)
387 {
388         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
389         MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
390         int result = MM_ERROR_NONE;
391
392         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
393         wfd_sink_return_val_if_fail(codec, MM_ERROR_WFD_INVALID_ARGUMENT);
394
395         MMWFDSINK_CMD_LOCK(wfd_sink);
396
397         MMWFDSINK_PRINT_STATE(wfd_sink);
398         cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
399         if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
400                 cur_state != MM_WFD_SINK_STATE_PLAYING &&
401                 cur_state != MM_WFD_SINK_STATE_PAUSED) {
402
403                 wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
404                 result = MM_ERROR_WFD_INVALID_STATE;
405         } else {
406                 *codec = wfd_sink->stream_info.audio_stream_info.codec;
407         }
408
409         MMWFDSINK_CMD_UNLOCK(wfd_sink);
410
411         wfd_sink_debug_fleave();
412
413         return result;
414 }
415
416 int mm_wfd_sink_get_negotiated_audio_channel(MMHandleType wfd_sink_handle,  gint *channel)
417 {
418         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
419         MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
420         int result = MM_ERROR_NONE;
421
422         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
423         wfd_sink_return_val_if_fail(channel, MM_ERROR_WFD_INVALID_ARGUMENT);
424
425         MMWFDSINK_CMD_LOCK(wfd_sink);
426
427         MMWFDSINK_PRINT_STATE(wfd_sink);
428         cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
429         if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
430                 cur_state != MM_WFD_SINK_STATE_PLAYING &&
431                 cur_state != MM_WFD_SINK_STATE_PAUSED) {
432
433                 wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
434                 result = MM_ERROR_WFD_INVALID_STATE;
435         } else {
436                 *channel = wfd_sink->stream_info.audio_stream_info.channels;
437         }
438
439         MMWFDSINK_CMD_UNLOCK(wfd_sink);
440
441         wfd_sink_debug_fleave();
442
443         return result;
444 }
445
446 int mm_wfd_sink_get_negotiated_audio_sample_rate(MMHandleType wfd_sink_handle,  gint *sample_rate)
447 {
448         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
449         MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
450         int result = MM_ERROR_NONE;
451
452         wfd_sink_debug_fenter();
453
454         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
455         wfd_sink_return_val_if_fail(sample_rate, MM_ERROR_WFD_INVALID_ARGUMENT);
456
457         MMWFDSINK_CMD_LOCK(wfd_sink);
458
459         MMWFDSINK_PRINT_STATE(wfd_sink);
460         cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
461         if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
462                 cur_state != MM_WFD_SINK_STATE_PLAYING &&
463                 cur_state != MM_WFD_SINK_STATE_PAUSED) {
464
465                 wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
466                 result = MM_ERROR_WFD_INVALID_STATE;
467         } else {
468                 *sample_rate = wfd_sink->stream_info.audio_stream_info.sample_rate;
469         }
470
471         MMWFDSINK_CMD_UNLOCK(wfd_sink);
472
473         wfd_sink_debug_fleave();
474
475         return result;
476 }
477
478 int mm_wfd_sink_get_negotiated_audio_bitwidth(MMHandleType wfd_sink_handle,  gint *bitwidth)
479 {
480         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
481         MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
482         int result = MM_ERROR_NONE;
483
484         wfd_sink_debug_fenter();
485
486         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
487         wfd_sink_return_val_if_fail(bitwidth, MM_ERROR_WFD_INVALID_ARGUMENT);
488
489         MMWFDSINK_CMD_LOCK(wfd_sink);
490
491         MMWFDSINK_PRINT_STATE(wfd_sink);
492         cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
493         if (cur_state != MM_WFD_SINK_STATE_CONNECTED &&
494                 cur_state != MM_WFD_SINK_STATE_PLAYING &&
495                 cur_state != MM_WFD_SINK_STATE_PAUSED) {
496
497                 wfd_sink_error("This function must be called after MM_WFD_SINK_STATE_CONNECTED");
498                 result = MM_ERROR_WFD_INVALID_STATE;
499         } else {
500                 *bitwidth = wfd_sink->stream_info.audio_stream_info.bitwidth;
501         }
502
503         MMWFDSINK_CMD_UNLOCK(wfd_sink);
504
505         wfd_sink_debug_fleave();
506
507         return result;
508 }
509
510 int mm_wfd_sink_get_current_state(MMHandleType wfd_sink_handle, gint *state)
511 {
512         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
513         int result = MM_ERROR_NONE;
514
515         wfd_sink_debug_fenter();
516
517         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
518         wfd_sink_return_val_if_fail(state, MM_ERROR_WFD_INVALID_ARGUMENT);
519
520         *state = MMWFDSINK_CURRENT_STATE(wfd_sink);
521         wfd_sink_debug("mm_wfd_sink_get_current_state [%d] ", *state);
522         if (*state < MM_WFD_SINK_STATE_NONE || *state >= MM_WFD_SINK_STATE_NUM) {
523                 wfd_sink_error("Wrong state is returned. State [%d]", *state);
524                 result = MM_ERROR_WFD_INVALID_STATE;
525         } else {
526                 result = MM_ERROR_NONE;
527         }
528
529         wfd_sink_debug_fleave();
530
531         return result;
532 }
533
534 int mm_wfd_sink_set_coupled_sink(MMHandleType wfd_sink_handle, gchar* address)
535 {
536         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
537         MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
538         int result = MM_ERROR_NONE;
539
540         wfd_sink_debug_fenter();
541
542         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
543         wfd_sink_return_val_if_fail(address, MM_ERROR_WFD_INVALID_ARGUMENT);
544
545         MMWFDSINK_CMD_LOCK(wfd_sink);
546         cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
547         if (cur_state == MM_WFD_SINK_STATE_CONNECTED ||
548                 cur_state == MM_WFD_SINK_STATE_PLAYING ||
549                 cur_state == MM_WFD_SINK_STATE_PAUSED) {
550                 wfd_sink_error("This function must be called before MM_WFD_SINK_STATE_CONNECTED");
551                 result = MM_ERROR_WFD_INVALID_STATE;
552         } else {
553                 if (wfd_sink->coupled_sink_address) {
554                         wfd_sink_debug("coupled_sink_address is already set. [ %s]", wfd_sink->coupled_sink_address);
555                 } else {
556                         wfd_sink->coupled_sink_address = g_strdup(address);
557                         wfd_sink_debug("coupled_sink_address is set [%s]", wfd_sink->coupled_sink_address);
558                 }
559         }
560         MMWFDSINK_CMD_UNLOCK(wfd_sink);
561
562         wfd_sink_debug_fleave();
563
564         return result;
565 }
566
567 int mm_wfd_sink_set_coupled_sink_status(MMHandleType wfd_sink_handle, guint status)
568 {
569         mm_wfd_sink_t *wfd_sink = (mm_wfd_sink_t *)wfd_sink_handle;
570         MMWFDSinkStateType cur_state = MM_WFD_SINK_STATE_NONE;
571         int result = MM_ERROR_NONE;
572
573         wfd_sink_debug_fenter();
574
575         wfd_sink_return_val_if_fail(wfd_sink, MM_ERROR_WFD_NOT_INITIALIZED);
576         wfd_sink_return_val_if_fail(status, MM_ERROR_WFD_INVALID_ARGUMENT);
577
578         MMWFDSINK_CMD_LOCK(wfd_sink);
579         cur_state = MMWFDSINK_CURRENT_STATE(wfd_sink);
580         if (cur_state == MM_WFD_SINK_STATE_CONNECTED ||
581                 cur_state == MM_WFD_SINK_STATE_PLAYING ||
582                 cur_state == MM_WFD_SINK_STATE_PAUSED) {
583                 wfd_sink_error("This function must be called before MM_WFD_SINK_STATE_CONNECTED");
584                 result = MM_ERROR_WFD_INVALID_STATE;
585         } else {
586                 wfd_sink->coupled_sink_status = status;
587                 wfd_sink_debug("coupled_sink_status is set [%d]", wfd_sink->coupled_sink_status);
588         }
589         MMWFDSINK_CMD_UNLOCK(wfd_sink);
590
591         wfd_sink_debug_fleave();
592
593         return result;
594 }