summaryrefslogtreecommitdiffstats
path: root/src/libs/client/OSCModelEngineInterface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/client/OSCModelEngineInterface.cpp')
-rw-r--r--src/libs/client/OSCModelEngineInterface.cpp364
1 files changed, 364 insertions, 0 deletions
diff --git a/src/libs/client/OSCModelEngineInterface.cpp b/src/libs/client/OSCModelEngineInterface.cpp
new file mode 100644
index 00000000..9e648141
--- /dev/null
+++ b/src/libs/client/OSCModelEngineInterface.cpp
@@ -0,0 +1,364 @@
+/* This file is part of Om. Copyright (C) 2005 Dave Robillard.
+ *
+ * Om is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
+ *
+ * Om is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "OSCModelEngineInterface.h"
+#include <list>
+#include <cassert>
+#include <cstdlib>
+#include <cstring>
+#include <iostream>
+#include <unistd.h>
+#include "OSCListener.h"
+#include "PatchModel.h"
+#include "ConnectionModel.h"
+#include "PresetModel.h"
+#include "ControlModel.h"
+#include "NodeModel.h"
+#include "PluginModel.h"
+
+using std::cerr; using std::cout; using std::endl;
+
+namespace LibOmClient {
+
+
+/** Construct a OSCModelEngineInterface with a user-provided ModelClientInterface object for notification
+ * of engine events.
+ */
+OSCModelEngineInterface::OSCModelEngineInterface(const string& engine_url)
+: OSCEngineInterface(engine_url),
+ m_request_id(0),
+ m_is_attached(false),
+ m_is_registered(false)
+ /*m_blocking(false),
+ m_waiting_for_response(false),
+ m_wait_response_id(0),
+ m_response_received(false),
+ m_wait_response_was_affirmative(false),
+ m_response_semaphore(0)*/
+{
+}
+
+
+OSCModelEngineInterface::~OSCModelEngineInterface()
+{
+ detach();
+}
+
+
+/** Attempt to connect to the Om engine and notify it of our existance.
+ *
+ * Passing a client_port of 0 will automatically choose a free port. If the
+ * @a block parameter is true, this function will not return until a connection
+ * has successfully been made.
+ */
+void
+OSCModelEngineInterface::attach(bool block)
+{
+ cerr << "FIXME: listen thread\n";
+ //start_listen_thread(_client_port);
+
+ /*if (engine_url == "") {
+ string local_url = m_osc_listener->listen_url().substr(
+ 0, m_osc_listener->listen_url().find_last_of(":"));
+ local_url.append(":16180");
+ _engine_addr = lo_address_new_from_url(local_url.c_str());
+ } else {
+ _engine_addr = lo_address_new_from_url(engine_url.c_str());
+ }
+ */
+ _engine_addr = lo_address_new_from_url(_engine_url.c_str());
+
+ if (_engine_addr == NULL) {
+ cerr << "Unable to connect, aborting." << endl;
+ exit(EXIT_FAILURE);
+ }
+
+ char* lo_url = lo_address_get_url(_engine_addr);
+ cout << "[OSCModelEngineInterface] Attempting to contact engine at " << lo_url << " ..." << endl;
+
+ this->ping();
+
+ m_is_attached = true; // FIXME
+
+ /*if (block) {
+ set_wait_response_id(request_id);
+
+ while (1) {
+ if (m_response_semaphore.try_wait() != 0) {
+ cout << ".";
+ cout.flush();
+ ping(request_id);
+ usleep(100000);
+ } else {
+ cout << " connected." << endl;
+ m_waiting_for_response = false;
+ break;
+ }
+ }
+ }
+ */
+
+ free(lo_url);
+}
+
+void
+OSCModelEngineInterface::detach()
+{
+ m_is_attached = false;
+}
+
+#if 0
+void
+OSCModelEngineInterface::start_listen_thread(int client_port)
+{
+ if (m_st != NULL)
+ return;
+
+ if (client_port == 0) {
+ m_st = lo_server_thread_new(NULL, error_cb);
+ } else {
+ char port_str[8];
+ snprintf(port_str, 8, "%d", client_port);
+ m_st = lo_server_thread_new(port_str, error_cb);
+ }
+
+ if (m_st == NULL) {
+ cerr << "[OSCModelEngineInterface] Could not start OSC listener. Aborting." << endl;
+ exit(EXIT_FAILURE);
+ } else {
+ cout << "[OSCModelEngineInterface] Started OSC listener on port " << lo_server_thread_get_port(m_st) << endl;
+ }
+
+ lo_server_thread_add_method(m_st, NULL, NULL, generic_cb, NULL);
+
+ lo_server_thread_add_method(m_st, "/om/response/ok", "i", om_response_ok_cb, this);
+ lo_server_thread_add_method(m_st, "/om/response/error", "is", om_response_error_cb, this);
+
+
+ m_osc_listener = new OSCListener(m_st, m_client_hooks);
+ m_osc_listener->setup_callbacks();
+
+ // Display any uncaught messages to the console
+ lo_server_thread_add_method(m_st, NULL, NULL, unknown_cb, NULL);
+
+ lo_server_thread_start(m_st);
+}
+#endif
+
+///// OSC Commands /////
+
+
+
+/** Load a node.
+ */
+void
+OSCModelEngineInterface::create_node_from_model(const NodeModel* nm)
+{
+ assert(_engine_addr);
+
+ // Load by URI
+ if (nm->plugin()->uri().length() > 0) {
+ lo_send(_engine_addr, "/om/synth/create_node", "isssi", next_id(),
+ nm->path().c_str(),
+ nm->plugin()->type_string(),
+ nm->plugin()->uri().c_str(),
+ (nm->polyphonic() ? 1 : 0));
+ // Load by libname, label
+ } else {
+ //assert(nm->plugin()->lib_name().length() > 0);
+ assert(nm->plugin()->plug_label().length() > 0);
+ lo_send(_engine_addr, "/om/synth/create_node", "issssi", next_id(),
+ nm->path().c_str(),
+ nm->plugin()->type_string(),
+ nm->plugin()->lib_name().c_str(),
+ nm->plugin()->plug_label().c_str(),
+ (nm->polyphonic() ? 1 : 0));
+ }
+}
+
+
+/** Create a patch.
+ */
+void
+OSCModelEngineInterface::create_patch_from_model(const PatchModel* pm)
+{
+ assert(_engine_addr);
+ lo_send(_engine_addr, "/om/synth/create_patch", "isi", next_id(), pm->path().c_str(), pm->poly());
+}
+
+
+/** Notify LASH restoring is finished */
+/*
+void
+OSCModelEngineInterface::lash_restore_finished()
+{
+ assert(_engine_addr != NULL);
+ int id = m_request_id++;
+ lo_send(_engine_addr, "/om/lash/restore_finished", "i", id);
+}
+*/
+#if 0
+/** Set/add a piece of metadata.
+ */
+void
+OSCModelEngineInterface::set_metadata(const string& obj_path,
+ const string& key, const string& value)
+{
+ assert(_engine_addr != NULL);
+ int id = m_request_id++;
+
+ // Deal with the "special" DSSI metadata strings
+ if (key.substr(0, 16) == "dssi-configure--") {
+ string path = "/dssi" + obj_path + "/configure";
+ string dssi_key = key.substr(16);
+ lo_send(_engine_addr, path.c_str(), "ss", dssi_key.c_str(), value.c_str());
+ } else if (key == "dssi-program") {
+ string path = "/dssi" + obj_path + "/program";
+ string dssi_bank_str = value.substr(0, value.find("/"));
+ int dssi_bank = atoi(dssi_bank_str.c_str());
+ string dssi_program_str = value.substr(value.find("/")+1);
+ int dssi_program = atoi(dssi_program_str.c_str());
+ lo_send(_engine_addr, path.c_str(), "ii", dssi_bank, dssi_program);
+ }
+
+ // Normal metadata
+ lo_send(_engine_addr, "/om/metadata/set", "isss", id,
+ obj_path.c_str(), key.c_str(), value.c_str());
+}
+#endif
+
+/** Set all pieces of metadata in a NodeModel.
+ */
+void
+OSCModelEngineInterface::set_all_metadata(const NodeModel* nm)
+{
+ assert(_engine_addr != NULL);
+
+ for (map<string, string>::const_iterator i = nm->metadata().begin(); i != nm->metadata().end(); ++i)
+ set_metadata(nm->path(), (*i).first, (*i).second.c_str());
+}
+
+
+/** Set a preset by setting all relevant controls for a patch.
+ */
+void
+OSCModelEngineInterface::set_preset(const string& patch_path, const PresetModel* const pm)
+{
+ assert(patch_path.find("//") == string::npos);
+ for (list<ControlModel>::const_iterator i = pm->controls().begin(); i != pm->controls().end(); ++i) {
+ set_port_value_queued((*i).port_path(), (*i).value());
+ usleep(1000);
+ }
+}
+
+
+///// Requests /////
+
+
+#if 0
+/** Sets the response ID to be waited for on the next call to wait_for_response()
+ */
+
+void
+OSCModelEngineInterface::set_wait_response_id(int id)
+{
+ assert(!m_waiting_for_response);
+ m_wait_response_id = id;
+ m_response_received = false;
+ m_waiting_for_response = true;
+}
+
+
+/** Waits for the response set by set_wait_response() from the server.
+ *
+ * Returns whether or not the response was positive (ie a success message)
+ * or negative (ie an error)
+ */
+bool
+OSCModelEngineInterface::wait_for_response()
+{
+ cerr << "[OSCModelEngineInterface] Waiting for response " << m_wait_response_id << ": ";
+ bool ret = true;
+
+ assert(m_waiting_for_response);
+ assert(!m_response_received);
+
+ while (!m_response_received)
+ m_response_semaphore.wait();
+
+ cerr << " received." << endl;
+
+ m_waiting_for_response = false;
+ ret = m_wait_response_was_affirmative;
+
+ return ret;
+}
+#endif
+
+///// Static OSC callbacks //////
+
+
+//// End static callbacks, member callbacks below ////
+
+/*
+int
+OSCModelEngineInterface::m_om_response_ok_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data)
+{
+ assert(argc == 1 && !strcmp(types, "i"));
+
+ // FIXME
+ if (!m_is_attached)
+ m_is_attached = true;
+
+ if (m_waiting_for_response) {
+ const int request_id = argv[0]->i;
+
+ if (request_id == m_wait_response_id) {
+ m_response_received = true;
+ m_wait_response_was_affirmative = true;
+ m_response_semaphore.post();
+ }
+ }
+
+ return 0;
+}
+
+
+int
+OSCModelEngineInterface::m_om_response_error_cb(const char* path, const char* types, lo_arg** argv, int argc, void* data)
+{
+ assert(argc == 2 && !strcmp(types, "is"));
+
+ const int request_id = argv[0]->i;
+ const char* msg = &argv[1]->s;
+
+ if (m_waiting_for_response) {
+ if (request_id == m_wait_response_id) {
+ m_response_received = true;
+ m_wait_response_was_affirmative = false;
+ m_response_semaphore.post();
+ }
+ }
+
+ cerr << "ERROR: " << msg << endl;
+ //if (m_client_hooks != NULL)
+ // m_client_hooks->error(msg);
+
+ return 0;
+}
+*/
+
+} // namespace LibOmClient