1
2 /*
3 linphone
4 Copyright (C) 2014 Belledonne Communications SARL
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20
21 #include "private.h"
22
23 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphonePlayer);
24
25 BELLE_SIP_INSTANCIATE_VPTR(LinphonePlayer, belle_sip_object_t,
26 _linphone_player_destroy, // destroy
27 NULL, // clone
28 NULL, // marshal
29 FALSE
30 );
31
linphone_player_new(void)32 LinphonePlayer * linphone_player_new(void) {
33 LinphonePlayer *player = belle_sip_object_new(LinphonePlayer);
34 player->callbacks = linphone_player_cbs_new();
35 return player;
36 }
37
linphone_player_ref(LinphonePlayer * player)38 LinphonePlayer * linphone_player_ref(LinphonePlayer *player) {
39 belle_sip_object_ref(player);
40 return player;
41 }
42
linphone_player_unref(LinphonePlayer * player)43 void linphone_player_unref(LinphonePlayer *player) {
44 belle_sip_object_unref(player);
45 }
46
linphone_player_get_user_data(const LinphonePlayer * player)47 void *linphone_player_get_user_data(const LinphonePlayer *player) {
48 return player->user_data;
49 }
50
linphone_player_set_user_data(LinphonePlayer * player,void * ud)51 void linphone_player_set_user_data(LinphonePlayer *player, void *ud) {
52 player->user_data = ud;
53 }
54
linphone_player_get_callbacks(const LinphonePlayer * player)55 LinphonePlayerCbs * linphone_player_get_callbacks(const LinphonePlayer *player) {
56 return player->callbacks;
57 }
58
linphone_player_open(LinphonePlayer * obj,const char * filename)59 LinphoneStatus linphone_player_open(LinphonePlayer *obj, const char *filename){
60 return obj->open(obj,filename);
61 }
62
linphone_player_start(LinphonePlayer * obj)63 LinphoneStatus linphone_player_start(LinphonePlayer *obj){
64 return obj->start(obj);
65 }
66
linphone_player_pause(LinphonePlayer * obj)67 LinphoneStatus linphone_player_pause(LinphonePlayer *obj){
68 return obj->pause(obj);
69 }
70
linphone_player_seek(LinphonePlayer * obj,int time_ms)71 LinphoneStatus linphone_player_seek(LinphonePlayer *obj, int time_ms){
72 return obj->seek(obj,time_ms);
73 }
74
linphone_player_get_state(LinphonePlayer * obj)75 LinphonePlayerState linphone_player_get_state(LinphonePlayer *obj){
76 switch (obj->get_state(obj)) {
77 case MSPlayerClosed:
78 default:
79 return LinphonePlayerClosed;
80 case MSPlayerPaused:
81 return LinphonePlayerPaused;
82 case MSPlayerPlaying:
83 return LinphonePlayerPlaying;
84 }
85 }
86
linphone_player_get_duration(LinphonePlayer * obj)87 int linphone_player_get_duration(LinphonePlayer *obj) {
88 return obj->get_duration(obj);
89 }
90
linphone_player_get_current_position(LinphonePlayer * obj)91 int linphone_player_get_current_position(LinphonePlayer *obj) {
92 return obj->get_position(obj);
93 }
94
linphone_player_close(LinphonePlayer * obj)95 void linphone_player_close(LinphonePlayer *obj){
96 obj->close(obj);
97 }
98
linphone_player_destroy(LinphonePlayer * obj)99 void linphone_player_destroy(LinphonePlayer *obj) {
100 if(obj->destroy) obj->destroy(obj);
101 }
102
_linphone_player_destroy(LinphonePlayer * player)103 void _linphone_player_destroy(LinphonePlayer *player) {
104 linphone_player_cbs_unref(player->callbacks);
105 }
106
107
108 /*
109 * Call player implementation below.
110 */
111
112
call_player_check_state(LinphonePlayer * player,bool_t check_player)113 static bool_t call_player_check_state(LinphonePlayer *player, bool_t check_player){
114 LinphoneCall *call=(LinphoneCall*)player->impl;
115 if (call->state!=LinphoneCallStreamsRunning){
116 ms_warning("Call [%p]: in-call player not usable in state [%s]",call,linphone_call_state_to_string(call->state));
117 return FALSE;
118 }
119 if (call->audiostream==NULL) {
120 ms_error("call_player_check_state(): no audiostream.");
121 return FALSE;
122 }
123 if (check_player && call->audiostream->av_player.player==NULL){
124 ms_error("call_player_check_state(): no player.");
125 return FALSE;
126 }
127 return TRUE;
128 }
129
on_eof(void * user_data,MSFilter * f,unsigned int event_id,void * arg)130 static void on_eof(void *user_data, MSFilter *f, unsigned int event_id, void *arg){
131 LinphonePlayer *player=(LinphonePlayer *)user_data;
132 LinphonePlayerCbs *cbs = linphone_player_get_callbacks(player);
133 LinphonePlayerCbsEofReachedCb cb = linphone_player_cbs_get_eof_reached(cbs);
134 if (cb) cb(player);
135 }
136
call_player_open(LinphonePlayer * player,const char * filename)137 static int call_player_open(LinphonePlayer* player, const char *filename){
138 LinphoneCall *call=(LinphoneCall*)player->impl;
139 MSFilter *filter;
140 if (!call_player_check_state(player,FALSE)) return -1;
141 filter=audio_stream_open_remote_play(call->audiostream,filename);
142 if (!filter) return -1;
143 ms_filter_add_notify_callback(filter,&on_eof,player,FALSE);
144 return 0;
145 }
146
call_player_start(LinphonePlayer * player)147 static int call_player_start(LinphonePlayer *player){
148 LinphoneCall *call=(LinphoneCall*)player->impl;
149 if (!call_player_check_state(player,TRUE)) return -1;
150 return ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_START);
151 }
152
call_player_pause(LinphonePlayer * player)153 static int call_player_pause(LinphonePlayer *player){
154 LinphoneCall *call=(LinphoneCall*)player->impl;
155 if (!call_player_check_state(player,TRUE)) return -1;
156 return ms_filter_call_method_noarg(call->audiostream->av_player.player,MS_PLAYER_PAUSE);
157 }
158
call_player_get_state(LinphonePlayer * player)159 static MSPlayerState call_player_get_state(LinphonePlayer *player){
160 LinphoneCall *call=(LinphoneCall*)player->impl;
161 MSPlayerState state=MSPlayerClosed;
162 if (!call_player_check_state(player,TRUE)) return MSPlayerClosed;
163 ms_filter_call_method(call->audiostream->av_player.player,MS_PLAYER_GET_STATE,&state);
164 return state;
165 }
166
call_player_seek(LinphonePlayer * player,int time_ms)167 static int call_player_seek(LinphonePlayer *player, int time_ms){
168 LinphoneCall *call=(LinphoneCall*)player->impl;
169 if (!call_player_check_state(player,TRUE)) return -1;
170 return ms_filter_call_method(call->audiostream->av_player.player,MS_PLAYER_SEEK_MS,&time_ms);
171 }
172
call_player_close(LinphonePlayer * player)173 static void call_player_close(LinphonePlayer *player){
174 LinphoneCall *call=(LinphoneCall*)player->impl;
175 if (!call_player_check_state(player,TRUE)) return;
176 audio_stream_close_remote_play(call->audiostream);
177
178 }
179
on_call_destroy(void * obj,belle_sip_object_t * call_being_destroyed)180 static void on_call_destroy(void *obj, belle_sip_object_t *call_being_destroyed){
181 linphone_player_unref(obj);
182 }
183
linphone_call_build_player(LinphoneCall * call)184 LinphonePlayer *linphone_call_build_player(LinphoneCall *call){
185 LinphonePlayer *obj = linphone_player_new();
186 obj->open=call_player_open;
187 obj->close=call_player_close;
188 obj->start=call_player_start;
189 obj->seek=call_player_seek;
190 obj->pause=call_player_pause;
191 obj->get_state=call_player_get_state;
192 obj->impl=call;
193 belle_sip_object_weak_ref(call,on_call_destroy,obj);
194 return obj;
195 }
196
197
198 BELLE_SIP_DECLARE_NO_IMPLEMENTED_INTERFACES(LinphonePlayerCbs);
199
200 BELLE_SIP_INSTANCIATE_VPTR(LinphonePlayerCbs, belle_sip_object_t,
201 NULL, // destroy
202 NULL, // clone
203 NULL, // marshal
204 FALSE);
205
linphone_player_cbs_new(void)206 LinphonePlayerCbs *linphone_player_cbs_new(void) {
207 return belle_sip_object_new(LinphonePlayerCbs);
208 }
209
linphone_player_cbs_ref(LinphonePlayerCbs * cbs)210 LinphonePlayerCbs * linphone_player_cbs_ref(LinphonePlayerCbs *cbs) {
211 belle_sip_object_ref(cbs);
212 return cbs;
213 }
214
linphone_player_cbs_unref(LinphonePlayerCbs * cbs)215 void linphone_player_cbs_unref(LinphonePlayerCbs *cbs) {
216 belle_sip_object_unref(cbs);
217 }
218
linphone_player_cbs_get_user_data(const LinphonePlayerCbs * cbs)219 void *linphone_player_cbs_get_user_data(const LinphonePlayerCbs *cbs) {
220 return cbs->user_data;
221 }
222
linphone_player_cbs_set_user_data(LinphonePlayerCbs * cbs,void * ud)223 void linphone_player_cbs_set_user_data(LinphonePlayerCbs *cbs, void *ud) {
224 cbs->user_data = ud;
225 }
226
linphone_player_cbs_get_eof_reached(const LinphonePlayerCbs * cbs)227 LinphonePlayerCbsEofReachedCb linphone_player_cbs_get_eof_reached(const LinphonePlayerCbs *cbs) {
228 return cbs->eof;
229 }
230
linphone_player_cbs_set_eof_reached(LinphonePlayerCbs * cbs,LinphonePlayerCbsEofReachedCb cb)231 void linphone_player_cbs_set_eof_reached(LinphonePlayerCbs *cbs, LinphonePlayerCbsEofReachedCb cb) {
232 cbs->eof = cb;
233 }
234