1 // Copyright 2010 The Native Client Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can
3 // be found in the LICENSE file.
6 #include <ppapi/cpp/audio.h>
7 #include <ppapi/cpp/instance.h>
8 #include <ppapi/cpp/module.h>
9 #include <ppapi/cpp/completion_callback.h>
10 #include <ppapi/cpp/url_loader.h>
11 #include <ppapi/cpp/url_request_info.h>
12 #include <ppapi/cpp/dev/scriptable_object_deprecated.h>
13 #include <ppapi/cpp/var.h>
22 #include "boost/shared_ptr.hpp"
23 #include "boost/format.hpp"
26 #include "geturl_handler.h"
30 const int kPthreadMutexSuccess = 0;
32 const char* const kLoadXmFile = "loadXmFile";
34 const char* const kPlaySoundId = "playSound";
36 const char* const kStopSoundId = "stopSound";
38 const char* const kGetLogId = "getLog";
40 const char* const kCheckLogId = "checkLog";
41 const char * const kRecievedBytesId = "receivedBytes";
42 const char * const kTotalBytesId = "totalBytes";
44 // システムにリクエストするサンプルカウント数
45 const uint32_t kSampleFrameCount = 4096u;
46 // 現在サポートしているのはステレオオーディオのみである。
47 const uint32_t kChannels = 2u;
51 // A small helper RAII class that implementes a scoped pthread_mutex lock.
52 class ScopedMutexLock {
54 explicit ScopedMutexLock(pthread_mutex_t* mutex) : mutex_(mutex) {
55 if (pthread_mutex_lock(mutex_) != kPthreadMutexSuccess) {
61 pthread_mutex_unlock(mutex_);
63 bool is_valid() const {
64 return mutex_ != NULL;
67 pthread_mutex_t* mutex_; // Weak reference.
70 class XmPlayerInstance : public pp::Instance {
72 explicit XmPlayerInstance(PP_Instance instance)
73 : pp::Instance(instance)/*, scriptable_object_(NULL)*/,
74 sample_frame_count_(kSampleFrameCount) , mod_( MOD__Create(this))
76 pthread_mutexattr_init(&mutex_attr_);
77 pthread_mutexattr_settype(&mutex_attr_,PTHREAD_MUTEX_RECURSIVE);
78 pthread_mutex_init(&mutex_, NULL );
81 virtual ~XmPlayerInstance()
83 pthread_mutex_destroy(&mutex_);
84 pthread_mutexattr_destroy(&mutex_attr_);
88 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
90 // Ask the device for an appropriate sample count size.
92 pp::AudioConfig::RecommendSampleFrameCount(PP_AUDIOSAMPLERATE_44100,
97 PP_AUDIOSAMPLERATE_44100,
99 XmPlayerCallback, this);
105 if(MOD__LoadSong(mod_,&(load_data_[0]),load_data_.size()) > 0 ){
107 audio_.StartPlayback();
110 SendLog("Load Error.");
116 audio_.StopPlayback();
119 std::vector<char> & GetLoadData(){return load_data_;}
120 void WriteLog(const char * log)
123 //ScopedMutexLock lock(&mutex_);
124 // log_.push_back(log);
129 return !log_.empty();
138 std::string ret(log_.front());
140 ScopedMutexLock lock(&mutex_);
146 void SendLog(const std::string& log)
148 PostMessage(std::string("reportLog:") + log);
151 virtual void HandleMessage(const pp::Var& message)
153 SendLog("HandleMessage");
154 const std::string& mes(message.AsString());
155 if(mes.find(kLoadXmFile) == 0)
157 size_t sep_pos = mes.find_first_of(':');
158 if (sep_pos != std::string::npos) {
159 std::string url = mes.substr(sep_pos + 1);
164 if(mes == kPlaySoundId)
169 if(mes == kStopSoundId)
177 bool LoadXmFile(const std::string& url)
179 SendLog("XmPlayerInstance::LoadXmFile()::CreateGetURLHandler");
181 { //GetURLHandler *handler_ = 0;
182 if(!handler_ || handler_->GetStatus() == GetURLHandler::end){
183 handler_.reset(GetURLHandler::Create(this,url,GetLoadData()));
184 // handler_= GetURLHandler::Create(this,url,GetLoadData(),jsFuncName);
192 SendLog("XmPlayerInstance::LoadXmFile()::handler_->Start()");
193 if(!handler_->Start()){
196 SendLog("XmPlayerInstance::LoadXmFile() Exit");
201 int32_t GetReceivedBytes()
203 if(!handler_) return 0;
204 return handler_->GetReceivedBytes();
207 int32_t GetTotalBytes()
209 if(!handler_) return 0;
210 return handler_->GetTotalBytes();
214 static void XmPlayerCallback(void* samples, size_t buffer_size, void* data) {
215 XmPlayerInstance* xm_player_instance =
216 reinterpret_cast<XmPlayerInstance*>(data);
217 //int16_t* buff = reinterpret_cast<int16_t*>(samples);
219 // Make sure we can't write outside the buffer.
220 //assert(buffer_size >= (sizeof(*buff) * kChannels *
221 // xm_player_instance->sample_frame_count_));
222 MOD__PlaySong(xm_player_instance->mod_,reinterpret_cast<U32*>(samples),buffer_size / (sizeof(U32)));
224 // Audio resource. Allocated in Init()
227 //XmPlayerScriptableObject* scriptable_object_;
229 // The count of sample frames per channel in an audio buffer.
230 uint32_t sample_frame_count_;
233 std::vector<char> load_data_;
234 std::list<std::string> log_;
235 pthread_mutex_t mutex_;
236 pthread_mutexattr_t mutex_attr_;
237 boost::shared_ptr<GetURLHandler> handler_;
240 // The Module class. The browser calls the CreateInstance() method to create
241 // an instance of you NaCl module on the web page. The browser creates a new
242 // instance for each <embed> tag with type="application/x-ppapi-nacl-srpc".
243 class XmPlayerModule : public pp::Module {
245 XmPlayerModule() : pp::Module() {}
248 // Create and return a HelloWorldInstance object.
249 virtual pp::Instance* CreateInstance(PP_Instance instance) {
250 return new XmPlayerInstance(instance);
255 } // namespace xm_player
258 void LogMsg (void* instance,const char* format,...)
263 vsnprintf(buf,sizeof(buf),format,ap);
266 //pp::Instance * inst = pp::Module::Get()->InstanceForPPInstance(instance);
267 xm_player::XmPlayerInstance * inst = static_cast<xm_player::XmPlayerInstance*>(instance);
271 //inst->WriteLog(buf);
272 // pp::Var window(inst->GetWindowObject());
275 //window.Call("reportLog",std::string(buf), &exception);
278 // Factory function called by the browser when the module is first loaded.
279 // The browser keeps a singleton of this module. It calls the
280 // CreateInstance() method on the object you return to make instances. There
281 // is one instance per <embed> tag on the page. This is the main binding
282 // point for your NaCl module with the browser.
284 Module* CreateModule() {
285 return new xm_player::XmPlayerModule();