Logo Search packages:      
Sourcecode: patchage version File versions  Download package

JackDriver.cpp

/* This file is part of Patchage.  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 <string>
#include <jack/jack.h>
#include <iostream>
#include "PatchagePatchBayArea.h"
#include "JackDriver.h"
#include "Patchage.h"
#include "PatchageModule.h"

using std::cerr; using std::endl; using std::cout;
using std::string;

using namespace PatchBay;


JackDriver::JackDriver(Patchage* app, pthread_mutex_t* refresh_mutex)
: m_app(app),
  m_patch_bay(app->patch_bay()),
  m_refresh_mutex(refresh_mutex)
{
}


JackDriver::~JackDriver() 
{
      detach();
}


/** Connect to Jack
 */
void
00048 JackDriver::attach() 
{
      cout << "Connecting to Jack... ";
      
      m_client = jack_client_new("Patchage");
      if (m_client == NULL) {
            cerr << "could not connect to jack server." << endl;
            throw;
      }
      cout << "Done" << endl;
      
      jack_set_port_registration_callback(m_client, jack_port_registration_cb, this);
      jack_set_graph_order_callback(m_client, jack_graph_order_cb, this);

      jack_activate(m_client);
}


void
JackDriver::detach() 
{
      if (m_client != NULL) {
            jack_deactivate(m_client);
            jack_client_close(m_client);
            m_client = NULL;
            cout << "Disconnected from Jack" << endl;
      }
}


/** Refresh all Jack audio ports/connections.
 *
 * This is to be called from Patchage/PatchBayArea, not from JackDriver.
 */
void
00083 JackDriver::refresh() 
{
      const char** ports;
      jack_port_t* port;
      
      ports = jack_get_ports(m_client, NULL, NULL, 0); // get all existing ports

      m_patch_bay->destroy();

      string client1_name;
      string port1_name;
      string client2_name;
      string port2_name;
      PatchageModule* m = NULL;
      
      // Add all ports
      if (ports != NULL)
      for (int i=0; ports[i]; ++i) {
            port = jack_port_by_name(m_client, ports[i]);
            client1_name = ports[i];
            client1_name = client1_name.substr(0, client1_name.find(":"));

            ModuleType type = InputOutput;
            if (jack_port_flags(port) & JackPortIsTerminal) {
                  if (jack_port_flags(port) & JackPortIsInput) {
                        type = Input;
                  } else {
                        type = Output;
                  }
            }

            m = (PatchageModule*)m_patch_bay->find_module(client1_name, type);

            if (m == NULL) {
                  m = new PatchageModule(m_app, client1_name, type);
                  m->load_location();
                  m->store_location();
                  m_patch_bay->add_module(m);
            }
            
            m->add_patchage_port(jack_port_short_name(port),
                  (jack_port_flags(port) & JackPortIsInput),
                  JACK);
      }
      
      // Add all connections
      if (ports != NULL) {
            for (int i=0; ports[i]; ++i) {
                  port = jack_port_by_name(m_client, ports[i]);
                  const char** connected_ports = jack_port_get_all_connections(m_client, port);
                  
                  if (connected_ports != NULL)
                  for (int j=0; connected_ports[j]; ++j) {
                        client1_name = ports[i];
                        port1_name = client1_name.substr(client1_name.find(':')+1);
                        client1_name = client1_name.substr(0, client1_name.find(':'));
                        
                        client2_name = connected_ports[j];
                        port2_name = client2_name.substr(client2_name.find(':')+1);
                        client2_name = client2_name.substr(0, client2_name.find(':'));
                        
                        m_patch_bay->add_connection(client1_name, port1_name, client2_name, port2_name);
                  }
                  free(connected_ports);
            }           
            free(ports);
      }
}


/** Connects two Jack audio ports.
 * 
 * \return Whether connection succeeded.
 */
bool
00158 JackDriver::connect(const string& src_module_name, const string& src_port_name,
                    const string& dst_module_name,  const string& dst_port_name) 
{
      pthread_mutex_lock(m_refresh_mutex);

      string src_port_jack_name = src_module_name + ":" + src_port_name;
      string dst_port_jack_name = dst_module_name + ":" + dst_port_name;

      int result = jack_connect(m_client, src_port_jack_name.c_str(), dst_port_jack_name.c_str());
      
      string msg;
      
      if (result == 0) {
            msg = "Sucessfully connected jack ports";
      } else {
            msg = "Unable to connect ";
            msg += src_port_jack_name;
            msg += " -> ";
            msg += dst_port_jack_name;
      }
      m_app->status_message(msg);
      
      pthread_mutex_unlock(m_refresh_mutex);
      return (!result);
}


/** Disconnects two Jack audio ports.
 * 
 * \return Whether disconnection succeeded.
 */
bool
00190 JackDriver::disconnect(const string& src_module_name, const string& src_port_name,
                    const string& dst_module_name,  const string& dst_port_name) 
{
      pthread_mutex_lock(m_refresh_mutex);

      string src_port_jack_name = src_module_name + ":" + src_port_name;
      string dst_port_jack_name = dst_module_name + ":" + dst_port_name;

      int result = jack_disconnect(m_client, src_port_jack_name.c_str(), dst_port_jack_name.c_str());
      
      string msg;
      
      if (result == 0) {
            msg = "Sucessfully disconnected jack ports";
      } else {
            msg = "Unable to disconnect ";
            msg += src_port_jack_name;
            msg += " -> ";
            msg += dst_port_jack_name;
      }
      m_app->status_message(msg);
      
      pthread_mutex_unlock(m_refresh_mutex);
      return (!result);
}


void
JackDriver::jack_port_registration_cb(jack_port_id_t port_id, int registered, void* me) 
{
      ((JackDriver*)me)->m_app->queue_refresh();
}


int
JackDriver::jack_graph_order_cb(void* me) 
{
      ((JackDriver*)me)->m_app->queue_refresh();

      return 0;
}


Generated by  Doxygen 1.6.0   Back to index