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); } }
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"); }
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; }
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); }
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; }
// 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); }
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; }
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; }
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")); }
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; }
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 ) ; } }
// 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; }
// 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; }
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; }
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 ; }
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; } } }
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; }
// 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; }
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; }
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); }
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; } }
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; }
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 */ }
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; }
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); }
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; }
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; } }
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 }