Esempio n. 1
0
void ensure_connected(jack_client_t *client, const char **ports, desired_connection *connection) {
  const char *from_port_name = find_port(client, ports, connection->from_port);
  const char *to_port_name = find_port(client, ports, connection->to_port);

  // make sure both ports exist
  if (from_port_name == NULL) {
    printf("X from port (%s:%s) cannot be found\n", connection->from_port->desired,
	   mtype_strings[connection->from_port->which]);
    return;
  }
  if (to_port_name == NULL) {
    printf("X to port (%s:%s) cannot be found\n", connection->to_port->desired,
	   mtype_strings[connection->to_port->which]);
    return;
  }

  jack_port_t *from_port, *to_port;
  from_port = jack_port_by_name(client, from_port_name);
  to_port = jack_port_by_name(client, to_port_name);

  // this should never prematurely return, in theory
  if (from_port == NULL || to_port == NULL) {
    return;
  }
  
  const char **connections, **orig_connections;
  orig_connections = connections = jack_port_get_all_connections(client, from_port);
  
  printf("! connections for %s\n", from_port_name);
  if (connections == NULL) {
    printf("X  --None\n");
  }
  int connected = 0;
  while (connections && *connections) {
    if (port_matcher(client, *connections, connection->to_port)) {
      printf("! -->%s\n", *connections);
      connected = 1;
      break;
    }
    printf("  >%s\n", *connections);
    *connections++;
  }
  if (connections != NULL) {
    jack_free(orig_connections);
  }

  if (!connected) {
    int rc;
    printf("! Connecting %s to %s\n", from_port_name, to_port_name);
    rc = jack_connect(client, from_port_name, to_port_name);
    printf("%s rc is %d\n", rc == 0 ? "!" : "X", rc);
  }
}
Esempio n. 2
0
void AudioReader::start(char* llabel = "cloop:capture_1", char* rlabel = "cloop:capture_2") {
    if(running)
        return;
    running = true;
    // set up the history
    head = 0;
    history_length = 0;
    sounds = new Sound[max_history_length];
    if((client = jack_client_open("AudioReader", JackNoStartServer, NULL)) == 0){
        fprintf(stderr, "jack server not running?\n");
        exit(EXIT_FAILURE);
    }
    pthread_mutex_lock(&reading_mutex); // jack_client_open() links the process() callback and if process() runs before the ports are connected this will break
    jack_set_process_callback(client, audio_reader_process_callback, (void *) this);
    jack_on_shutdown(client, audio_reader_shutdown_callback, this);
    if (jack_activate(client)) {
        fprintf(stderr, "Cannot activate client");
        exit(EXIT_FAILURE);
    }
    // register the ports to capture data on, in this case set with the JACK audio GUI
    output_left = jack_port_by_name(client, llabel);
    output_right = jack_port_by_name(client, rlabel);
    if (output_left == NULL || output_right == NULL) {
        fprintf(stderr, "Can't get ports from Jack server");
        jack_client_close(client);
        exit(EXIT_FAILURE);
    }
    // allocate space for the main audio buffer that will continuously be written to
    buffer = new jack_default_audio_sample_t[nports * maxframes];
    // register this program's loopback ports
    input_left = jack_port_register(client, "AudioReaderLeft", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
    input_right = jack_port_register(client, "AudioReaderRight", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
    if (input_left == 0 || input_right == 0) {
        fprintf(stderr, "Cannot register loopback port\n");
        stop();
        exit(EXIT_FAILURE);
    }
    // create the new connections to route all audio to system out through this program
    int left_con = jack_connect(client, jack_port_name(output_left), jack_port_name(input_left));
    int right_con = jack_connect(client, jack_port_name(output_right), jack_port_name(input_right));
    if (left_con != 0 || right_con != 0) {
        fprintf(stderr, "Cannot connect input to output\n");
        stop();
        exit(EXIT_FAILURE);
    }
    pthread_mutex_unlock(&reading_mutex);
    // allocate the space for the fft
    if ((cfg = kiss_fftr_alloc(maxframes, 0, NULL, NULL)) == NULL)
        fprintf(stderr, "Out of memory!\n");
}
Esempio n. 3
0
static int _list_ports(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj* const *objv) {
  if (argc != 2) return fw_error_str(interp, "jack-client list-ports");
  _t *dp = (_t *)clientData;
  Tcl_Obj *dict = Tcl_NewDictObj();
  const char **portv[] = {
    jack_get_ports (dp->fw.client, NULL, JACK_DEFAULT_AUDIO_TYPE, 0),
    jack_get_ports (dp->fw.client, NULL, JACK_DEFAULT_MIDI_TYPE, 0)
  };
  for (int p = 0; p < 2; p += 1)
    if (portv[p] != NULL) {
      for (int i = 0; portv[p][i] != NULL; i += 1) {
	jack_port_t *port = jack_port_by_name(dp->fw.client, portv[p][i]);
	if (port != NULL) {
	  Tcl_Obj *pdict = Tcl_NewDictObj();
	  int flags = jack_port_flags(port);
	  Tcl_DictObjPut(interp, pdict, Tcl_NewStringObj("direction", -1), flags & JackPortIsInput ? Tcl_NewStringObj("input", -1) : Tcl_NewStringObj("output", -1) );
	  Tcl_DictObjPut(interp, pdict, Tcl_NewStringObj("physical", -1), Tcl_NewIntObj(flags & JackPortIsPhysical ? 1 : 0));
	  Tcl_DictObjPut(interp, pdict, Tcl_NewStringObj("type", -1), p == 0 ? Tcl_NewStringObj("audio", -1) : Tcl_NewStringObj("midi", -1));
	  const char **connv = jack_port_get_all_connections(dp->fw.client, port);
	  Tcl_Obj *list = Tcl_NewListObj(0, NULL);
	  if (connv != NULL) {
	    for (int j = 0; connv[j] != NULL; j += 1)
	      Tcl_ListObjAppendElement(interp, list, Tcl_NewStringObj(connv[j], -1));
	    jack_free(connv);
	  }
	  Tcl_DictObjPut(interp, pdict, Tcl_NewStringObj("connections", -1), list);
	  Tcl_DictObjPut(interp, dict, Tcl_NewStringObj(portv[p][i], -1), pdict);
	}
      }
      jack_free(portv[p]);
    }
  Tcl_SetObjResult(interp, dict);
  return TCL_OK;
}
Esempio n. 4
0
static PyObject* get_port_type(PyObject* self, PyObject* args)
{
    char * port_name;

    if (! PyArg_ParseTuple(args, "s", &port_name))
        return NULL;

    if (port_name == NULL) {
        PyErr_SetString(JackError, "Port name cannot be empty.");
        return NULL;
    }

    pyjack_client_t * client = self_or_global_client(self);
    if(client->pjc == NULL) {
        PyErr_SetString(JackNotConnectedError, "Jack connection has not yet been established.");
        return NULL;
    }

    jack_port_t * port = jack_port_by_name(client->pjc, port_name);
    if (!port) {
        PyErr_SetString(JackError, "Port name cannot be empty.");
        return NULL;
    }
    const char * port_type = jack_port_type(port);

    return Py_BuildValue("s", port_type);
}
//-------------------------------------------------------------------------------
void JMess::setConnectedPorts()
{
  mConnectedPorts.clear();

  const char **ports, **connections; //vector of ports and connections
  QVector<QString> OutputInput(2); //helper variable

  //Get active output ports.
  ports = jack_get_ports (mClient, NULL, NULL, JackPortIsOutput);
  
  for (unsigned int out_i = 0; ports[out_i]; ++out_i) {
    if ((connections = jack_port_get_all_connections 
	 (mClient, jack_port_by_name(mClient, ports[out_i]))) != 0) {
      for (unsigned int in_i = 0; connections[in_i]; ++in_i) {
	OutputInput[0] = ports[out_i];
	//cout << "Output ===> " <<qPrintable(OutputInput[0]) << endl;
	OutputInput[1] = connections[in_i];
	//cout << "Input ===> " << qPrintable(OutputInput[1]) << endl;
	mConnectedPorts.append(OutputInput);
      }
    }
  }

  free(ports);
}
Esempio n. 6
0
int getConnections(void) 
{
    int nConnect = 0;
 	const char** ports = getAllPorts();
    int a = numeroPorte(ports);
    int i;
    for (i = 0; i < a; i++) {
        const char** aa;
        jack_port_t* jp;
        jp = jack_port_by_name(client, ports[i]);
        if (jp != NULL) {
			if ((aa = jack_port_get_all_connections(client, jp)) != NULL) {
				int g = 0;
				while (aa[g] != NULL) {
					g++;
				}
				nConnect += g;
				free(aa);  
			}
		}
    }
	if (ports)
		free(ports);
    return nConnect;
}
Esempio n. 7
0
// Return port flags (an integer)
static PyObject* get_port_flags(PyObject* self, PyObject* args)
{
    char* pname;
    jack_port_t* jp;
    int i;

    pyjack_client_t * client = self_or_global_client(self);
    if(client->pjc == NULL) {
        PyErr_SetString(JackNotConnectedError, "Jack connection has not yet been established.");
        return NULL;
    }

    if (! PyArg_ParseTuple(args, "s", &pname))
        return NULL;

    jp = jack_port_by_name(client->pjc, pname);
    if(jp == NULL) {
        PyErr_SetString(JackError, "Bad port name.");
        return NULL;
    }

    i = jack_port_flags(jp);
    if(i < 0) {
        PyErr_SetString(JackError, "Error getting port flags.");
        return NULL;
    }

    return Py_BuildValue("i", i);
}
Esempio n. 8
0
static jack_port_t *
update_connection(jack_port_t *remote_port, int connected,
                  jack_port_t *local_port, jack_port_t *current_port,
                  const char *target_name)
{
    if (connected) {
        if (current_port) {
            return current_port;
        }
        if (target_name) {
            char *aliases[2];
            if (! strcmp(target_name, jack_port_name(remote_port))) {
                return remote_port;
            }
            aliases[0] = alias1;
            aliases[1] = alias2;
            switch (jack_port_get_aliases(remote_port, aliases)) {
            case -1:
                /* Sigh ... */
                die("jack_port_get_aliases", "Failed to get port aliases");
            case 2:
                if (! strcmp(target_name, alias2)) {
                    return remote_port;
                }
                /* Fallthrough on purpose */
            case 1:
                if (! strcmp(target_name, alias1)) {
                    return remote_port;
                }
                /* Fallthrough on purpose */
            case 0:
                return NULL;
            }
            /* This shouldn't happen. */
            assert(0);
        }
        return remote_port;
    }
    if (! strcmp(jack_port_name(remote_port), jack_port_name(current_port))) {
        const char **port_names;
        if (target_name) {
            return NULL;
        }
        port_names = jack_port_get_connections(local_port);
        if (port_names == NULL) {
            return NULL;
        }

        /* If a connected port is disconnected and other ports are still
           connected, then we take the first port name in the array and use it
           as our remote port.  It's a dumb implementation. */
        current_port = jack_port_by_name(client, port_names[0]);
        jack_free(port_names);
        if (current_port == NULL) {
            /* Sigh */
            die("jack_port_by_name", "failed to get port by name");
        }
    }
    return current_port;
}
Esempio n. 9
0
int connessionePerNumero2(int n, char** nomeOut, int len) 
{
    int many = 0;
    char porta[256];
    jack_port_t* jp;
    unsigned long tipo;
    portaPerNumero(n, porta, &tipo);
    jp = jack_port_by_name(client, porta);
    if (jp == NULL) 
		return 0;
    const char** connec = jack_port_get_all_connections(client, jp);
	if (connec != NULL) {
		int nu = numeroConn(connec);
		int i;
		if (nomeOut != NULL) {
			for (i = 0; i < nu && i < len; i++){
				if (connec[i] != NULL && nomeOut[i] != NULL) 
					strcpy(nomeOut[i], connec[i]);
			}
		}
		many = nu;
		free(connec); 
	}
    return many;
}
Esempio n. 10
0
static void autoconnect_port(jack_client_t *client, const char *port, const char *use_name, int is_cbox_input, const jack_port_t *only_connect_port, struct cbox_command_target *fb)
{
    int res;
    if (only_connect_port)
    {
        jack_port_t *right;
        right = jack_port_by_name(client, use_name);
        if (only_connect_port != right)
            return;
    }
    
    const char *pfrom = is_cbox_input ? use_name : port;
    const char *pto = !is_cbox_input ? use_name : port;
    
    res = jack_connect(client, pfrom, pto);
    if (res == EEXIST)
        res = 0;
    gboolean suppressed = FALSE;
    if (fb)
    {
        if (!res)
            suppressed = cbox_execute_on(fb, NULL, "/io/jack/connected", "ss", NULL, pfrom, pto);
        else
            suppressed = cbox_execute_on(fb, NULL, "/io/jack/connect_failed", "sss", NULL, pfrom, pto, (res == EEXIST ? "already connected" : "failed"));
    }
    if (!suppressed)
        g_message("Connect: %s %s %s (%s)", port, is_cbox_input ? "<-" : "->", use_name, res == 0 ? "success" : (res == EEXIST ? "already connected" : "failed"));
}
Esempio n. 11
0
unsigned long getTipoByName(const char* name)
{
    jack_port_t* jp;
    jp = jack_port_by_name(client, name);
    if (jp != NULL) 
		return jack_port_flags(jp);
    return 0;
}
Esempio n. 12
0
void
jack_port_clear_all_connections ( jack_client_t *j , const char *l ) 
{
  const char **c ;
  c = jack_port_get_all_connections ( j , jack_port_by_name ( j , l ) ) ;
  if ( c ) {
    int k ;
    for ( k = 0 ; c[k] ; k++ ) {
      jack_port_disconnect_named ( j , l , c[k] ) ;
    }
    free ( c ) ;
  }
}
Esempio n. 13
0
// connect_port
static PyObject* port_connect(PyObject* self, PyObject* args)
{
    char* src_name;
    char* dst_name;

    pyjack_client_t * client = self_or_global_client(self);
    if(client->pjc == NULL) {
        PyErr_SetString(JackNotConnectedError, "Jack connection has not yet been established.");
        return NULL;
    }

    if (! PyArg_ParseTuple(args, "ss", &src_name, &dst_name))
        return NULL;

    jack_port_t * src = jack_port_by_name(client->pjc, src_name);
    if (!src) {
        PyErr_SetString(JackUsageError, "Non existing source port.");
        return NULL;
        }
    jack_port_t * dst = jack_port_by_name(client->pjc, dst_name);
    if (!dst) {
        PyErr_SetString(JackUsageError, "Non existing destination port.");
        return NULL;
        }
    if(! client->active) {
        if(jack_port_is_mine(client->pjc, src) || jack_port_is_mine(client->pjc, dst)) {
            PyErr_SetString(JackUsageError, "Jack client must be activated to connect own ports.");
            return NULL;
        }
    }
    int error = jack_connect(client->pjc, src_name, dst_name);
    if (error !=0 && error != EEXIST) {
        PyErr_SetString(JackError, "Failed to connect ports.");
        return NULL;
    }

    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 14
0
// disconnect_port
static PyObject* port_disconnect(PyObject* self, PyObject* args)
{
    char* src_name;
    char* dst_name;
    pyjack_client_t * client = self_or_global_client(self);

    if(client->pjc == NULL) {
        PyErr_SetString(JackNotConnectedError, "Jack connection has not yet been established.");
        return NULL;
    }

    if (! PyArg_ParseTuple(args, "ss", &src_name, &dst_name))
        return NULL;

    jack_port_t * src = jack_port_by_name(client->pjc, src_name);
    if (!src) {
        PyErr_SetString(JackUsageError, "Non existing source port.");
        return NULL;
    }

    jack_port_t * dst = jack_port_by_name(client->pjc, dst_name);
    if (!dst) {
        PyErr_SetString(JackUsageError, "Non existing destination port.");
        return NULL;
    }

    if(jack_port_connected_to_extern(client, src, dst_name)) {
        if (jack_disconnect(client->pjc, src_name, dst_name)) {
            PyErr_SetString(JackError, "Failed to disconnect ports.");
            return NULL;
        }
    }

    Py_INCREF(Py_None);
    return Py_None;
}
Esempio n. 15
0
QList<QString> JackAudio::inputPorts()
      {
      const char** ports = jack_get_ports(client, 0, 0, 0);
      QList<QString> clientList;
      for (const char** p = ports; p && *p; ++p) {
            jack_port_t* port = jack_port_by_name(client, *p);
            int flags = jack_port_flags(port);
            if (!(flags & JackPortIsInput))
                  continue;
            char buffer[128];
            strncpy(buffer, *p, 128);
            if (strncmp(buffer, "Mscore", 6) == 0)
                  continue;
            clientList.append(QString(buffer));
            }
      return clientList;
      }
Esempio n. 16
0
int
jack_port_is_connected_p ( jack_client_t *j , const char *l , const char *r ) 
{
  const char **c ;
  c = jack_port_get_all_connections ( j , jack_port_by_name ( j , l ) ) ;
  if ( c ) {
    int k ;
    for ( k = 0 ; c[k] ; k++ ) {
      if ( strcmp ( c[k] , r ) == 0 ) {
	free ( c ) ;
	return 1 ;
      }
    }
    free ( c ) ;
  }
  return 0 ;
}
Esempio n. 17
0
void JackAudioSystem::auto_connect_ports() {
	if (!(client && g.s.bJackAutoConnect)) {
		return;
	}

	disconnect_ports();

	const char **ports = NULL;
	const int wanted_out_flags = JackPortIsPhysical | JackPortIsOutput;
	const int wanted_in_flags = JackPortIsPhysical | JackPortIsInput;
	int err;
	unsigned int connected_out_ports = 0;
	unsigned int connected_in_ports = 0;

	ports = jack_get_ports(client, 0, "audio", JackPortIsPhysical);
	if (ports != NULL) {
		int i = 0;
		while (ports[i] != NULL) {
			jack_port_t * const port = jack_port_by_name(client, ports[i]);
			if (port == NULL)  {
				qWarning("JackAudioSystem: jack_port_by_name() returned an invalid port - skipping it");
				continue;
			}

			const int port_flags = jack_port_flags(port);

			if (bInputIsGood && (port_flags & wanted_out_flags) == wanted_out_flags && connected_in_ports < 1) {
				err = jack_connect(client, ports[i], jack_port_name(in_port));
				if (err != 0) {
					qWarning("JackAudioSystem: unable to connect port '%s' to '%s' - jack_connect() returned %i", ports[i], jack_port_name(in_port), err);
				} else {
					connected_in_ports++;
				}
			} else if (bOutputIsGood && (port_flags & wanted_in_flags) == wanted_in_flags && connected_out_ports < iOutPorts) {
				err = jack_connect(client, jack_port_name(out_ports[connected_out_ports]), ports[i]);
				if (err != 0) {
					qWarning("JackAudioSystem: unable to connect port '%s' to '%s' - jack_connect() returned %i", jack_port_name(out_ports[connected_out_ports]), ports[i], err);
				} else {
					connected_out_ports++;
				}
			}

			++i;
		}
	}
}
Esempio n. 18
0
static gboolean cbox_jack_io_get_jack_uuid_from_name(struct cbox_jack_io_impl *jii, const char *name, jack_uuid_t *uuid, GError **error)
{
    jack_port_t *port = NULL;
    port = jack_port_by_name(jii->client, name);
    if (!port)
    {
        g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", name);
        return FALSE;
    }
    assert(uuid);
    jack_uuid_t temp_uuid = jack_port_uuid(port);
    if (!temp_uuid)
    {
        g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "JACK uuid for port '%s' not found", name);
        return FALSE;
    }
    *uuid = temp_uuid;
    return TRUE;
}
Esempio n. 19
0
// Return a list of full port names connected to the named port
// Port does not need to be owned by this client.
static PyObject* get_connections(PyObject* self, PyObject* args)
{
    char* pname;
    const char** jplist;
    jack_port_t* jp;
    PyObject* plist;
    int i;

    pyjack_client_t * client = self_or_global_client(self);
    if(client->pjc == NULL) {
        PyErr_SetString(JackNotConnectedError, "Jack connection has not yet been established.");
        return NULL;
    }

    if (! PyArg_ParseTuple(args, "s", &pname))
        return NULL;

    jp = jack_port_by_name(client->pjc, pname);
    if(jp == NULL) {
        PyErr_SetString(JackError, "Bad port name.");
        return NULL;
    }

    jplist = jack_port_get_all_connections(client->pjc, jp);

    i = 0;
    plist = PyList_New(0);
    if(jplist != NULL) {
        while(jplist[i] != NULL) {
            PyList_Append(plist, Py_BuildValue("s", jplist[i]));
            //free(jplist[i]);  // memory leak or not?
            i++;
        }
    }

    Py_INCREF(plist);
    return plist;
}
Esempio n. 20
0
int port_matcher(jack_client_t *client, const char *name, port_ident *ident) {
  // look for aliases
  jack_port_t *port = jack_port_by_name(client, name);
  int num_aliases;
  aliases[0][0] = 0;
  aliases[1][0] = 0;

  if (port == NULL) {
    printf("port is null %s\n", name);
    return 0;
  }
  num_aliases = jack_port_get_aliases(port, aliases);

  if (num_aliases > 0) {
    int i;
    for (i = 0; i < num_aliases; i++) {
      if (port_matcher_inner(aliases[i], ident)) {
	return 1;
      }
    }
  }

  return port_matcher_inner(name, ident);
}
RString RageSoundDriver_JACK::ConnectPorts()
{
	vector<RString> portNames;
	split(PREFSMAN->m_iSoundDevice.Get(), ",", portNames, true);

	const char *port_out_l = NULL, *port_out_r = NULL;
	const char **ports = NULL;
	if( portNames.size() == 0 )
	{
		// The user has NOT specified any ports to connect to. Search 
		// for all physical sinks and use the first two.
		ports = jack_get_ports( client, NULL, NULL, JackPortIsInput | JackPortIsPhysical );
		if( ports == NULL )
			return "Couldn't get JACK ports";
		if( ports[0] == NULL )
		{
			jack_free( ports );
			return "No physical sinks!";
		}
		port_out_l = ports[0];

		if( ports[1] == NULL )
			// Only one physical sink. We're going mono!
			port_out_r = ports[0];
		else
			port_out_r = ports[1];
	}
	else
	{
		// The user has specified ports to connect to. Loop through
		// them to find two that are valid, then use them. If we find 
		// only one that is valid, connect both channels to it.
		// Use jack_port_by_name to ensure ports exist, then
		// jack_port_name to use their canonical name.  (I'm not sure 
		// if that second step is necessary, I've seen something about 
		// "aliases" in the docs.)
		FOREACH( RString, portNames, portName )
		{
			jack_port_t *out = jack_port_by_name( client, *portName );
			// Make sure the port is a sink.
			if( ! ( jack_port_flags( out ) & JackPortIsInput ) )
				continue;

			if( out != NULL )
			{
				if( port_out_l == NULL )
					port_out_l = jack_port_name( out );
				else
				{
					port_out_r = jack_port_name( out );
					break;
				}
			}
		}
		if( port_out_l == NULL )
			return "All specified sinks are invalid.";
		
		if( port_out_r == NULL )
			// Only found one valid sink. Going mono!
			port_out_r = port_out_l;
	}
Esempio n. 22
0
void JACKInput::Init() {

	m_message_queue.Reset(RING_BUFFER_SIZE * m_channels * sizeof(float));

	m_jack_client = jack_client_open("SimpleScreenRecorder", JackNoStartServer, NULL);
	if(m_jack_client == NULL) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not connect to JACK!"));
		throw JACKException();
	}

	m_jack_ports.resize(m_channels, NULL);
	for(unsigned int i = 0; i < m_channels; ++i) {
		std::string port_name = "in_" + NumToString(i + 1);
		m_jack_ports[i] = jack_port_register(m_jack_client, port_name.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
		if(m_jack_ports[i] == NULL) {
			Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not create JACK port!"));
			throw JACKException();
		}
	}

	if(jack_set_process_callback(m_jack_client, ProcessCallback, this) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not set JACK process callback!"));
		throw JACKException();
	}
	if(jack_set_sample_rate_callback(m_jack_client, SampleRateCallback, this) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not set JACK sample rate callback!"));
		throw JACKException();
	}
	if(jack_set_xrun_callback(m_jack_client, XRunCallback, this) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not set JACK xrun callback!"));
		throw JACKException();
	}
	if(jack_set_port_connect_callback(m_jack_client, PortConnectCallback, this) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not set JACK port connect callback!"));
		throw JACKException();
	}

	if(jack_activate(m_jack_client) != 0) {
		Logger::LogError("[JACKInput::Init] " + Logger::tr("Error: Could not activate JACK client!"));
		throw JACKException();
	}

	for(unsigned int i = 0; i < m_channels; ++i) {
		std::string port_name_full = std::string(jack_get_client_name(m_jack_client)) + ":in_" + NumToString(i + 1);
		if(m_connect_system_capture) {
			std::string capture_name = "system:capture_" + NumToString(i + 1);
			Logger::LogInfo("[JACKInput::Init] " + Logger::tr("Connecting port %1 to %2.")
							.arg(QString::fromStdString(capture_name)).arg(QString::fromStdString(port_name_full)));
			jack_connect(m_jack_client, capture_name.c_str(), port_name_full.c_str());
		}
		if(m_connect_system_playback) {
			std::string playback_name = "system:playback_" + NumToString(i + 1);
			jack_port_t *port = jack_port_by_name(m_jack_client, playback_name.c_str());
			if(port != NULL) {
				const char **connected_ports = jack_port_get_all_connections(m_jack_client, port);
				if(connected_ports != NULL) {
					for(const char **p = connected_ports; *p != NULL; ++p) {
						Logger::LogInfo("[JACKInput::Init] " + Logger::tr("Connecting port %1 to %2.")
										.arg(*p).arg(QString::fromStdString(port_name_full)));
						jack_connect(m_jack_client, *p, port_name_full.c_str());
					}
					jack_free(connected_ports);
				}
			}
		}

	}

	// start input thread
	m_should_stop = false;
	m_error_occurred = false;
	m_thread = std::thread(&JACKInput::InputThread, this);

}
Esempio n. 23
0
static gboolean cbox_jack_io_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
{
    struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)ct->user_data;
    struct cbox_io *io = jii->ioi.pio;
    gboolean handled = FALSE;
    if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        return cbox_execute_on(fb, NULL, "/client_type", "s", error, "JACK") &&
            cbox_execute_on(fb, NULL, "/client_name", "s", error, jii->client_name) &&
            cbox_execute_on(fb, NULL, "/external_tempo", "i", error, jii->external_tempo) &&
            cbox_io_process_cmd(io, fb, cmd, error, &handled);
    }
    else if (!strcmp(cmd->command, "/rename_midi_port") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *new_name = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (!midiout && !midiin)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port
            : ((struct cbox_jack_midi_input *)midiin)->port;
        char **pname = midiout ? &midiout->name : &midiin->name;
        if (0 != jack_port_rename_fn(jii->client, port, new_name))
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot set port name to '%s'", new_name);
            return FALSE;
        }
        g_free(*pname);
        *pname = g_strdup(new_name);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/rename_audio_port") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *new_name = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_audio_output *audioout = cbox_io_get_audio_output(io, NULL, &uuid);
        if (!audioout)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        if (0 != jack_port_rename_fn(jii->client, ((struct cbox_jack_audio_output *)audioout)->port, new_name))
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot set port name to '%s'", new_name);
            return FALSE;
        }
        g_free(audioout->name);
        audioout->name = g_strdup(new_name);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/autoconnect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *spec = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (midiout)
        {
            cbox_jack_midi_output_set_autoconnect((struct cbox_jack_midi_output *)midiout, spec);
            return TRUE;
        }
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        if (midiin)
        {
            cbox_jack_midi_input_set_autoconnect((struct cbox_jack_midi_input *)midiin, spec);
            return TRUE;
        }
        struct cbox_audio_output *audioout = cbox_io_get_audio_output(io, NULL, &uuid);
        if (audioout)
        {
            cbox_jack_audio_output_set_autoconnect((struct cbox_jack_audio_output *)audioout, spec);
            return TRUE;
        }
        g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
        return FALSE;
    }
    else if (!strcmp(cmd->command, "/disconnect_audio_output") && !strcmp(cmd->arg_types, "s"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_audio_output *audioout = cbox_io_get_audio_output(io, NULL, &uuid);
        if (!audioout)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        jack_port_disconnect(jii->client, ((struct cbox_jack_audio_output *)audioout)->port);
        return TRUE;
    }
    else if (!strncmp(cmd->command, "/disconnect_midi_", 17) && !strcmp(cmd->arg_types, "s"))
    {
        bool is_both = !strcmp(cmd->command + 17, "port");
        bool is_in = is_both || !strcmp(cmd->command + 17, "input");
        bool is_out = is_both || !strcmp(cmd->command + 17, "output");
        if (is_in || is_out) {
            const char *uuidstr = CBOX_ARG_S(cmd, 0);
            struct cbox_uuid uuid;
            if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
                return FALSE;
            struct cbox_midi_input *midiin = is_in ? cbox_io_get_midi_input(io, NULL, &uuid) : NULL;
            struct cbox_midi_output *midiout = is_out ? cbox_io_get_midi_output(io, NULL, &uuid) : NULL;
            if (!midiout && !midiin)
            {
                g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
                return FALSE;
            }
            jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port
                : ((struct cbox_jack_midi_input *)midiin)->port;
            jack_port_disconnect(jii->client, port);
            return TRUE;
        }
    }

    if (!strcmp(cmd->command, "/port_connect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *port_from = CBOX_ARG_S(cmd, 0);
        const char *port_to = CBOX_ARG_S(cmd, 1);
        int res = jack_connect(jii->client, port_from, port_to);
        if (res == EEXIST)
            res = 0;
        if (res)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot connect port '%s' to '%s'", port_from, port_to);
        return res == 0;
    }
    else if (!strcmp(cmd->command, "/port_disconnect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *port_from = CBOX_ARG_S(cmd, 0);
        const char *port_to = CBOX_ARG_S(cmd, 1);
        int res = jack_disconnect(jii->client, port_from, port_to);
        if (res)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot disconnect port '%s' from '%s'", port_from, port_to);
        return res == 0;
    }
    else if (!strcmp(cmd->command, "/get_connected_ports") && !strcmp(cmd->arg_types, "s"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        const char *name = CBOX_ARG_S(cmd, 0);
        jack_port_t *port = NULL;
        if (!strchr(name, ':')) {
            // try UUID
            struct cbox_uuid uuid;
            if (!cbox_uuid_fromstring(&uuid, name, error))
                return FALSE;
            struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
            if (midiout)
                port = ((struct cbox_jack_midi_output *)midiout)->port;
            else {
                struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
                if (midiin)
                    port = ((struct cbox_jack_midi_input *)midiin)->port;
            }
        }
        else
            port = jack_port_by_name(jii->client, name);
        if (!port)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", name);
            return FALSE;
        }
        const char** ports = jack_port_get_all_connections(jii->client, port);
        for (int i = 0; ports && ports[i]; i++)
        {
            if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
                return FALSE;
        }
        jack_free(ports);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_ports") && !strcmp(cmd->arg_types, "ssi"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        const char *mask = CBOX_ARG_S(cmd, 0);
        const char *type = CBOX_ARG_S(cmd, 1);
        uint32_t flags = CBOX_ARG_I(cmd, 2);
        const char** ports = jack_get_ports(jii->client, mask, type, flags);
        for (int i = 0; ports && ports[i]; i++)
        {
            if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
                return FALSE;
        }
        jack_free(ports);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/external_tempo") && !strcmp(cmd->arg_types, "i"))
    {
        jii->external_tempo = CBOX_ARG_I(cmd, 0);
        return TRUE;
    }

    //Metadata

    else if (!strcmp(cmd->command, "/set_property") && !strcmp(cmd->arg_types, "ssss"))
    //parameters: "client:port", key, value, type according to jack_property_t (empty or NULL for string)
    {
        const char *name = CBOX_ARG_S(cmd, 0);
        const char *key = CBOX_ARG_S(cmd, 1);
        const char *value = CBOX_ARG_S(cmd, 2);
        const char *type = CBOX_ARG_S(cmd, 3);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error)) //error message set inside
            return FALSE;

        if (jack_set_property(jii->client, subject, key, value, type)) // 0 on success
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Set property key:'%s' value: '%s' to port '%s' was not successful", key, value, name);
            return FALSE;
        }
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_property") && !strcmp(cmd->arg_types, "ss"))
    //parameters: "client:port", key
    //returns python key, value and type as strings
    {
        const char *name = CBOX_ARG_S(cmd, 0);
        const char *key = CBOX_ARG_S(cmd, 1);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error)) //error message set inside
            return FALSE;

        char* value = NULL;
        char* type = NULL;

        if (jack_get_property(subject, key, &value, &type)) // 0 on success, -1 if the subject has no key property.
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' does not have key '%s'", name, key);
            return FALSE;
        }

        char* returntype; //We need to call jack_free on type in any case so it can't be our own data.
        if (type == NULL)
             returntype = "";
        else
            returntype = type;

        if (!cbox_execute_on(fb, NULL, "/value", "ss", error, value, returntype)) //send return values to Python.
           return FALSE;

        jack_free(value);
        jack_free(type);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_properties") && !strcmp(cmd->arg_types, "s"))
    //parameters: "client:port"
    {
        const char *name = CBOX_ARG_S(cmd, 0);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error))  //error message set inside
            return FALSE;

        jack_description_t desc;
        if (!jack_get_properties(subject, &desc)) // 0 on success, -1 if no subject with any properties exists.
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' with uuid '%lli' does not have any properties", name, (long long)subject);
            return FALSE;
        }

        const char *returntype;
        for (uint32_t i = 0; i<desc.property_cnt ; i++)
        {
            if (desc.properties[i].type == NULL)
                 returntype = "";
            else
                returntype = desc.properties[i].type;
            if (!cbox_execute_on(fb, NULL, "/properties", "sss", error, desc.properties[i].key, desc.properties[i].data, returntype))
                return FALSE;
        }
        jack_free_description(&desc, 0); //if non-zero desc will also be passed to free()
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_all_properties") && !strcmp(cmd->arg_types, ""))
    {
        jack_description_t *descs;
        int counter;
        counter = jack_get_all_properties(&descs);
        const char *returntype;
        for (int j = 0; j < counter; j++)
        {
            jack_description_t *one_desc = &descs[j];
            for (uint32_t i = 0; i < one_desc->property_cnt ; i++)
            {
                if (one_desc->properties[i].type == NULL)
                    returntype = "";
                else
                    returntype = one_desc->properties[i].type;

                /*
                index = jack_uuid_to_index(one_desc->subject)
                portid = jack_port_by_id(jii->client, index);
                portname = jack_port_name(port);
                */
                if (!cbox_execute_on(fb, NULL, "/all_properties", "ssss",
                        error,
                        jack_port_name(jack_port_by_id(jii->client, jack_uuid_to_index(one_desc->subject))),
                        one_desc->properties[i].key,
                        one_desc->properties[i].data,
                        returntype))
                    return FALSE;
            }
            jack_free_description(one_desc, 0); //if non-zero one_desc will also be passed to free()
        }
        jack_free(descs);
        return TRUE;
    }


    else if (!strcmp(cmd->command, "/remove_property") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *name = CBOX_ARG_S(cmd, 0);
        const char *key = CBOX_ARG_S(cmd, 1);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error)) //error message set inside
            return FALSE;

        if (jack_remove_property(jii->client, subject, key)) // 0 on success, -1 otherwise
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Could not remove port '%s' key '%s'", name, key);
            return FALSE;
        }
        return TRUE;
    }

    else if (!strcmp(cmd->command, "/remove_properties") && !strcmp(cmd->arg_types, "s"))
    {
        const char *name = CBOX_ARG_S(cmd, 0);

        jack_uuid_t subject;
        if (!cbox_jack_io_get_jack_uuid_from_name(jii, name, &subject, error)) //error message set inside
            return FALSE;

        if (jack_remove_properties(jii->client, subject) == -1) // number of removed properties returned, -1 on error
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Could not remove properties of port '%s'", name);
            return FALSE;
        }
        return TRUE;
    }


    else if (!strcmp(cmd->command, "/remove_all_properties") && !strcmp(cmd->arg_types, ""))
    {
        if (jack_remove_all_properties(jii->client)) // 0 on success, -1 otherwise
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Remove all JACK properties was not successful");
            return FALSE;
        }
        return TRUE;
    }

    else
    {
        gboolean result = cbox_io_process_cmd(io, fb, cmd, error, &handled);
        if (!handled)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Unknown combination of target path and argument: '%s', '%s'", cmd->command, cmd->arg_types);
        return result;
    }
}
Esempio n. 24
0
int main(int argc, char *argv[])
{
	parse_arguments(argc, argv);
	jack_session_command_t *retval;
	int k,i,j;


	/* become a JACK client */
	if ((client = jack_client_open(package, JackNullOption, NULL)) == 0) {
		fprintf(stderr, "JACK server not running?\n");
		exit(1);
	}

	signal(SIGQUIT, signal_handler);
	signal(SIGTERM, signal_handler);
	signal(SIGHUP, signal_handler);
	signal(SIGINT, signal_handler);

	jack_on_shutdown(client, jack_shutdown, 0);

	jack_activate(client);


	retval = jack_session_notify( client, NULL, notify_type, save_path );
	for(i=0; retval[i].uuid; i++ ) {
		printf( "export SESSION_DIR=\"%s%s/\"\n", save_path, retval[i].client_name );
		printf( "%s &\n", retval[i].command );
		add_uuid_mapping(retval[i].uuid); 
	}

	printf( "sleep 10\n" );

	for(k=0; retval[k].uuid; k++ ) {

		char* port_regexp = alloca( jack_client_name_size()+3 );
		char* client_name = jack_get_client_name_by_uuid( client, retval[k].uuid );
		snprintf( port_regexp, jack_client_name_size()+3, "%s:.*", client_name );
		jack_free(client_name);
		const char **ports = jack_get_ports( client, port_regexp, NULL, 0 );
		if( !ports ) {
			continue;
		}
		for (i = 0; ports[i]; ++i) {
			const char **connections;
			if ((connections = jack_port_get_all_connections (client, jack_port_by_name(client, ports[i]))) != 0) {
				for (j = 0; connections[j]; j++) {
					char *src = map_port_name_to_uuid_port( ports[i] ); 
					char *dst = map_port_name_to_uuid_port( connections[j] ); 
					printf( "jack_connect -u \"%s\" \"%s\"\n", src, dst );
				}
				jack_free (connections);
			} 
		}
		jack_free(ports);

	}
	jack_session_commands_free(retval);

	jack_client_close(client);

	return 0;
}
Esempio n. 25
0
void
setup_ports (int sources, char *source_names[], jack_thread_info_t *info)
{
	unsigned int i;
	size_t in_size;
	const char **jack_ports;

	/* Allocate data structures that depend on the number of ports. */
	nports = sources;
	ports = (jack_port_t **) malloc (sizeof (jack_port_t *) * nports);
	in_size =  nports * sizeof (jack_default_audio_sample_t *);
	rb =(jack_ringbuffer_t **)malloc(sizeof (jack_ringbuffer_t *) * (sources));
	for(i=0;i<sources;i++){
		rb[i]=jack_ringbuffer_create(info->rb_size);
	}

	for (i = 0; i < nports; i++) {
		char name[64];

		sprintf (name, "in_%d", i+1);

		if ((ports[i] = jack_port_register (info->client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0)) == 0) {
			fprintf (stderr, "cannot register input port \"%s\"!\n", name);
			jack_client_close (info->client);
			exit (1);
		}
	}

	if (!getFirstTwo) {
		for (i = 0; i < nports; i++) {
			if (jack_connect (info->client, source_names[i], jack_port_name (ports[i]))) {
				fprintf (stderr, "cannot connect input port %s to %s\n", jack_port_name (ports[i]), source_names[i]);
				jack_client_close (info->client);
				exit (1);
			} 
		}
	}
	else {
		jack_ports = jack_get_ports (info->client, NULL, NULL, 0);

		int portNum = 0;
		for (i = 0; jack_ports[i]; ++i) {
			if (portNum >= 2) {
				break;
			}
			if (strstr(jack_ports[i], portMatch)) {
				jack_port_t *port = jack_port_by_name (info->client, jack_ports[i]);
				if (port) {
					int flags = jack_port_flags (port);
					if (flags & JackPortIsOutput) {
						printf("registering with %s\n", jack_ports[i]);
						if (jack_connect (info->client, jack_ports[i], jack_port_name(ports[portNum]))) {
							fprintf (stderr, "cannot connect input port %s to %s\n", jack_port_name (ports[portNum]), jack_ports[i]);
							jack_client_close (info->client);
							exit (1);
						}
						portNum++;
					}
				}
			}
		}
		if (portNum < 2) {
			printf("Could not find at least two output ports matching (%s)\n", portMatch);
			jack_client_close (info->client);
			exit (1);
		}

	}

	info->can_process = 1;		/* process() can start, now */
}
Esempio n. 26
0
static int refresh_devices_bare(SoundIoPrivate *si) {
    SoundIo *soundio = &si->pub;
    SoundIoJack *sij = &si->backend_data.jack;

    if (sij->is_shutdown)
        return SoundIoErrorBackendDisconnected;


    SoundIoDevicesInfo *devices_info = allocate<SoundIoDevicesInfo>(1);
    if (!devices_info)
        return SoundIoErrorNoMem;

    devices_info->default_output_index = -1;
    devices_info->default_input_index = -1;
    const char **port_names = jack_get_ports(sij->client, nullptr, nullptr, 0);
    if (!port_names) {
        soundio_destroy_devices_info(devices_info);
        return SoundIoErrorNoMem;
    }

    SoundIoList<SoundIoJackClient> clients = {0};
    const char **port_name_ptr = port_names;
    for (; *port_name_ptr; port_name_ptr += 1) {
        const char *client_and_port_name = *port_name_ptr;
        int client_and_port_name_len = strlen(client_and_port_name);
        jack_port_t *jport = jack_port_by_name(sij->client, client_and_port_name);
        if (!jport) {
            // This refresh devices scan is already outdated. Just give up and
            // let refresh_devices be called again.
            jack_free(port_names);
            soundio_destroy_devices_info(devices_info);
            return SoundIoErrorInterrupted;
        }

        int flags = jack_port_flags(jport);
        const char *port_type = jack_port_type(jport);
        if (strcmp(port_type, JACK_DEFAULT_AUDIO_TYPE) != 0) {
            // we don't know how to support such a port
            continue;
        }

        SoundIoDeviceAim aim = (flags & JackPortIsInput) ?
            SoundIoDeviceAimOutput : SoundIoDeviceAimInput;
        bool is_physical = flags & JackPortIsPhysical;

        const char *client_name = nullptr;
        const char *port_name = nullptr;
        int client_name_len;
        int port_name_len;
        split_str(client_and_port_name, client_and_port_name_len, ':',
                &client_name, &client_name_len, &port_name, &port_name_len);
        if (!client_name || !port_name) {
            // device does not have colon, skip it
            continue;
        }
        SoundIoJackClient *client = find_or_create_client(&clients, aim, is_physical,
                client_name, client_name_len);
        if (!client) {
            jack_free(port_names);
            soundio_destroy_devices_info(devices_info);
            return SoundIoErrorNoMem;
        }
        if (client->port_count >= SOUNDIO_MAX_CHANNELS) {
            // we hit the channel limit, skip the leftovers
            continue;
        }
        SoundIoJackPort *port = &client->ports[client->port_count++];
        port->full_name = client_and_port_name;
        port->full_name_len = client_and_port_name_len;
        port->name = port_name;
        port->name_len = port_name_len;
        port->channel_id = soundio_parse_channel_id(port_name, port_name_len);

        jack_latency_callback_mode_t latency_mode = (aim == SoundIoDeviceAimOutput) ?
            JackPlaybackLatency : JackCaptureLatency;
        jack_port_get_latency_range(jport, latency_mode, &port->latency_range);
    }

    for (int i = 0; i < clients.length; i += 1) {
        SoundIoJackClient *client = &clients.at(i);
        if (client->port_count <= 0)
            continue;

        SoundIoDevicePrivate *dev = allocate<SoundIoDevicePrivate>(1);
        if (!dev) {
            jack_free(port_names);
            soundio_destroy_devices_info(devices_info);
            return SoundIoErrorNoMem;
        }
        SoundIoDevice *device = &dev->pub;
        SoundIoDeviceJack *dj = &dev->backend_data.jack;
        int description_len = client->name_len + 3 + 2 * client->port_count;
        for (int port_index = 0; port_index < client->port_count; port_index += 1) {
            SoundIoJackPort *port = &client->ports[port_index];

            description_len += port->name_len;
        }

        dev->destruct = destruct_device;

        device->ref_count = 1;
        device->soundio = soundio;
        device->is_raw = false;
        device->aim = client->aim;
        device->id = soundio_str_dupe(client->name, client->name_len);
        device->name = allocate<char>(description_len);
        device->current_format = SoundIoFormatFloat32NE;
        device->sample_rate_count = 1;
        device->sample_rates = &dev->prealloc_sample_rate_range;
        device->sample_rates[0].min = sij->sample_rate;
        device->sample_rates[0].max = sij->sample_rate;
        device->sample_rate_current = sij->sample_rate;

        device->software_latency_current = sij->period_size / (double) sij->sample_rate;
        device->software_latency_min = sij->period_size / (double) sij->sample_rate;
        device->software_latency_max = sij->period_size / (double) sij->sample_rate;

        dj->port_count = client->port_count;
        dj->ports = allocate<SoundIoDeviceJackPort>(dj->port_count);

        if (!device->id || !device->name || !dj->ports) {
            jack_free(port_names);
            soundio_device_unref(device);
            soundio_destroy_devices_info(devices_info);
            return SoundIoErrorNoMem;
        }

        for (int port_index = 0; port_index < client->port_count; port_index += 1) {
            SoundIoJackPort *port = &client->ports[port_index];
            SoundIoDeviceJackPort *djp = &dj->ports[port_index];
            djp->full_name = soundio_str_dupe(port->full_name, port->full_name_len);
            djp->full_name_len = port->full_name_len;
            djp->channel_id = port->channel_id;
            djp->latency_range = port->latency_range;

            if (!djp->full_name) {
                jack_free(port_names);
                soundio_device_unref(device);
                soundio_destroy_devices_info(devices_info);
                return SoundIoErrorNoMem;
            }
        }

        memcpy(device->name, client->name, client->name_len);
        memcpy(&device->name[client->name_len], ": ", 2);
        int index = client->name_len + 2;
        for (int port_index = 0; port_index < client->port_count; port_index += 1) {
            SoundIoJackPort *port = &client->ports[port_index];
            memcpy(&device->name[index], port->name, port->name_len);
            index += port->name_len;
            if (port_index + 1 < client->port_count) {
                memcpy(&device->name[index], ", ", 2);
                index += 2;
            }
        }

        device->current_layout.channel_count = client->port_count;
        bool any_invalid = false;
        for (int port_index = 0; port_index < client->port_count; port_index += 1) {
            SoundIoJackPort *port = &client->ports[port_index];
            device->current_layout.channels[port_index] = port->channel_id;
            any_invalid = any_invalid || (port->channel_id == SoundIoChannelIdInvalid);
        }
        if (any_invalid) {
            const struct SoundIoChannelLayout *layout = soundio_channel_layout_get_default(client->port_count);
            if (layout)
                device->current_layout = *layout;
        } else {
            soundio_channel_layout_detect_builtin(&device->current_layout);
        }

        device->layout_count = 1;
        device->layouts = &device->current_layout;
        device->format_count = 1;
        device->formats = &dev->prealloc_format;
        device->formats[0] = device->current_format;

        SoundIoList<SoundIoDevice *> *device_list;
        if (device->aim == SoundIoDeviceAimOutput) {
            device_list = &devices_info->output_devices;
            if (devices_info->default_output_index < 0 && client->is_physical)
                devices_info->default_output_index = device_list->length;
        } else {
            assert(device->aim == SoundIoDeviceAimInput);
            device_list = &devices_info->input_devices;
            if (devices_info->default_input_index < 0 && client->is_physical)
                devices_info->default_input_index = device_list->length;
        }

        if (device_list->append(device)) {
            soundio_device_unref(device);
            soundio_destroy_devices_info(devices_info);
            return SoundIoErrorNoMem;
        }

    }
    jack_free(port_names);

    soundio_destroy_devices_info(si->safe_devices_info);
    si->safe_devices_info = devices_info;

    return 0;
}
Esempio n. 27
0
File: connect.c Progetto: 7890/tools
int
main (int argc, char *argv[])
{
    jack_client_t *client;
    jack_status_t status;
    char *server_name = NULL;
    int c;
    int option_index;
    jack_options_t options = JackNoStartServer;
    char *my_name = strrchr(argv[0], '/');
    jack_port_t *src_port = 0;
    jack_port_t *dst_port = 0;
    jack_port_t *port1 = 0;
    jack_port_t *port2 = 0;
    char portA[300];
    char portB[300];
    int use_uuid=0;
    int connecting, disconnecting;
    int port1_flags, port2_flags;
    int rc = 1;

    struct option long_options[] = {
        { "server", 1, 0, 's' },
        { "help", 0, 0, 'h' },
        { "version", 0, 0, 'v' },
        { "uuid", 0, 0, 'u' },
        { 0, 0, 0, 0 }
    };

    while ((c = getopt_long (argc, argv, "s:hvu", long_options, &option_index)) >= 0) {
        switch (c) {
        case 's':
            server_name = (char *) malloc (sizeof (char) * strlen(optarg));
            strcpy (server_name, optarg);
            options |= JackServerName;
            break;
        case 'u':
            use_uuid = 1;
            break;
        case 'h':
            show_usage (my_name);
            return 1;
            break;
        case 'v':
            show_version (my_name);
            return 1;
            break;
        default:
            show_usage (my_name);
            return 1;
            break;
        }
    }

    connecting = disconnecting = FALSE;
    if (my_name == 0) {
        my_name = argv[0];
    } else {
        my_name ++;
    }

    if (strstr(my_name, "disconnect")) {
        disconnecting = 1;
    } else if (strstr(my_name, "connect")) {
        connecting = 1;
    } else {
        fprintf(stderr, "ERROR! client should be called jack_connect or jack_disconnect. client is called %s\n", my_name);
        return 1;
    }

    if (argc < 3) {
        show_usage(my_name);
        return 1;
    }

    /* try to become a client of the JACK server */

    if ((client = jack_client_open (my_name, options, &status, server_name)) == 0) {
        fprintf (stderr, "jack server not running?\n");
        return 1;
    }

    /* find the two ports */

    if( use_uuid ) {
        char *tmpname;
        char *clientname;
        char *portname;
        tmpname = strdup( argv[argc-1] );
        portname = strchr( tmpname, ':' );
        portname[0] = '\0';
        portname+=1;
        clientname = jack_get_client_name_by_uuid( client, tmpname );
        if( clientname ) {

            snprintf( portA, sizeof(portA), "%s:%s", clientname, portname );
            jack_free( clientname );
        } else {
            snprintf( portA, sizeof(portA), "%s", argv[argc-1] );
        }
        free( tmpname );

        tmpname = strdup( argv[argc-2] );
        portname = strchr( tmpname, ':' );
        portname[0] = '\0';
        portname+=1;
        clientname = jack_get_client_name_by_uuid( client, tmpname );
        if( clientname ) {
            snprintf( portB, sizeof(portB), "%s:%s", clientname, portname );
            jack_free( clientname );
        } else {
            snprintf( portB, sizeof(portB), "%s", argv[argc-2] );
        }

        free( tmpname );

    } else {
        snprintf( portA, sizeof(portA), "%s", argv[argc-1] );
        snprintf( portB, sizeof(portB), "%s", argv[argc-2] );
    }
    if ((port1 = jack_port_by_name(client, portA)) == 0) {
        fprintf (stderr, "ERROR %s not a valid port\n", portA);
        goto exit;
    }
    if ((port2 = jack_port_by_name(client, portB)) == 0) {
        fprintf (stderr, "ERROR %s not a valid port\n", portB);
        goto exit;
    }

    port1_flags = jack_port_flags (port1);
    port2_flags = jack_port_flags (port2);

    if (port1_flags & JackPortIsInput) {
        if (port2_flags & JackPortIsOutput) {
            src_port = port2;
            dst_port = port1;
        }
    } else {
        if (port2_flags & JackPortIsInput) {
            src_port = port1;
            dst_port = port2;
        }
    }

    if (!src_port || !dst_port) {
        fprintf (stderr, "arguments must include 1 input port and 1 output port\n");
        goto exit;
    }

    /* connect the ports. Note: you can't do this before
       the client is activated (this may change in the future).
    */

    if (connecting) {
        if (jack_connect(client, jack_port_name(src_port), jack_port_name(dst_port))) {
            goto exit;
        }
    }
    if (disconnecting) {
        if (jack_disconnect(client, jack_port_name(src_port), jack_port_name(dst_port))) {
            goto exit;
        }
    }

    /* everything was ok, so setting exitcode to 0 */
    rc = 0;

exit:
    jack_client_close (client);
    exit (rc);
}
Esempio n. 28
0
int main(int argc, char *argv[])
{
    unsigned int i;
    int opt;
    int help = 0;
    int console = 0;
    char port_name[32];
    pthread_t dt;
#ifdef HAVE_LASH
    lash_args_t *lash_args = lash_extract_args(&argc, &argv);
     lash_event_t *event;
#endif

    auto_begin_threshold = db2lin(DEFAULT_AUTO_BEGIN_THRESHOLD);
    auto_end_threshold = db2lin(DEFAULT_AUTO_END_THRESHOLD);

    while ((opt = getopt(argc, argv, "hic:t:n:p:f:sab:e:T:")) != -1) {
	switch (opt) {
	case 'h':
	    help = 1;
	    break;
	case 'i':
	    console = 1;
	    break;
	case 'c':
	    num_ports = atoi(optarg);
	    DEBUG(1, "ports: %d\n", num_ports);
	    break;
	case 't':
	    buf_length = atoi(optarg);
	    DEBUG(1, "buffer: %ds\n", buf_length);
	    break;
	case 'n':
	    client_name = optarg;
	    DEBUG(1, "client name: %s\n", client_name);
	    break;
	case 'p':
	    prefix = optarg;
	    DEBUG(1, "prefix: %s\n", prefix);
	    break;
	case 'f':
	    format_name = optarg;
	    break;
	case 's':
	    safe_filename = 1;
	    break;
	case 'a':
	    auto_record = 1;
	    break;
	case 'b':
	    auto_begin_threshold = db2lin(atof(optarg));
	    break;
	case 'e':
	    auto_end_threshold = db2lin(atof(optarg));
	    break;
	case 'T':
	    auto_end_time = atoi(optarg);
	    break;
	default:
	    num_ports = 0;
	    break;
	}
    }

    if (optind != argc) {
	num_ports = argc - optind;
    }

    if (num_ports < 1 || num_ports > MAX_PORTS || help) {
	fprintf(stderr, "Usage %s: [-h] [-i] [-c channels] [-n jack-name]\n\t"
			"[-t buffer-length] [-p file prefix] [-f format]\n\t"
			"[-a] [-b begin-threshold] [-e end-threshold] [-T end-time]\n\t"
			"[port-name ...]\n\n", argv[0]);
	fprintf(stderr, "\t-h\tshow this help\n");
	fprintf(stderr, "\t-i\tinteractive mode (console instead of X11) also enabled\n\t\tif DISPLAY is unset\n");
	fprintf(stderr, "\t-c\tspecify number of recording channels\n");
	fprintf(stderr, "\t-n\tspecify the JACK name timemachine will use\n");
	fprintf(stderr, "\t-t\tspecify the pre-recording buffer length\n");
	fprintf(stderr, "\t-p\tspecify the saved file prefix, may include path\n");
	fprintf(stderr, "\t-s\tuse safer characters in filename (windows compatibility)\n");
	fprintf(stderr, "\t-f\tspecify the saved file format\n");
	fprintf(stderr, "\t-a\tenable automatic sound-triggered recording\n");
	fprintf(stderr, "\t-b\tspecify threshold above which automatic recording will begin\n");
	fprintf(stderr, "\t-e\tspecify threshold below which automatic recording will end\n");
	fprintf(stderr, "\t-T\tspecify silence length before automatic recording ends\n");
	fprintf(stderr, "\n");
	fprintf(stderr, "\tchannels must be in the range 1-8, default %d\n",
			DEFAULT_NUM_PORTS);
	fprintf(stderr, "\tjack-name, default \"%s\"\n", DEFAULT_CLIENT_NAME);
	fprintf(stderr, "\tfile-prefix, default \"%s\"\n", DEFAULT_PREFIX);
	fprintf(stderr, "\tbuffer-length, default %d secs\n", DEFAULT_BUF_LENGTH);
	fprintf(stderr, "\tformat, default '%s', options: wav, w64\n", DEFAULT_FORMAT);
	fprintf(stderr, "\tbegin-threshold, default %.1f dB\n", DEFAULT_AUTO_BEGIN_THRESHOLD);
	fprintf(stderr, "\tend-threshold, default %.1f dB\n", DEFAULT_AUTO_END_THRESHOLD);
	fprintf(stderr, "\tend-time, default %d secs\n", DEFAULT_AUTO_END_TIME);
	fprintf(stderr, "\n");
	fprintf(stderr, "specifying port names to connect to on the command line overrides -c\n\n");
	exit(1);
    }

    if (!strcasecmp(format_name, "wav")) {
	format_sf = SF_FORMAT_WAV | SF_FORMAT_FLOAT;
    }
#ifdef HAVE_W64
    if (!strcasecmp(format_name, "w64")) {
	format_sf = SF_FORMAT_W64 | SF_FORMAT_FLOAT;
    }
#endif

    if (format_sf == 0) {
	fprintf(stderr, "Unknown format '%s'\n", format_name);
    }

    /* Register with jack */
    if ((client = jack_client_open(client_name, 0, NULL)) == 0) {
	DEBUG(0, "jack server not running?\n");
	exit(1);
    }
    DEBUG(1, "registering as %s\n", client_name);

    process_init(buf_length);

#ifdef HAVE_LASH
    lash_client = lash_init (lash_args, "TimeMachine",
                     0, /* would be LASH_Config_Data_Set etc. */
                     LASH_PROTOCOL (2,0));
    if (!lash_client) {
	DEBUG(1, "could not initialise LASH\n");
    }
    event = lash_event_new_with_type(LASH_Client_Name);
    lash_event_set_string(event, client_name);
    lash_send_event(lash_client, event);
#endif

    jack_set_process_callback(client, process, 0);

    if (jack_activate(client)) {
	DEBUG(0, "cannot activate JACK client");
	exit(1);
    }
#ifdef HAVE_LASH
    lash_jack_client_name(lash_client, client_name);
#endif

    /* Create the jack ports */
    for (i = 0; i < num_ports; i++) {
	jack_port_t *port;

	snprintf(port_name, 31, "in_%d", i + 1);
	ports[i] = jack_port_register(client, port_name,
				      JACK_DEFAULT_AUDIO_TYPE,
				      JackPortIsInput, 0);
	if (optind != argc) {
	    port = jack_port_by_name(client, argv[optind+i]);
	    if (port == NULL) {
		fprintf(stderr, "Can't find port '%s'\n", port_name);
		continue;
	    }
	    if (jack_connect(client, argv[optind+i], jack_port_name(ports[i]))) {
		fprintf(stderr, "Cannot connect port '%s' to '%s'\n",
			argv[optind+i], jack_port_name(ports[i]));
	    }
	}
    }

    /* Start the disk thread */
    pthread_create(&dt, NULL, (void *)&writer_thread, NULL);

#ifdef HAVE_LIBREADLINE
    if (console || !getenv("DISPLAY") || getenv("DISPLAY")[0] == '\0') {
#ifdef HAVE_LIBLO
      lo_server_thread st = lo_server_thread_new(OSC_PORT, NULL);
      if (st) {
	  lo_server_thread_add_method(st, "/start", "", osc_handler_nox, (void *)1);
	  lo_server_thread_add_method(st, "/stop", "", osc_handler_nox, (void *)0);
	  lo_server_thread_start(st);
	  printf("Listening for OSC requests on osc.udp://localhost:%s\n",
	    OSC_PORT);
      }
#endif

      int done = 0;
      while (!done) {
	char *line = readline("TimeMachine> ");
	if (!line) {
	  printf("EOF\n");
	  break;
	}
	if (line && *line) {
	  add_history(line);
	  if (strncmp(line, "q", 1) == 0) done = 1;
	  else if (strncmp(line, "start", 3) == 0) recording_start();
	  else if (strncmp(line, "stop", 3) == 0) recording_stop();
	  else if (strncmp(line, "help", 3) == 0) {
	    printf("Commands: start stop\n");
	  } else {
	    printf("Unknown command\n");
          }
	}
	free(line);
      }
    } else
#endif
    {
      gtk_init(&argc, &argv);

      add_pixmap_directory(PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
      add_pixmap_directory("pixmaps");
      add_pixmap_directory("../pixmaps");

      img_on = create_pixbuf("on.png");
      img_off = create_pixbuf("off.png");
      img_busy = create_pixbuf("busy.png");
      icon_on = create_pixbuf("on-icon.png");
      icon_off = create_pixbuf("off-icon.png");

      main_window = create_window(client_name);
      gtk_window_set_icon(GTK_WINDOW(main_window), icon_off);
      gtk_widget_show(main_window);

      bind_meters();
      g_timeout_add(100, meter_tick, NULL);

#ifdef HAVE_LIBLO
    lo_server_thread st = lo_server_thread_new(OSC_PORT, NULL);
    if (st) {
	lo_server_thread_add_method(st, "/start", "", osc_handler, (void *)1);
	lo_server_thread_add_method(st, "/stop", "", osc_handler, (void *)0);
	lo_server_thread_start(st);
	printf("Listening for OSC requests on osc.udp://localhost:%s\n",
	       OSC_PORT);
    }
#endif

#ifdef HAVE_LASH
      gtk_idle_add(idle_cb, lash_client);
#endif

      gtk_main();
    }

    cleanup();

    /* We can't ever get here, but it keeps gcc quiet */
    return 0;
}
Esempio n. 29
0
static gboolean cbox_jack_io_process_cmd(struct cbox_command_target *ct, struct cbox_command_target *fb, struct cbox_osc_command *cmd, GError **error)
{
    struct cbox_jack_io_impl *jii = (struct cbox_jack_io_impl *)ct->user_data;
    struct cbox_io *io = jii->ioi.pio;
    gboolean handled = FALSE;
    if (!strcmp(cmd->command, "/status") && !strcmp(cmd->arg_types, ""))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        return cbox_execute_on(fb, NULL, "/client_type", "s", error, "JACK") &&
            cbox_execute_on(fb, NULL, "/client_name", "s", error, jii->client_name) &&
            cbox_io_process_cmd(io, fb, cmd, error, &handled);
    }
    else if (!strcmp(cmd->command, "/rename_midi_port") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *new_name = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (!midiout && !midiin)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port 
            : ((struct cbox_jack_midi_input *)midiin)->port;
        char **pname = midiout ? &midiout->name : &midiin->name;
        if (0 != jack_port_set_name(port, new_name))
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot set port name to '%s'", new_name);
            return FALSE;
        }
        g_free(*pname);
        *pname = g_strdup(new_name);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/autoconnect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        const char *spec = CBOX_ARG_S(cmd, 1);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (midiout)
        {
            cbox_jack_midi_output_set_autoconnect((struct cbox_jack_midi_output *)midiout, spec);
            return TRUE;
        }
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        if (midiin)
        {
            cbox_jack_midi_input_set_autoconnect((struct cbox_jack_midi_input *)midiin, spec);
            return TRUE;
        }
        g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
        return FALSE;
    }
    else if (!strcmp(cmd->command, "/disconnect_midi_port") && !strcmp(cmd->arg_types, "s"))
    {
        const char *uuidstr = CBOX_ARG_S(cmd, 0);
        struct cbox_uuid uuid;
        if (!cbox_uuid_fromstring(&uuid, uuidstr, error))
            return FALSE;
        struct cbox_midi_input *midiin = cbox_io_get_midi_input(io, NULL, &uuid);
        struct cbox_midi_output *midiout = cbox_io_get_midi_output(io, NULL, &uuid);
        if (!midiout && !midiin)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", uuidstr);
            return FALSE;
        }
        jack_port_t *port = midiout ? ((struct cbox_jack_midi_output *)midiout)->port 
            : ((struct cbox_jack_midi_input *)midiin)->port; 
        jack_port_disconnect(jii->client, port);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/port_connect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *port_from = CBOX_ARG_S(cmd, 0);
        const char *port_to = CBOX_ARG_S(cmd, 1);
        int res = jack_connect(jii->client, port_from, port_to);
        if (res == EEXIST)
            res = 0;
        if (res)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot connect port '%s' to '%s'", port_from, port_to);
        return res == 0;
    }
    else if (!strcmp(cmd->command, "/port_disconnect") && !strcmp(cmd->arg_types, "ss"))
    {
        const char *port_from = CBOX_ARG_S(cmd, 0);
        const char *port_to = CBOX_ARG_S(cmd, 1);
        int res = jack_disconnect(jii->client, port_from, port_to);
        if (res)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Cannot disconnect port '%s' from '%s'", port_from, port_to);
        return res == 0;
    }
    else if (!strcmp(cmd->command, "/get_connected_ports") && !strcmp(cmd->arg_types, "s"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        const char *name = CBOX_ARG_S(cmd, 0);
        jack_port_t *port = jack_port_by_name(jii->client, name);
        if (!port)
        {
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Port '%s' not found", name);
            return FALSE;
        }
        const char** ports = jack_port_get_all_connections(jii->client, port);
        for (int i = 0; ports && ports[i]; i++)
        {
            if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
                return FALSE;
        }
        jack_free(ports);
        return TRUE;
    }
    else if (!strcmp(cmd->command, "/get_ports") && !strcmp(cmd->arg_types, "ssi"))
    {
        if (!cbox_check_fb_channel(fb, cmd->command, error))
            return FALSE;
        const char *mask = CBOX_ARG_S(cmd, 0);
        const char *type = CBOX_ARG_S(cmd, 1);
        uint32_t flags = CBOX_ARG_I(cmd, 2);
        const char** ports = jack_get_ports(jii->client, mask, type, flags);
        for (int i = 0; ports && ports[i]; i++)
        {
            if (!cbox_execute_on(fb, NULL, "/port", "s", error, ports[i]))
                return FALSE;
        }
        jack_free(ports);
        return TRUE;
    }
    else
    {
        gboolean result = cbox_io_process_cmd(io, fb, cmd, error, &handled);
        if (!handled)
            g_set_error(error, CBOX_MODULE_ERROR, CBOX_MODULE_ERROR_FAILED, "Unknown combination of target path and argument: '%s', '%s'", cmd->command, cmd->arg_types);
        return result;
    }
}
Esempio n. 30
0
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
                           PaStream** s,
                           const PaStreamParameters *inputParameters,
                           const PaStreamParameters *outputParameters,
                           double sampleRate,
                           unsigned long framesPerBuffer,
                           PaStreamFlags streamFlags,
                           PaStreamCallback *streamCallback,
                           void *userData )
{
    PaError result = paNoError;
    PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi;
    PaJackStream *stream = 0;
    char port_string[100];
    char regex_pattern[100];
    const char **jack_ports;
    int jack_max_buffer_size = jack_get_buffer_size( jackHostApi->jack_client );
    int i;
    int inputChannelCount, outputChannelCount;
    PaSampleFormat inputSampleFormat, outputSampleFormat;

    /* the client has no say over the frames per callback */

    if( framesPerBuffer == paFramesPerBufferUnspecified )
        framesPerBuffer = jack_max_buffer_size;

    /* Preliminary checks */

    if( inputParameters )
    {
        inputChannelCount = inputParameters->channelCount;
        inputSampleFormat = inputParameters->sampleFormat;

        /* unless alternate device specification is supported, reject the use of
            paUseHostApiSpecificDeviceSpecification */

        if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
            return paInvalidDevice;

        /* check that input device can support inputChannelCount */
        if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
            return paInvalidChannelCount;

        /* validate inputStreamInfo */
        if( inputParameters->hostApiSpecificStreamInfo )
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
    }
    else
    {
        inputChannelCount = 0;
    }

    if( outputParameters )
    {
        outputChannelCount = outputParameters->channelCount;
        outputSampleFormat = outputParameters->sampleFormat;

        /* unless alternate device specification is supported, reject the use of
            paUseHostApiSpecificDeviceSpecification */

        if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
            return paInvalidDevice;

        /* check that output device can support inputChannelCount */
        if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
            return paInvalidChannelCount;

        /* validate outputStreamInfo */
        if( outputParameters->hostApiSpecificStreamInfo )
            return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
    }
    else
    {
        outputChannelCount = 0;
    }

    /* ... check that the sample rate exactly matches the ONE acceptable rate */

#define ABS(x) ( (x) > 0 ? (x) : -(x) )
    if( ABS(sampleRate - hostApi->deviceInfos[0]->defaultSampleRate) > 1 )
       return paInvalidSampleRate;
#undef ABS

    /* Allocate memory for structuures */

#define MALLOC(size) \
    (PaUtil_GroupAllocateMemory( stream->stream_memory, (size) ))

#define MEMVERIFY(ptr) \
    if( (ptr) == NULL ) \
    { \
        result = paInsufficientMemory; \
        goto error; \
    }

    stream = (PaJackStream*)PaUtil_AllocateMemory( sizeof(PaJackStream) );
    MEMVERIFY( stream );

    stream->stream_memory = PaUtil_CreateAllocationGroup();
    stream->jack_client = jackHostApi->jack_client;
    PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );

    stream->local_input_ports =
        (jack_port_t**) MALLOC(sizeof(jack_port_t*) * inputChannelCount );
    stream->local_output_ports =
        (jack_port_t**) MALLOC( sizeof(jack_port_t*) * outputChannelCount );
    stream->remote_output_ports =
        (jack_port_t**) MALLOC( sizeof(jack_port_t*) * inputChannelCount );
    stream->remote_input_ports =
        (jack_port_t**) MALLOC( sizeof(jack_port_t*) * outputChannelCount );

    MEMVERIFY( stream->local_input_ports );
    MEMVERIFY( stream->local_output_ports );
    MEMVERIFY( stream->remote_input_ports );
    MEMVERIFY( stream->remote_output_ports );

    stream->num_incoming_connections = inputChannelCount;
    stream->num_outgoing_connections = outputChannelCount;

    if( streamCallback )
    {
        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
              &jackHostApi->callbackStreamInterface, streamCallback, userData );
    }
    else
    {
        /* we do not support blocking I/O */
        return paBadIODeviceCombination;
    }

    /* create the JACK ports.  We cannot connect them until audio
     * processing begins */

    for( i = 0; i < inputChannelCount; i++ )
    {
        sprintf( port_string, "in_%d", i );
        stream->local_input_ports[i] = jack_port_register(
              jackHostApi->jack_client, port_string,
              JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 );
    }

    for( i = 0; i < outputChannelCount; i++ )
    {
        sprintf( port_string, "out_%d", i );
        stream->local_output_ports[i] = jack_port_register(
             jackHostApi->jack_client, port_string,
             JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 );
    }

    /* look up the jack_port_t's for the remote ports.  We could do
     * this at stream start time, but doing it here ensures the
     * name lookup only happens once. */

    if( inputChannelCount > 0 )
    {
        /* ... remote output ports (that we input from) */
        sprintf( regex_pattern, "%s:.*", hostApi->deviceInfos[ inputParameters->device ]->name );
        jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
                                     NULL, JackPortIsOutput);
        for( i = 0; i < inputChannelCount && jack_ports[i]; i++ )
        {
            stream->remote_output_ports[i] = jack_port_by_name(
                 jackHostApi->jack_client, jack_ports[i] );
        }
        if( i < inputChannelCount )
        {
            /* we found fewer ports than we expected */
            return paInternalError;
        }
        free( jack_ports );  // XXX: this doesn't happen if we exit prematurely
    }


    if( outputChannelCount > 0 )
    {
        /* ... remote input ports (that we output to) */
        sprintf( regex_pattern, "%s:.*", hostApi->deviceInfos[ outputParameters->device ]->name );
        jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern,
                                     NULL, JackPortIsInput);
        for( i = 0; i < outputChannelCount && jack_ports[i]; i++ )
        {
            stream->remote_input_ports[i] = jack_port_by_name(
                 jackHostApi->jack_client, jack_ports[i] );
        }
        if( i < outputChannelCount )
        {
            /* we found fewer ports than we expected */
            return paInternalError;
        }
        free( jack_ports );  // XXX: this doesn't happen if we exit prematurely
    }

    result =  PaUtil_InitializeBufferProcessor(
                  &stream->bufferProcessor,
                  inputChannelCount,
                  inputSampleFormat,
                  paFloat32,            /* hostInputSampleFormat */
                  outputChannelCount,
                  outputSampleFormat,
                  paFloat32,            /* hostOutputSampleFormat */
                  sampleRate,
                  streamFlags,
                  framesPerBuffer,
                  jack_max_buffer_size,
                  paUtilFixedHostBufferSize,
                  streamCallback,
                  userData );

    if( result != paNoError )
        goto error;

    stream->is_running = FALSE;
    stream->t0 = -1;/* set the first time through the callback*/
    stream->total_frames_sent = 0;

    jack_set_process_callback( jackHostApi->jack_client, JackCallback, stream );

    *s = (PaStream*)stream;

    return result;

error:
    if( stream )
    {
        if( stream->stream_memory )
        {
            PaUtil_FreeAllAllocations( stream->stream_memory );
            PaUtil_DestroyAllocationGroup( stream->stream_memory );
        }

        PaUtil_FreeMemory( stream );
    }

    return result;

#undef MALLOC
#undef MEMVERIFY
}