OSDN Git Service

Native Clientからのログ出力部分を作成してみた。
[nacltest/xmplayer.git] / xm_player.cc
index b9098fd..fe6d0eb 100644 (file)
 #include <ppapi/cpp/url_request_info.h>
 #include <ppapi/cpp/dev/scriptable_object_deprecated.h>
 #include <ppapi/cpp/var.h>
+#include <pthread.h>
 
 #include <cassert>
 #include <cmath>
 #include <limits>
 #include <sstream>
 #include <iostream>
+#include <list>
 
 #include "_mod.h"
 #include "geturl_handler.h"
 #include "boost/shared_ptr.hpp"
 #include "boost/format.hpp"
+#include "zlib.h"
 
 namespace {
+  const int kPthreadMutexSuccess = 0;
   // XM ファイルのロード
   const char* const kLoadXmFile = "loadXmFile";
   // XM ファイルの再生コマンド文字列
   const char* const kPlaySoundId = "playSound";
   // XM ファイルの停止コマンド文字列
   const char* const kStopSoundId = "stopSound";
-
-// システムにリクエストするサンプルカウント数
+  // メインスレッド以外のログを取得する
+  const char* const kGetLogId = "getLog";
+  //  
+  const char* const kCheckLogId = "checkLog";
+ // システムにリクエストするサンプルカウント数
 const uint32_t kSampleFrameCount = 4096u;
 // 現在サポートしているのはステレオオーディオのみである。
 const uint32_t kChannels = 2u;
 }  // namespace
 
 namespace xm_player {
-class XmPlayerInstance;
+// A small helper RAII class that implementes a scoped pthread_mutex lock.
+class ScopedMutexLock {
+ public:
+  explicit ScopedMutexLock(pthread_mutex_t* mutex) : mutex_(mutex) {
+    if (pthread_mutex_lock(mutex_) != kPthreadMutexSuccess) {
+      mutex_ = NULL;
+    }
+  }
+  ~ScopedMutexLock() {
+    if (mutex_)
+      pthread_mutex_unlock(mutex_);
+  }
+  bool is_valid() const {
+    return mutex_ != NULL;
+  }
+ private:
+  pthread_mutex_t* mutex_;  // Weak reference.
+};
+
+  class XmPlayerInstance;
  // このクラスはNaClモジュールのためのスクリプティング・インターフェースである。
 // HasMethodメソッドはXmPlayerオブジェクトのメソッドが呼び出され、実行される前にブラウザによって呼び出される。
 // (詳細はxm_player.html内のmoduleDidLoad()関数を見ること。)
@@ -94,7 +120,10 @@ class XmPlayerInstance : public pp::Instance {
  public:
   explicit XmPlayerInstance(PP_Instance instance)
       : pp::Instance(instance), scriptable_object_(NULL),
-        sample_frame_count_(kSampleFrameCount)  , mod_( MOD__Create()){}
+        sample_frame_count_(kSampleFrameCount)  , mod_( MOD__Create(this))
+  {
+    pthread_mutex_init(&mutex_, NULL);
+  }
   virtual ~XmPlayerInstance() 
   {
     MOD__Destruct(mod_);
@@ -104,6 +133,7 @@ class XmPlayerInstance : public pp::Instance {
   virtual pp::Var GetInstanceObject() {
     scriptable_object_ =
         new XmPlayerScriptableObject(*this);
+    
     return pp::Var(this, scriptable_object_);
   }
 
@@ -127,25 +157,48 @@ class XmPlayerInstance : public pp::Instance {
       if(MOD__LoadSong(mod_,&(load_data_[0]),load_data_.size()) > 0 ){
           MOD__InitPlay(mod_);
           audio_.StartPlayback();
-          pp::Var window = this->GetWindowObject();
-          // calls JavaScript function reportResult(url, result, success)
-          // defined in geturl.html.
-          pp::Var exception;
-          window.Call("reportResult", std::string("play()"), std::string("Play Start!!"), true, &exception);
+          SendLog("started.");
       } else {
-        pp::Var window = this->GetWindowObject();
-        // calls JavaScript function reportResult(url, result, success)
-        // defined in geturl.html.
-        pp::Var exception;
-        window.Call("reportResult", std::string("play()"), std::string("Load Error"), false, &exception);
+        SendLog("Load Error.");
       };
   }
   void stop()
   {
     audio_.StopPlayback();
+    SendLog("stopped.");
   }
   std::vector<char> & GetLoadData(){return load_data_;}
+  void WriteLog(const char * log)
+  {  
+      ScopedMutexLock lock(&mutex_);
+      log_.push_back(log);
+  }
+
+  bool CheckLog()
+  {
+    return !log_.empty();
+  }
+
+  std::string GetLog()
+  {
+    if(log_.empty())
+    {
+        return "";
+    }
+    std::string ret(log_.front());
+    {
+      ScopedMutexLock lock(&mutex_);
+      log_.pop_front();
+    }
+    return ret;
+  };
 
+  void SendLog(const std::string& log)
+  {
+    pp::Var window(GetWindowObject());
+    pp::Var exception;
+    window.Call("reportLog",log, &exception);
+  }
  private:
   static void XmPlayerCallback(void* samples, size_t buffer_size, void* data) {
     XmPlayerInstance* xm_player_instance =
@@ -167,6 +220,8 @@ class XmPlayerInstance : public pp::Instance {
  // MOD構造体へのポインタ
   ::MOD * mod_;
   std::vector<char> load_data_;
+  std::list<std::string> log_;
+  pthread_mutex_t mutex_;
 };
 
 // The Module class.  The browser calls the CreateInstance() method to create
@@ -197,14 +252,17 @@ pp::Var XmPlayerScriptableObject::Call(const pp::Var& method,
   } else if(method_name ==  kLoadXmFile ){
    if ((args.size() >= 1) && args[0].is_string()) {
       std::string url = args[0].AsString();
-      printf("GetURLScriptableObject::Call('%s'', '%s'')\n",
-             method_name.c_str(),
-             url.c_str());
-      fflush(stdout);
+      player_.SendLog((boost::format("GetURLScriptableObject::Call('%s'', '%s'')\n") %
+             method_name % 
+             url).str());
     return pp::Var(LoadXmFile(url));
    } else {
      *exception = std::string("") + method_name;
    }
+  } else  if(method_name == kGetLogId) {
+    return pp::Var(player_.GetLog());
+  } else if(method_name == kCheckLogId) {
+    return pp::Var(player_.CheckLog());
   } else {
     *exception = std::string("No method named ") + method_name;
   }
@@ -218,7 +276,9 @@ bool XmPlayerScriptableObject::HasMethod(const pp::Var& method,
   }
   const std::string method_name = method.AsString();
   const bool has_method = method_name == kPlaySoundId ||
-      method_name == kStopSoundId || method_name == kLoadXmFile;
+      method_name == kStopSoundId || method_name == kLoadXmFile ||
+      method_name == kGetLogId || method_name == kCheckLogId 
+      ;
   return has_method;
 }
 
@@ -311,6 +371,24 @@ pp::Var XmPlayerScriptableObject::GetProperty(const pp::Var& property,
   }
 }  // namespace xm_player
 
+void LogMsg (void* instance,const char* format,...)
+{
+  va_list ap;
+  va_start(ap,format);
+  char buf[4096];
+  vsnprintf(buf,sizeof(buf),format,ap);
+  va_end(ap);
+
+  //pp::Instance * inst = pp::Module::Get()->InstanceForPPInstance(instance);
+ xm_player::XmPlayerInstance * inst = reinterpret_cast<xm_player::XmPlayerInstance*>(instance);
+ inst->WriteLog(buf);
+ // pp::Var window(inst->GetWindowObject());
+  //window.is_int();
+  //pp::Var exception;
+  //window.Call("reportLog",std::string(buf), &exception);
+};
+
+
 // Factory function called by the browser when the module is first loaded.
 // The browser keeps a singleton of this module.  It calls the
 // CreateInstance() method on the object you return to make instances.  There
@@ -321,3 +399,5 @@ Module* CreateModule() {
   return new xm_player::XmPlayerModule();
 }
 }  // namespace pp
+
+