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