1 /*
2  * Copyright (C) 2009, 2010 Hermann Meyer, James Warden, Andreas Degert
3  * Copyright (C) 2011 Pete Shorthose
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #pragma once
21 
22 #ifndef SRC_HEADERS_JSONRPC_H_
23 #define SRC_HEADERS_JSONRPC_H_
24 
25 #include "engine.h"
26 #include <bitset>
27 #include <queue>
28 #include <giomm/init.h>     // NOLINT
29 #include <giomm/socketservice.h>
30 #include "jsonrpc_methods.h"
31 
32 class GxService;
33 
34 class JsonValue {
35 protected:
JsonValue()36     JsonValue() {}
~JsonValue()37     virtual ~JsonValue() {}
38     friend class JsonArray;
39 public:
40     virtual double getFloat() const;
41     virtual int getInt() const;
42     virtual const Glib::ustring& getString() const;
43     virtual gx_system::JsonSubParser getSubParser() const;
44 };
45 
46 class JsonArray: public std::vector<JsonValue*> {
47 public:
JsonArray()48     JsonArray():std::vector<JsonValue*>() {}
49     ~JsonArray();
50     JsonValue *operator[](unsigned int i);
51     void append(gx_system::JsonParser& jp);
52 };
53 
54 class CmdConnection: public sigc::trackable {
55 public:
56     struct methodnames {
57 	const char *name;
58 	jsonrpc_method m_id;
59     };
60     enum msg_type {
61 	f_preset_changed,
62 	f_state_changed,
63 	f_freq_changed,
64 	f_display,
65 	f_display_state,
66 	f_selection_done,
67 	f_presetlist_changed,
68 	f_log_message,
69 	f_midi_changed,
70 	f_midi_value_changed,
71 	f_parameter_change_notify,
72 	f_plugins_changed,
73 	f_misc_msg,
74 	f_units_changed,
75 	END_OF_FLAGS
76     };
77 private:
78     GxService& serv;
79     Glib::RefPtr<Gio::SocketConnection> connection;
80     std::list<std::string> outgoing;
81     unsigned int current_offset;
82     gx_system::JsonStringParser jp;
83     bool midi_config_mode;
84     std::bitset<END_OF_FLAGS> flags;
85     std::map<string,float> maxlevel;
86 private:
87     bool find_token(const Glib::ustring& token, msg_type *start, msg_type *end);
activate(int n,bool v)88     void activate(int n, bool v) { flags.set(n, v); }
89     void exec(Glib::ustring cmd);
90     void call(gx_system::JsonWriter& jw, const methodnames *mn, JsonArray& params);
91     void notify(gx_system::JsonStringWriter& jw, const methodnames *mn, JsonArray& params);
92     bool request(gx_system::JsonStringParser& jp, gx_system::JsonStringWriter& jw, bool batch_start);
93     void write_error(gx_system::JsonWriter& jw, int code, const char *message);
write_error(gx_system::JsonWriter & jw,int code,Glib::ustring & message)94     void write_error(gx_system::JsonWriter& jw, int code, Glib::ustring& message) { write_error(jw, code, message.c_str()); }
95     void error_response(gx_system::JsonWriter& jw, int code, const char *message);
error_response(gx_system::JsonWriter & jw,int code,const Glib::ustring & message)96     void error_response(gx_system::JsonWriter& jw, int code, const Glib::ustring& message) { error_response(jw, code, message.c_str()); }
send_notify_begin(gx_system::JsonStringWriter & jw,const char * method)97     void send_notify_begin(gx_system::JsonStringWriter& jw, const char *method) { jw.send_notify_begin(method); }
98     void send_notify_end(gx_system::JsonStringWriter& jw, bool send_out=true);
99     void listen(const Glib::ustring& tp);
100     void unlisten(const Glib::ustring& tp);
101     void process(gx_system::JsonStringParser& jp);
102 
103 public:
104     CmdConnection(GxService& serv, const Glib::RefPtr<Gio::SocketConnection>& connection_);
105     ~CmdConnection();
106     bool on_data_in(Glib::IOCondition cond);
107     bool on_data_out(Glib::IOCondition cond);
108     void send(gx_system::JsonStringWriter& jw);
is_activated(msg_type n)109     bool is_activated(msg_type n) { return flags[n]; }
update_maxlevel(const std::string & id,float v)110     void update_maxlevel(const std::string& id, float v) { float& m = maxlevel[id]; m = max(m, v); }
111     friend class UiBuilderVirt;
112 };
113 
114 struct broadcast_data {
115     gx_system::JsonStringWriter *jw;
116     CmdConnection::msg_type n;
117     CmdConnection *sender;
118 };
119 
120 class GxService: public Gio::SocketService {
121 private:
122     struct ChangedPlugin {
123 	std::string id;
124 	gx_engine::PluginChange::pc status;
ChangedPluginChangedPlugin125 	ChangedPlugin(const std::string& id_, gx_engine::PluginChange::pc status_): id(id_), status(status_) {}
126     };
127 private:
128     gx_preset::GxSettings& settings;
129     gx_jack::GxJack& jack;
130     TunerSwitcher& tuner_switcher;
131     sigc::slot<void> quit_mainloop;
132     time_t oldest_unsaved;
133     time_t last_change;
134     sigc::connection save_conn;
135     std::list<CmdConnection*> connection_list;
136     std::queue<broadcast_data> broadcast_list;
137     gx_system::JsonStringWriter *jwc;
138     std::map<std::string,bool> *preg_map;
139     std::map<std::string,float> maxlevel;
140 private:
141     virtual bool on_incoming(const Glib::RefPtr<Gio::SocketConnection>& connection,
142 			     const Glib::RefPtr<Glib::Object>& source_object);
143     void save_state();
144     void remove_connection(CmdConnection* p);
145     bool broadcast_listeners(CmdConnection::msg_type n, CmdConnection *sender = 0);
146     void broadcast(gx_system::JsonStringWriter& jw, CmdConnection::msg_type n, CmdConnection *sender = 0);
147     bool idle_broadcast_handler();
148     void connect_value_changed_signal(gx_engine::Parameter *p);
149 
150     // message formatting functions
151     void serialize_parameter_change(gx_system::JsonWriter& jw);
152     void ladspaloader_write_changes(gx_system::JsonWriter& jw, std::vector<ChangedPlugin>& changed_plugins);
153 
154     // signal handler
155     void on_param_insert_remove(gx_engine::Parameter *p, bool insert);
156     void on_param_value_changed(gx_engine::Parameter *p);
157     void preset_changed();
158     void on_engine_state_change(gx_engine::GxEngineState state);
159     void on_tuner_freq_changed();
160     void display(const Glib::ustring& bank, const Glib::ustring& preset);
161     void set_display_state(TunerSwitcher::SwitcherState newstate);
162     void on_selection_done(bool v);
163     void on_presetlist_changed();
164     void on_log_message(const string& msg, GxLogger::MsgType tp, bool plugged);
165     void on_midi_changed();
166     void on_midi_value_changed(int ctl, int value);
167     void on_rack_unit_changed(bool stereo);
168     static void add_changed_plugin(gx_engine::Plugin* pl, gx_engine::PluginChange::pc v,
169 				   std::vector<ChangedPlugin>& vec);
170     void create_bluetooth_sockets(const Glib::ustring& host);
171 
172     friend class CmdConnection;
173 public:
174     GxService(gx_preset::GxSettings& settings_, gx_jack::GxJack& jack_,
175 	      TunerSwitcher& tunerswitcher, sigc::slot<void> quit_mainloop_,
176 	      const Glib::ustring& host, int *port);
177     ~GxService();
178     void send_rack_changed(bool stereo, CmdConnection *cmd);
179     void ladspaloader_update_plugins(gx_system::JsonWriter *jw, CmdConnection *cmd);
180     float update_maxlevel(const std::string& id, bool reset=false);
181 };
182 
183 const char *engine_state_to_string(gx_engine::GxEngineState s);
184 gx_engine::GxEngineState string_to_engine_state(const std::string& s);
185 
186 #endif // SRC_HEADERS_JSONRPC_H_
187