OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef LIFE_APPLICATION_H_ | |
6 #define LIFE_APPLICATION_H_ | |
7 | |
8 #include <cstdlib> | |
9 #include <map> | |
10 #include <memory> | |
11 #include <tr1/memory> | |
12 #include <vector> | |
13 | |
14 #include "experimental/conways_life/audio/audio_player.h" | |
15 #include "experimental/conways_life/life.h" | |
16 #include "experimental/conways_life/locking_image_data.h" | |
17 #include "experimental/conways_life/scripting/scripting_bridge.h" | |
18 #include "experimental/conways_life/stamp.h" | |
19 #include "experimental/conways_life/threading/pthread_ext.h" | |
20 #include "experimental/conways_life/threading/condition_lock.h" | |
21 #include "ppapi/cpp/graphics_2d.h" | |
22 #include "ppapi/cpp/instance.h" | |
23 #include "ppapi/cpp/rect.h" | |
24 #include "ppapi/cpp/size.h" | |
25 | |
26 namespace life { | |
27 // The main object that runs Conway's Life simulation (for details, see: | |
28 // http://en.wikipedia.org/wiki/Conway's_Game_of_Life). This class holds all | |
29 // the Pepper objects (the 2D context and the instance) required to interface | |
30 // with the browser. It also owns an instance of the simulation object. | |
31 class LifeApplication : public pp::Instance { | |
32 public: | |
33 // The states for the |sim_state_condition_| condition lock. | |
34 enum SimulationState { | |
35 kStopped, | |
36 kRunning | |
37 }; | |
38 | |
39 explicit LifeApplication(PP_Instance instance); | |
40 virtual ~LifeApplication(); | |
41 | |
42 // Called by the browser when the NaCl module is loaded and all ready to go. | |
43 virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]); | |
44 | |
45 // Update the graphics context to the new size, and reallocate all new | |
46 // buffers to the new size. | |
47 virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip); | |
48 | |
49 // Called by the browser to handle the postMessage() call in Javascript. | |
50 virtual void HandleMessage(const pp::Var& message); | |
51 | |
52 // Runs a tick of the simulations, updating all buffers. Flushes the | |
53 // contents of |pixel_buffer_| to the 2D graphics context. | |
54 void Update(); | |
55 | |
56 // Replace the current stamp. See stamp.h for a description of the stamp | |
57 // format. Exposed to the browser as "setCurrentStamp". Takes a parameter | |
58 // named "description" that contains the string-encoded stamp description. | |
59 void SetCurrentStamp(const scripting::ScriptingBridge& bridge, | |
60 const scripting::MethodParameter& parameters); | |
61 | |
62 // Set the automaton rules. The rules are expressed as a string, with the | |
63 // Birth and Keep Alive rules separated by a '/'. The format follows the .LIF | |
64 // 1.05 format here: http://psoup.math.wisc.edu/mcell/ca_files_formats.html | |
65 // Survival/Birth. Exposed to the browser as "setAutomatonRules". | |
66 // Takes a single parameter named "rules". | |
67 void SetAutomatonRules(const scripting::ScriptingBridge& bridge, | |
68 const scripting::MethodParameter& parameters); | |
69 | |
70 // Clears the current simulation (resets back to all-dead, graphics buffer to | |
71 // black). Exposed to the browser as "clear()". |args| can be empty. | |
72 void Clear(const scripting::ScriptingBridge& bridge, | |
73 const scripting::MethodParameter& parameters); | |
74 | |
75 // Plot a new blob of life centered around the (x, y) coordinates described | |
76 // in |parameters|. This method is exposed to the browser as | |
77 // "putStampAtPoint", it takes a parameter named "x" and one named "y". | |
78 void PutStampAtPoint(const scripting::ScriptingBridge& bridge, | |
79 const scripting::MethodParameter& parameters); | |
80 | |
81 // Run the simulation in the specified mode. If the mode is changed, then | |
82 // the simulation is stopped and restarted in the new mode. Takes one | |
83 // parameter named "mode" which can be one of "random_seed" or "stamp". | |
84 // Exposed to the browser as "runSimulation". | |
85 void RunSimulation(const scripting::ScriptingBridge& bridge, | |
86 const scripting::MethodParameter& parameters); | |
87 | |
88 // Stop the simulation. Does nothing if the simulation is stopped. | |
89 // Exposed to the browser as "stopSimulation". Takes no parameters. | |
90 void StopSimulation(const scripting::ScriptingBridge& bridge, | |
91 const scripting::MethodParameter& parameters); | |
92 | |
93 // Set the URL used to get the stamp sound. Takes one parameter named | |
94 // "soundUrl" that is the URL of the sound file. Does not affect a | |
95 // stamp sound that is currently playing, but can affect all subsequent plays | |
96 // of the stamp sound. If there are errors fetching the sound data from | |
97 // |soundUrl|, then the stamp sound is left unchanged. Exposed to the browser | |
98 // as "setStampSoundUrl". | |
99 void SetStampSoundUrl(const scripting::ScriptingBridge& bridge, | |
100 const scripting::MethodParameter& parameters); | |
101 | |
102 int width() const { | |
103 return shared_pixel_buffer_ ? shared_pixel_buffer_->size().width() : 0; | |
104 } | |
105 int height() const { | |
106 return shared_pixel_buffer_ ? shared_pixel_buffer_->size().height() : 0; | |
107 } | |
108 | |
109 // Indicate whether the simulation is running or paused. | |
110 bool is_running() const { | |
111 return life_simulation_.simulation_mode() != life::Life::kPaused; | |
112 } | |
113 | |
114 // Indicate whether a flush is pending. This can only be called from the | |
115 // main thread; it is not thread safe. | |
116 bool flush_pending() const { | |
117 return flush_pending_; | |
118 } | |
119 void set_flush_pending(bool flag) { | |
120 flush_pending_ = flag; | |
121 } | |
122 | |
123 private: | |
124 // Create and initialize the 2D context used for drawing. | |
125 void CreateContext(const pp::Size& size); | |
126 // Destroy the 2D drawing context. | |
127 void DestroyContext(); | |
128 // Push the pixels to the browser, then attempt to flush the 2D context. If | |
129 // there is a pending flush on the 2D context, then update the pixels only | |
130 // and do not flush. | |
131 void FlushPixelBuffer(); | |
132 // Return a pointer to the pixels without acquiring the pixel buffer lock. | |
133 uint32_t* PixelBufferNoLock(); | |
134 | |
135 bool IsContextValid() const { | |
136 return graphics_2d_context_ != NULL; | |
137 } | |
138 | |
139 // Browser connectivity and scripting support. | |
140 scripting::ScriptingBridge scripting_bridge_; | |
141 | |
142 // The simulation. | |
143 Life life_simulation_; | |
144 | |
145 // 2D context variables. | |
146 std::tr1::shared_ptr<LockingImageData> shared_pixel_buffer_; | |
147 pp::Graphics2D* graphics_2d_context_; | |
148 bool flush_pending_; | |
149 bool view_changed_size_; | |
150 pp::Size view_size_; | |
151 | |
152 // The current stamp. The dictionary of stamps is kept in the browser. | |
153 Stamp stamp_; | |
154 | |
155 // Audio. | |
156 audio::AudioPlayer audio_player_; | |
157 }; | |
158 | |
159 } // namespace life | |
160 | |
161 #endif // LIFE_APPLICATION_H_ | |
162 | |
OLD | NEW |