tizen beta release
[framework/web/wrt-plugins-common.git] / src / modules / tizen / MMPlayer / MMPlayer.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 #include "MMPlayer.h"
17 #include <mmf/mm.h>
18 #include <mm_player.h>
19 #include <dpl/log/log.h>
20 #include <Commons/Exception.h>
21
22
23 namespace WrtDeviceApis {
24 namespace MMPlayer {
25
26 using namespace Api;
27
28 MMPlayer::MMPlayer() :
29     Commons::EventListener<EventOnEOS>(Commons::ThreadEnum::NULL_THREAD),
30     m_player(0),
31     m_currentState(STATE_UNDEFINED),
32     m_repeatTimes(0)
33 {
34     Try {
35         init();
36     } Catch(Commons::Exception) {
37         LogError("Unknown exception while constructing MMPlayer");
38     }
39 }
40
41 MMPlayer::~MMPlayer()
42 {
43     LogInfo("Enter");
44     finalize();
45 }
46
47 MMHandleType MMPlayer::getHandler() const
48 {
49     return m_player;
50 }
51
52 void MMPlayer::setEmitter(const EventOnStateChangeEmitterPtr& emitter)
53 {
54     LogDebug("Enter");
55     DPL::Mutex::ScopedLock lock(&m_emitterMtx);
56     m_onStateChangeEmitter = emitter;
57 }
58
59 EventOnStateChangeEmitterPtr MMPlayer::getEmitter()
60 {
61     DPL::Mutex::ScopedLock lock(&m_emitterMtx);
62     return m_onStateChangeEmitter;
63 }
64
65 void MMPlayer::clearEmitter()
66 {
67     LogDebug("Enter");
68     DPL::Mutex::ScopedLock lock(&m_emitterMtx);
69     m_onStateChangeEmitter.Reset();
70 }
71
72 int MMPlayer::onStateChange(int message,
73         void *param,
74         void* data)
75 {
76     LogInfo("Enter");
77     static DPL::Mutex playerMtx;
78     MMPlayer *this_ = static_cast<MMPlayer*>(data);
79     if (this_) {
80         EventOnStateChangePtr event(new EventOnStateChange());
81         { //Separated block to avoid deadlock when this_->m_emitterMtx will be locked
82             DPL::Mutex::ScopedLock lock(&playerMtx);
83             switch (message) {
84             case MM_MESSAGE_ERROR:
85             {
86                 MMMessageParamType* type =
87                     static_cast<MMMessageParamType*>(param);
88                 if (type && (MM_MSG_UNION_CODE == type->union_type)) {
89                     LogError(
90                         "Error from platform, code: " << std::hex <<
91                         type->code);
92                 }
93                 event->setPlayerState(EventOnStateChange::BEGIN);
94                 break;
95             }
96
97             case MM_MESSAGE_BEGIN_OF_STREAM:
98                 LogInfo("Begin of stream");
99                 event->setPlayerState(EventOnStateChange::PLAYING);
100                 break;
101
102             case MM_MESSAGE_END_OF_STREAM:
103                 LogInfo("End of stream");
104                 event->setPlayerState(EventOnStateChange::COMPLETED);
105
106                 // mm_player_stop should be executed outside the callback
107                 {
108                     EventOnEOSPtr eventEOS(new EventOnEOS());
109                     if (this_->m_onEOSEmitter) {
110                         this_->m_onEOSEmitter->emit(eventEOS);
111                     } else {
112                         LogError("EOS emitter not set");
113                     }
114                 }
115                 break;
116
117             case MM_MESSAGE_STATE_INTERRUPTED:
118                 // since platform reports always param->union_type == 0, only what can be done is to use field code
119                 // and pray it won't be changed right before demo
120             {
121                 MMMessageParamType* type =
122                     static_cast<MMMessageParamType*>(param);
123                 LogInfo("Player callback message: " << std::hex << message);
124                 if (type && (MM_MSG_UNION_CODE == type->union_type)) {
125                     LogError("Code: " << std::hex << type->code);
126                     if (MM_PLAYER_STATE_PAUSED == type->code) {
127                         LogInfo("Sending pause event");
128                         event->setPlayerState(EventOnStateChange::PAUSED);
129                     } else {
130                         return 0;
131                     }
132                 }
133             }
134             break;
135
136             default:
137                 LogInfo("Player callback message: " << std::hex << message);
138                 MMMessageParamType* type =
139                     static_cast<MMMessageParamType*>(param);
140                 if (type && (MM_MSG_UNION_CODE == type->union_type)) {
141                     LogInfo("Code: " << type->code);
142                 }
143                 return 0;
144             }
145         }
146
147         DPL::Mutex::ScopedLock lock(&this_->m_emitterMtx);
148         if (this_->m_onStateChangeEmitter) {
149             this_->m_onStateChangeEmitter->emit(event);
150         }
151         return 0;
152     }
153     return -1;
154 }
155
156 void MMPlayer::init()
157 {
158     LogDebug("Enter");
159     int err = mm_player_create(&m_player);
160     if (MM_ERROR_NONE != err || !m_player) {
161         LogError("Can't create player");
162         Throw(Commons::PlatformException);
163     }
164
165     err = mm_player_set_message_callback(m_player,
166                                          MMPlayer::onStateChange,
167                                          this);
168     if (MM_ERROR_NONE != err) {
169         LogDebug("Can't set player's callback. Error code: " << std::hex << err);
170         mm_player_destroy(m_player);
171         ThrowMsg(Commons::PlatformException, "Can't set player's callback.");
172     }
173     //Set emmiter for EOS event
174     m_onEOSEmitter.Reset(new EventOnEOSEmitter());
175     m_onEOSEmitter->setListener(this);
176 }
177
178 void MMPlayer::finalize()
179 {
180     LogDebug("Enter");
181     //if the music is playing, stop music.
182     if (MM_PLAYER_STATE_PLAYING == getState()) {
183         LogInfo("Sending stop request");
184         int err = mm_player_stop(m_player);
185         if (MM_ERROR_NONE != err) {
186             LogError("Can't stop player. Error code: " << std::hex << err);
187         }
188     }
189
190     int err = mm_player_set_message_callback(m_player, NULL, NULL);
191     if (MM_ERROR_NONE != err) {
192         LogDebug("Can't set player's callback. Error code: " << std::hex << err);
193     }
194     err = mm_player_destroy(m_player);
195     if (MM_ERROR_NONE != err) {
196         LogError(
197             "There were some problems during player destruction. Error code: "
198             << std::hex << err);
199     }
200 }
201
202 MMPlayerStateType MMPlayer::getState() const
203 {
204     MMPlayerStateType state;
205     int err = mm_player_get_state(m_player, &state);
206     if (MM_ERROR_NONE != err) {
207         LogError("Can't get player status. Error code: " << std::hex << err);
208         ThrowMsg(Commons::PlatformException, "Can't get player status.");
209     }
210     LogInfo("Current player state: " << static_cast<int>(state));
211     return state;
212 }
213
214 void MMPlayer::onAnswerReceived(const EventOnEOSPtr& /*event*/)
215 {
216     LogInfo("Enter");
217     int err = mm_player_stop(m_player);
218     if (MM_ERROR_NONE != err) {
219         LogError("Can't stop player. Error code: " << std::hex << err);
220     }
221     LogInfo("Repeat " << m_repeatTimes << " more time" <<
222             ((m_repeatTimes == 1) ? "" : "s"));
223     if (m_repeatTimes > 0) {
224         --m_repeatTimes;
225         int err = mm_player_start(m_player);
226         if (MM_ERROR_NONE != err) {
227             LogError("Can't start play. Error code: " << std::hex << err);
228         }
229     }
230 }
231
232 unsigned int MMPlayer::getRepeatTimes() const
233 {
234     return m_repeatTimes;
235 }
236
237 void MMPlayer::setRepeatTimes(unsigned int count)
238 {
239     m_repeatTimes = count;
240 }
241
242 }
243 }