OSDN Git Service

jQueryのアップデートに伴う変更。
[nacltest/xmplayer.git] / xm_player.cc
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.
4 #include <stdio.h>
5
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>
14 #include <pthread.h>
15
16 #include <cassert>
17 #include <cmath>
18 #include <limits>
19 #include <sstream>
20 #include <iostream>
21 #include <list>
22 #include "boost/shared_ptr.hpp"
23 #include "boost/format.hpp"
24
25 #include "_mod.h"
26 #include "geturl_handler.h"
27 //#include "zlib.h"
28
29 namespace {
30   const int kPthreadMutexSuccess = 0;
31   // XM ファイルのロード
32   const char* const kLoadXmFile = "loadXmFile";
33   // XM ファイルの再生コマンド文字列
34   const char* const kPlaySoundId = "playSound";
35   // XM ファイルの停止コマンド文字列
36   const char* const kStopSoundId = "stopSound";
37   // メインスレッド以外のログを取得する
38   const char* const kGetLogId = "getLog";
39  //
40   const char* const kCheckLogId = "checkLog";
41   const char * const kRecievedBytesId = "receivedBytes";
42   const char * const kTotalBytesId = "totalBytes";
43
44  // システムにリクエストするサンプルカウント数
45 const uint32_t kSampleFrameCount = 4096u;
46 // 現在サポートしているのはステレオオーディオのみである。
47 const uint32_t kChannels = 2u;
48 }  // namespace
49
50 namespace xm_player {
51 // A small helper RAII class that implementes a scoped pthread_mutex lock.
52 class ScopedMutexLock {
53  public:
54   explicit ScopedMutexLock(pthread_mutex_t* mutex) : mutex_(mutex) {
55     if (pthread_mutex_lock(mutex_) != kPthreadMutexSuccess) {
56       mutex_ = NULL;
57     }
58   }
59   ~ScopedMutexLock() {
60     if (mutex_)
61       pthread_mutex_unlock(mutex_);
62   }
63   bool is_valid() const {
64     return mutex_ != NULL;
65   }
66  private:
67   pthread_mutex_t* mutex_;  // Weak reference.
68 };
69
70 class XmPlayerInstance : public pp::Instance {
71  public:
72   explicit XmPlayerInstance(PP_Instance instance)
73       : pp::Instance(instance)/*, scriptable_object_(NULL)*/,
74         sample_frame_count_(kSampleFrameCount)  , mod_( MOD__Create(this))
75   {
76     pthread_mutexattr_init(&mutex_attr_);
77     pthread_mutexattr_settype(&mutex_attr_,PTHREAD_MUTEX_RECURSIVE);
78     pthread_mutex_init(&mutex_, NULL );
79   }
80
81   virtual ~XmPlayerInstance() 
82   {
83     pthread_mutex_destroy(&mutex_);
84     pthread_mutexattr_destroy(&mutex_attr_);
85     MOD__Destruct(mod_);
86   }
87
88   virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
89
90     // Ask the device for an appropriate sample count size.
91     sample_frame_count_ =
92         pp::AudioConfig::RecommendSampleFrameCount(PP_AUDIOSAMPLERATE_44100,
93                                                    kSampleFrameCount);
94     audio_ = pp::Audio(
95         this,
96         pp::AudioConfig(this,
97                         PP_AUDIOSAMPLERATE_44100,
98                         sample_frame_count_),
99         XmPlayerCallback, this);
100     return true;
101   }
102
103   void play()
104   {
105       if(MOD__LoadSong(mod_,&(load_data_[0]),load_data_.size()) > 0 ){
106           MOD__InitPlay(mod_);
107           audio_.StartPlayback();
108           SendLog("started.");
109       } else {
110         SendLog("Load Error.");
111       };
112   }
113
114   void stop()
115   {
116     audio_.StopPlayback();
117     SendLog("stopped.");
118   }
119   std::vector<char> & GetLoadData(){return load_data_;}
120   void WriteLog(const char * log)
121   {  
122     PostMessage(log);
123     //ScopedMutexLock lock(&mutex_);
124     //  log_.push_back(log);
125   }
126
127   bool CheckLog()
128   {
129     return !log_.empty();
130   }
131
132   std::string GetLog()
133   {
134     if(log_.empty())
135     {
136         return "";
137     }
138     std::string ret(log_.front());
139     {
140      ScopedMutexLock lock(&mutex_);
141       log_.pop_front();
142     }
143     return ret;
144   };
145
146   void SendLog(const std::string& log)
147   {
148     PostMessage(std::string("reportLog:") + log);
149   }
150
151   virtual void HandleMessage(const pp::Var& message)
152   {
153     SendLog("HandleMessage");
154     const std::string& mes(message.AsString());
155     if(mes.find(kLoadXmFile) == 0)
156     {
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);
160          LoadXmFile(url);
161       }
162     }
163
164     if(mes == kPlaySoundId)
165     {
166       play();
167     }
168
169     if(mes == kStopSoundId)
170     {
171       stop();
172     }
173
174
175   };
176
177   bool LoadXmFile(const std::string& url)
178   {
179      SendLog("XmPlayerInstance::LoadXmFile()::CreateGetURLHandler");
180     //MODファイルのロード
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);
185       if(!handler_)
186       {
187           return false;
188       }
189     } else {
190       return false;
191     }
192     SendLog("XmPlayerInstance::LoadXmFile()::handler_->Start()");
193     if(!handler_->Start()){
194       return false;
195     };
196     SendLog("XmPlayerInstance::LoadXmFile() Exit");
197     return true;
198    }
199   }
200
201   int32_t GetReceivedBytes()
202   {
203     if(!handler_) return 0;
204      return  handler_->GetReceivedBytes();
205   }
206
207   int32_t GetTotalBytes()
208   {
209     if(!handler_) return 0;
210     return  handler_->GetTotalBytes();
211   }
212
213  private:
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);
218
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)));
223   }
224   // Audio resource. Allocated in Init()
225   pp::Audio audio_;
226
227   //XmPlayerScriptableObject* scriptable_object_;
228
229   // The count of sample frames per channel in an audio buffer.
230   uint32_t sample_frame_count_;
231  // MOD構造体へのポインタ
232   ::MOD * mod_;
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_; 
238 };
239
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 {
244  public:
245   XmPlayerModule() : pp::Module() {}
246   ~XmPlayerModule() {}
247
248   // Create and return a HelloWorldInstance object.
249   virtual pp::Instance* CreateInstance(PP_Instance instance) {
250     return new XmPlayerInstance(instance);
251   }
252 };
253
254
255 }  // namespace xm_player
256
257
258 void LogMsg (void* instance,const char* format,...)
259 {
260   va_list ap;
261   va_start(ap,format);
262   char buf[4096];
263   vsnprintf(buf,sizeof(buf),format,ap);
264   va_end(ap);
265
266   //pp::Instance * inst = pp::Module::Get()->InstanceForPPInstance(instance);
267  xm_player::XmPlayerInstance * inst = static_cast<xm_player::XmPlayerInstance*>(instance);
268  inst->SendLog(buf);
269  
270  //printf(buf);
271  //inst->WriteLog(buf);
272  // pp::Var window(inst->GetWindowObject());
273   //window.is_int();
274   //pp::Var exception;
275   //window.Call("reportLog",std::string(buf), &exception);
276 };
277
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.
283 namespace pp {
284 Module* CreateModule() {
285   return new xm_player::XmPlayerModule();
286 }
287 }  // namespace pp
288
289