Index: ppapi/examples/extensions/extensions.cc |
diff --git a/ppapi/examples/extensions/extensions.cc b/ppapi/examples/extensions/extensions.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..659d1d8096e3e106d3d85db54a1fa5961947fa35 |
--- /dev/null |
+++ b/ppapi/examples/extensions/extensions.cc |
@@ -0,0 +1,374 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "ppapi/c/dev/ppb_alarms_dev.h" |
+#include "ppapi/c/dev/ppb_memory_dev.h" |
+#include "ppapi/c/ppb_console.h" |
+#include "ppapi/c/ppb_input_event.h" |
+#include "ppapi/c/ppb_var.h" |
+#include "ppapi/cpp/dev/alarms_dev.h" |
+#include "ppapi/cpp/graphics_2d.h" |
+#include "ppapi/cpp/image_data.h" |
+#include "ppapi/cpp/input_event.h" |
+#include "ppapi/cpp/instance.h" |
+#include "ppapi/cpp/logging.h" |
+#include "ppapi/cpp/module.h" |
+#include "ppapi/cpp/rect.h" |
+#include "ppapi/cpp/var.h" |
+#include "ppapi/utility/completion_callback_factory.h" |
+ |
+using namespace pp; |
+ |
+const PPB_Console* console = NULL; |
+const PPB_Alarms_Dev* alarms_interface = NULL; |
+const PPB_Var* var_interface = NULL; |
+ |
+class MyInstance : public Instance { |
+ public: |
+ explicit MyInstance(PP_Instance instance) |
+ : Instance(instance), |
+ width_(0), |
+ height_(0), |
+ pending_paint_(false), |
+ waiting_for_flush_completion_(false), |
+ callback_factory_(this), |
+ alarms_(InstanceHandle(instance)) { |
+ } |
+ virtual ~MyInstance() { |
+ } |
+ |
+ virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) { |
+ console = static_cast<const PPB_Console*>( |
+ Module::Get()->GetBrowserInterface(PPB_CONSOLE_INTERFACE)); |
+ if (!console) |
+ return false; |
+ |
+ alarms_interface = static_cast<const PPB_Alarms_Dev*>( |
+ Module::Get()->GetBrowserInterface(PPB_ALARMS_DEV_INTERFACE)); |
+ if (!alarms_interface) |
+ return false; |
+ |
+ var_interface = static_cast<const PPB_Var*>( |
+ Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE)); |
+ if (!var_interface) |
+ return false; |
+ |
+ RequestInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD); |
+ return true; |
+ } |
+ |
+ virtual bool HandleInputEvent(const InputEvent& event) { |
+ switch (event.GetType()) { |
+ case PP_INPUTEVENT_TYPE_KEYDOWN: { |
+ KeyboardInputEvent key_event(event); |
+ switch (key_event.GetKeyCode()) { |
+ ///////////////////////////////////////////////////////////////////// |
+ // Exercise the C interface PPB_Alarms_Dev. |
+ ///////////////////////////////////////////////////////////////////// |
+ case '1' : { // Create() |
+ PP_Var name = var_interface->VarFromUtf8("alarms2", |
+ strlen("alarms2")); |
+ PP_Alarms_AlarmCreateInfo_Dev create_info = { |
+ {0, PP_FALSE}, |
+ {1, PP_TRUE}, |
+ {1, PP_TRUE} |
+ }; |
+ |
+ alarms_interface->Create(pp_instance(), name, &create_info); |
+ |
+ var_interface->Release(name); |
+ break; |
+ } |
+ case '2' : { // Get() |
+ PP_Var name = var_interface->VarFromUtf8("alarms2", |
+ strlen("alarms2")); |
+ PP_Alarms_Alarm_Dev* alarm = new PP_Alarms_Alarm_Dev(); |
+ |
+ // GetCallbackInC() will delete |alarm|. |
+ // NOTE: |callback_factory_| should not be used in this case. |
+ // Otherwise, |alarm| is leaked if this object is destroyed before |
+ // the callback is executed. |
+ PP_CompletionCallback callback = PP_MakeCompletionCallback( |
+ &MyInstance::GetCallbackInC, alarm); |
+ |
+ int32_t result = alarms_interface->Get(pp_instance(), name, alarm, |
+ callback); |
+ PP_DCHECK(result == PP_OK_COMPLETIONPENDING); |
+ var_interface->Release(name); |
+ break; |
+ } |
+ case '3' : { // GetAll() |
+ PP_Alarms_Alarm_Array_Dev* alarms = new PP_Alarms_Alarm_Array_Dev(); |
+ PP_ArrayOutput array_allocator = |
+ { &MyInstance::GetDataBuffer, NULL }; |
+ |
+ // GetAllCallbackInC() will delete |alarms|. |
+ // NOTE: |callback_factory_| should not be used in this case. |
+ // Otherwise, |alarms| is leaked if this object is destroyed before |
+ // the callback is executed. |
+ PP_CompletionCallback callback = PP_MakeCompletionCallback( |
+ &MyInstance::GetAllCallbackInC, alarms); |
+ |
+ int32_t result = alarms_interface->GetAll( |
+ pp_instance(), alarms, array_allocator, callback); |
+ PP_DCHECK(result == PP_OK_COMPLETIONPENDING); |
+ break; |
+ } |
+ case '4' : { // Clear() |
+ PP_Var name = var_interface->VarFromUtf8("alarms2", |
+ strlen("alarms2")); |
+ alarms_interface->Clear(pp_instance(), name); |
+ var_interface->Release(name); |
+ break; |
+ } |
+ case '5' : { // Register event |
+ break; |
+ } |
+ case '6' : { // Unregister event |
+ break; |
+ } |
+ |
+ ////////////////////////////////////////////////////////////////////// |
+ // Exercise the C++ interface pp::alarms::Alarms_Dev. |
+ ////////////////////////////////////////////////////////////////////// |
+ case 'A' : { // Create() |
+ std::string name("alarm1"); |
+ |
+ alarms::AlarmCreateInfo_Dev create_info; |
+ create_info.set_delay_in_minutes(1); |
+ create_info.set_period_in_minutes(1); |
+ |
+ alarms_.Create(name, create_info); |
+ break; |
+ } |
+ case 'B' : { // Get() |
+ std::string name("alarm1"); |
+ |
+ CompletionCallbackWithOutput<alarms::Alarm_Dev> |
+ callback = callback_factory_.NewCallbackWithOutput( |
+ &MyInstance::GetCallbackInCpp); |
+ |
+ int32_t result = alarms_.Get(name, callback); |
+ PP_DCHECK(result == PP_OK_COMPLETIONPENDING); |
+ break; |
+ } |
+ case 'C' : { // GetAll() |
+ CompletionCallbackWithOutput<Array<alarms::Alarm_Dev> > |
+ callback = callback_factory_.NewCallbackWithOutput( |
+ &MyInstance::GetAllCallbackInCpp); |
+ |
+ int32_t result = alarms_.GetAll(callback); |
+ PP_DCHECK(result == PP_OK_COMPLETIONPENDING); |
+ break; |
+ } |
+ case 'D' : { // Clear() |
+ std::string name("alarm1"); |
+ alarms_.Clear(name); |
+ break; |
+ } |
+ case 'E' : { // Register event |
+ break; |
+ } |
+ case 'F' : { // Unregister event |
+ break; |
+ } |
+ default: |
+ break; |
+ } |
+ return true; |
+ } |
+ default: |
+ return false; |
+ } |
+ } |
+ |
+ virtual void DidChangeView(const Rect& position, const Rect& clip) { |
+ if (position.size().width() == width_ && |
+ position.size().height() == height_) |
+ return; // We don't care about the position, only the size. |
+ |
+ width_ = position.size().width(); |
+ height_ = position.size().height(); |
+ |
+ device_context_ = Graphics2D(this, Size(width_, height_), false); |
+ if (!BindGraphics(device_context_)) |
+ return; |
+ |
+ Paint(); |
+ } |
+ |
+ private: |
+ ////////////////////////////////////////////////////////////////////////////// |
+ // Exercise the C interface. |
+ ////////////////////////////////////////////////////////////////////////////// |
+ static void DestroyAlarmStruct(PP_Alarms_Alarm_Dev* alarm) { |
+ var_interface->Release(alarm->name); |
+ alarm->name = PP_MakeUndefined(); |
+ } |
+ |
+ static void* GetDataBuffer(void* user_data, uint32_t count, uint32_t size) { |
+ if (size != sizeof(PP_Alarms_Alarm_Dev)) { |
+ PP_NOTREACHED(); |
+ return NULL; |
+ } |
+ |
+ if (count == 0) |
+ return NULL; |
+ |
+ // We don't have to remember the pointer. The browser is responsible to |
+ // update |elements| and |size| in PP_Alarms_Alarm_Array_Dev. |
+ return calloc(count, size); |
+ } |
+ |
+ static void DestroyAlarmArrayStruct(PP_Alarms_Alarm_Array_Dev* alarms) { |
+ for (uint32_t i = 0; i < alarms->size; ++i) |
+ DestroyAlarmStruct(alarms->elements + i); |
+ |
+ free(alarms->elements); |
+ alarms->elements = NULL; |
+ alarms->size = 0; |
+ } |
+ |
+ static void GetAllCallbackInC(void* user_data, int32_t result) { |
+ PP_Alarms_Alarm_Array_Dev* alarms = |
+ static_cast<PP_Alarms_Alarm_Array_Dev*>(user_data); |
+ if (result == PP_OK) { |
+ for (uint32_t i = 0; i < alarms->size; ++i) { |
+ PP_Alarms_Alarm_Dev& element = alarms->elements[i]; |
+ // The following fields are available. |
+ element.name; |
+ element.scheduled_time; |
+ if (element.period_in_minutes.is_set) |
+ element.period_in_minutes.value; |
+ } |
+ } |
+ DestroyAlarmArrayStruct(alarms); |
+ delete alarms; |
+ } |
+ |
+ static void GetCallbackInC(void* user_data, int32_t result) { |
+ PP_Alarms_Alarm_Dev* alarm = static_cast<PP_Alarms_Alarm_Dev*>(user_data); |
+ if (result == PP_OK) { |
+ // The following fields are available. |
+ alarm->name; |
+ alarm->scheduled_time; |
+ if (alarm->period_in_minutes.is_set) |
+ alarm->period_in_minutes.value; |
+ } |
+ DestroyAlarmStruct(alarm); |
+ delete alarm; |
+ } |
+ |
+ ////////////////////////////////////////////////////////////////////////////// |
+ // Exercise the C++ interface. |
+ ////////////////////////////////////////////////////////////////////////////// |
+ void GetAllCallbackInCpp(int32_t result, |
+ Array<alarms::Alarm_Dev>& alarms) { |
+ if (result == PP_OK) { |
+ for (size_t i = 0; i < alarms.size(); ++i) { |
+ // The following fields are available. |
+ alarms::Alarm_Dev& alarm = alarms[i]; |
+ alarm.name(); |
+ alarm.scheduled_time(); |
+ if (alarm.is_period_in_minutes_set()) |
+ alarm.period_in_minutes(); |
+ } |
+ } |
+ } |
+ |
+ void GetCallbackInCpp(int32_t result, alarms::Alarm_Dev& alarm) { |
+ if (result == PP_OK) { |
+ // The following fields are available. |
+ alarm.name(); |
+ alarm.scheduled_time(); |
+ if (alarm.is_period_in_minutes_set()) |
+ alarm.period_in_minutes(); |
+ } |
+ } |
+ |
+ void DidFlush(int32_t result) { |
+ waiting_for_flush_completion_ = false; |
+ if (pending_paint_) { |
+ pending_paint_ = false; |
+ Paint(); |
+ } |
+ } |
+ |
+ void Paint() { |
+ if (waiting_for_flush_completion_) { |
+ pending_paint_ = true; |
+ return; |
+ } |
+ |
+ ImageData image = PaintImage(width_, height_); |
+ if (!image.is_null()) { |
+ device_context_.ReplaceContents(&image); |
+ waiting_for_flush_completion_ = true; |
+ device_context_.Flush( |
+ callback_factory_.NewCallback(&MyInstance::DidFlush)); |
+ } |
+ } |
+ |
+ ImageData PaintImage(int width, int height) { |
+ ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, |
+ Size(width, height), false); |
+ if (image.is_null()) |
+ return image; |
+ |
+ for (int y = 0; y < image.size().height(); ++y) { |
+ for (int x = 0; x < image.size().width(); ++x) { |
+ *image.GetAddr32(Point(x, y)) = 0xfff0f0f0; |
+ } |
+ } |
+ |
+ return image; |
+ } |
+ |
+ void Log(PP_LogLevel level, const char* format, ...) { |
+ va_list args; |
+ va_start(args, format); |
+ char buf[512]; |
+ vsnprintf(buf, sizeof(buf) - 1, format, args); |
+ buf[sizeof(buf) - 1] = '\0'; |
+ va_end(args); |
+ |
+ Var value(buf); |
+ console->Log(pp_instance(), level, value.pp_var()); |
+ } |
+ |
+ int width_; |
+ int height_; |
+ |
+ bool pending_paint_; |
+ bool waiting_for_flush_completion_; |
+ |
+ CompletionCallbackFactory<MyInstance> callback_factory_; |
+ |
+ alarms::Alarms_Dev alarms_; |
+ |
+ Graphics2D device_context_; |
+}; |
+ |
+// This object is the global object representing this plugin library as long |
+// as it is loaded. |
+class MyModule : public Module { |
+ public: |
+ MyModule() : Module() {} |
+ virtual ~MyModule() {} |
+ |
+ // Override CreateInstance to create your customized Instance object. |
+ virtual Instance* CreateInstance(PP_Instance instance) { |
+ return new MyInstance(instance); |
+ } |
+}; |
+ |
+namespace pp { |
+ |
+// Factory function for your specialization of the Module object. |
+Module* CreateModule() { |
+ return new MyModule(); |
+} |
+ |
+} // namespace pp |
+ |