From 200bbe1593e456e2da4423f3153898a53bbebe8b Mon Sep 17 00:00:00 2001 From: Danmei Chen Date: Thu, 21 Dec 2017 15:19:22 +0100 Subject: [PATCH] Add incall-player in linphone-daemon --- daemon/CMakeLists.txt | 2 + daemon/commands/play.cc | 233 ++++++++++++++++++++++++++++++++++++++++ daemon/commands/play.h | 50 +++++++++ daemon/daemon.cc | 18 ++++ daemon/daemon.h | 7 +- 5 files changed, 309 insertions(+), 1 deletion(-) create mode 100644 daemon/commands/play.cc create mode 100644 daemon/commands/play.h diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index 61178d119..038ef986f 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -79,6 +79,8 @@ set(DAEMON_SOURCE_FILES commands/msfilter-add-fmtp.h commands/netsim.cc commands/netsim.h + commands/play.cc + commands/play.h commands/play-wav.cc commands/play-wav.h commands/pop-event.cc diff --git a/daemon/commands/play.cc b/daemon/commands/play.cc new file mode 100644 index 000000000..736919954 --- /dev/null +++ b/daemon/commands/play.cc @@ -0,0 +1,233 @@ +/* +play-wav.cc +Copyright (C) 2016 Belledonne Communications, Grenoble, France + +This library is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at +your option) any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "play.h" +#include "call.h" +#include +using namespace std; +#define VOIDPTR_TO_INT(p) ((int)(intptr_t)(p)) + +void IncallPlayerStartCommand::onEof(LinphonePlayer *player){ + pair *callPlayingData = (pair *)linphone_player_get_user_data(player); + Daemon *app = callPlayingData->second; + int id = callPlayingData->first; + app->callPlayingComplete(id); + delete callPlayingData; + linphone_player_set_user_data(player, NULL); +} + + +IncallPlayerStartCommand::IncallPlayerStartCommand() : + DaemonCommand("incall-player-start", "incall-player-start []", + "Play a WAV audio file or a MKV audio/video file. The played media stream will be sent through \n" + "the RTP session of the given call.\n" + " is the file to be played.\n") { + addExample(new DaemonCommandExample("incall-player-start /usr/local/share/sounds/linphone/hello8000.wav 1", + "Status: Ok\n")); + addExample(new DaemonCommandExample("incall-player-start /usr/local/share/sounds/linphone/hello8000.wav 1", + "Status: Error\n" + "Reason: No call with such id.")); + addExample(new DaemonCommandExample("incall-player-start /usr/local/share/sounds/linphone/hello8000.wav", + "Status: Ok\n")); + addExample(new DaemonCommandExample("incall-player-start /usr/local/share/sounds/linphone/hello8000.wav", + "Status: Error\n" + "Reason: No active call.")); +} + +void IncallPlayerStartCommand::exec(Daemon *app, const string& args) { + LinphoneCall *call = NULL; + int cid; + const MSList *elem; + istringstream ist(args); + string filename; + + ist >> filename; + if (ist.eof() && (filename.length() == 0)) { + app->sendResponse(Response("Missing filename parameter.", Response::Error)); + return; + } + if (ist.fail()) { + app->sendResponse(Response("Incorrect filename parameter.", Response::Error)); + return; + } + + ist >> cid; + if (ist.fail()) { + elem = linphone_core_get_calls(app->getCore()); + if (elem != NULL && elem->next == NULL) { + call = (LinphoneCall*)elem->data; + } + } else { + call = app->findCall(cid); + if (call == NULL) { + app->sendResponse(Response("No call with such id.")); + return; + } + } + if (call == NULL) { + app->sendResponse(Response("No active call.")); + return; + } + LinphonePlayer *p = linphone_call_get_player(call); + + LinphonePlayerCbs *cbs=linphone_player_get_callbacks(p); + + pair *callPlayingData = (pair *)linphone_player_get_user_data(p); + if(callPlayingData) callPlayingData = new pair({ + VOIDPTR_TO_INT(linphone_call_get_user_pointer(call)), + app + }); + linphone_player_set_user_data(p, callPlayingData); + linphone_player_cbs_set_eof_reached(cbs, onEof); + linphone_player_open(p,filename.c_str()); + linphone_player_start(p); + app->sendResponse(Response()); +} + + +IncallPlayerStopCommand::IncallPlayerStopCommand() : + DaemonCommand("incall-player-stop", "incall-player-stop []","Close the opened file.\n") { + addExample(new DaemonCommandExample("incall-player-stop 1", + "Status: Error\n" + "Reason: No call with such id.")); + addExample(new DaemonCommandExample("incall-player-stop 1", + "Status: Ok\n")); + addExample(new DaemonCommandExample("incall-player-stop", + "Status: Ok\n")); + addExample(new DaemonCommandExample("incall-player-stop", + "Status: Error\n" + "Reason: No active call.")); +} + +void IncallPlayerStopCommand::exec(Daemon *app, const string& args) { + LinphoneCall *call = NULL; + int cid; + const MSList *elem; + istringstream ist(args); + ist >> cid; + if (ist.fail()) { + elem = linphone_core_get_calls(app->getCore()); + if (elem != NULL && elem->next == NULL) { + call = (LinphoneCall*)elem->data; + } + } else { + call = app->findCall(cid); + if (call == NULL) { + app->sendResponse(Response("No call with such id.")); + return; + } + } + if (call == NULL) { + app->sendResponse(Response("No active call.")); + return; + } + + LinphonePlayer *p = linphone_call_get_player(call); + + linphone_player_close(p); + app->sendResponse(Response()); + pair *callPlayingData = (pair *)linphone_player_get_user_data(p); + if(callPlayingData) delete callPlayingData; +} + +IncallPlayerPauseCommand::IncallPlayerPauseCommand() : + DaemonCommand("incall-player-pause", "incall-player-pause []", + "Pause the playing of a file.\n") { + addExample(new DaemonCommandExample("incall-player-pause 1", + "Status: Error\n" + "Reason: No call with such id.")); + addExample(new DaemonCommandExample("incall-player-pause 1", + "Status: Ok\n")); + addExample(new DaemonCommandExample("incall-player-pause", + "Status: Ok\n")); + addExample(new DaemonCommandExample("incall-player-pause", + "Status: Error\n" + "Reason: No active call.")); +} + +void IncallPlayerPauseCommand::exec(Daemon *app, const string& args) { + LinphoneCall *call = NULL; + int cid; + const MSList *elem; + istringstream ist(args); + ist >> cid; + if (ist.fail()) { + elem = linphone_core_get_calls(app->getCore()); + if (elem != NULL && elem->next == NULL) { + call = (LinphoneCall*)elem->data; + } + } else { + call = app->findCall(cid); + if (call == NULL) { + app->sendResponse(Response("No call with such id.")); + return; + } + } + if (call == NULL) { + app->sendResponse(Response("No active call.")); + return; + } + + LinphonePlayer *p = linphone_call_get_player(call); + linphone_player_pause(p); + app->sendResponse(Response()); +} + +IncallPlayerResumeCommand::IncallPlayerResumeCommand() : + DaemonCommand("incall-player-resume", "incall-player-resume []", + "Unpause the playing of a file.\n") { + addExample(new DaemonCommandExample("incall-player-resume 1", + "Status: Error\n" + "Reason: No call with such id.")); + addExample(new DaemonCommandExample("incall-player-resume 1", + "Status: Ok\n")); + addExample(new DaemonCommandExample("incall-player-resume", + "Status: Ok\n")); + addExample(new DaemonCommandExample("incall-player-resume", + "Status: Error\n" + "Reason: No active call.")); +} + +void IncallPlayerResumeCommand::exec(Daemon *app, const string& args) { + LinphoneCall *call = NULL; + int cid; + const MSList *elem; + istringstream ist(args); + ist >> cid; + if (ist.fail()) { + elem = linphone_core_get_calls(app->getCore()); + if (elem != NULL && elem->next == NULL) { + call = (LinphoneCall*)elem->data; + } + } else { + call = app->findCall(cid); + if (call == NULL) { + app->sendResponse(Response("No call with such id.")); + return; + } + } + if (call == NULL) { + app->sendResponse(Response("No active call.")); + return; + } + + LinphonePlayer *p = linphone_call_get_player(call); + linphone_player_start(p); + app->sendResponse(Response()); +} diff --git a/daemon/commands/play.h b/daemon/commands/play.h new file mode 100644 index 000000000..e8787e71b --- /dev/null +++ b/daemon/commands/play.h @@ -0,0 +1,50 @@ +/* +play-wav.h +Copyright (C) 2016 Belledonne Communications, Grenoble, France + +This library is free software; you can redistribute it and/or modify it +under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or (at +your option) any later version. + +This library is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this library; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef LINPHONE_DAEMON_COMMAND_PLAY_H_ +#define LINPHONE_DAEMON_COMMAND_PLAY_H_ + +#include "daemon.h" + +class IncallPlayerStartCommand: public DaemonCommand { +public: + IncallPlayerStartCommand(); + virtual void exec(Daemon *app, const std::string& args); +private: + static void onEof(LinphonePlayer *player); +}; + +class IncallPlayerStopCommand: public DaemonCommand { +public: + IncallPlayerStopCommand(); + virtual void exec(Daemon *app, const std::string& args); +}; + +class IncallPlayerPauseCommand: public DaemonCommand { +public: + IncallPlayerPauseCommand(); + virtual void exec(Daemon *app, const std::string& args); +}; + +class IncallPlayerResumeCommand: public DaemonCommand { +public: + IncallPlayerResumeCommand(); + virtual void exec(Daemon *app, const std::string& args); +}; +#endif // LINPHONE_DAEMON_COMMAND_PLAY_H_ diff --git a/daemon/daemon.cc b/daemon/daemon.cc index 907972976..8c99f8dac 100644 --- a/daemon/daemon.cc +++ b/daemon/daemon.cc @@ -79,6 +79,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "commands/netsim.h" #include "commands/cn.h" #include "commands/version.h" +#include "commands/play.h" #include "private.h" using namespace std; @@ -214,6 +215,15 @@ AudioStreamStatsResponse::AudioStreamStatsResponse(Daemon* daemon, AudioStream* setBody(ostr.str().c_str()); } +CallPlayingStatsResponse::CallPlayingStatsResponse(Daemon* daemon, int id) { + ostringstream ostr; + + ostr << "Event-type: call-playing-complete\n"; + ostr << "Id: " << id << "\n"; + + setBody(ostr.str().c_str()); +} + PayloadTypeResponse::PayloadTypeResponse(LinphoneCore *core, const PayloadType *payloadType, int index, const string &prefix, bool enabled_status) { ostringstream ostr; if (payloadType != NULL) { @@ -486,6 +496,10 @@ void Daemon::initCommands() { mCommands.push_back(new ConfigSetCommand()); mCommands.push_back(new NetsimCommand()); mCommands.push_back(new CNCommand()); + mCommands.push_back(new IncallPlayerStartCommand()); + mCommands.push_back(new IncallPlayerStopCommand()); + mCommands.push_back(new IncallPlayerPauseCommand()); + mCommands.push_back(new IncallPlayerResumeCommand()); mCommands.sort(compareCommands); } @@ -524,6 +538,10 @@ void Daemon::callStatsUpdated(LinphoneCall *call, const LinphoneCallStats *stats } } +void Daemon::callPlayingComplete(int id) { + mEventQueue.push(new CallPlayingStatsResponse(this, id)); +} + void Daemon::dtmfReceived(LinphoneCall *call, int dtmf) { mEventQueue.push(new DtmfResponse(this, call, dtmf)); } diff --git a/daemon/daemon.h b/daemon/daemon.h index 12a32c358..45a3ec7c8 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -160,6 +160,11 @@ public: const LinphoneCallStats *stats, bool event); }; +class CallPlayingStatsResponse: public Response { +public: + CallPlayingStatsResponse(Daemon *daemon, int id); +}; + class DtmfResponse: public Response { public: DtmfResponse(Daemon *daemon, LinphoneCall *call, int dtmf); @@ -230,7 +235,7 @@ public: void dumpCommandsHelpHtml(); void enableStatsEvents(bool enabled); void enableLSD(bool enabled); - + void callPlayingComplete(int id); void setAutoVideo( bool enabled ){ mAutoVideo = enabled; } inline bool autoVideo(){ return mAutoVideo; }