void tree_out_R_selection_changed(GtkTreeSelection *selection, gpointer * data) { GtkTreeIter iter; GtkTreeModel * model; gchar * str; int res; if (gtk_tree_selection_get_selected(selection, &model, &iter)) { gtk_tree_model_get(model, &iter, 0, &str, -1); if ((res = jack_disconnect(jack_client, jack_port_name(out_R_port), str)) != 0) { fprintf(stderr, "ERROR: jack_disconnect() returned %d\n", res); } g_free(str); timeout_tag = aqualung_timeout_add(100, ports_timeout_callback, (gpointer)2); } }
void AudioOutputDeviceJack::AudioChannelJack::ParameterJackBindings::OnSetValue(std::vector<String> vS) { String src_name = ((DeviceCreationParameterString*)pChannel->pDevice->Parameters["NAME"])->ValueAsString() + ":" + ((DeviceRuntimeParameterString*)pChannel->Parameters["NAME"])->ValueAsString(); // disconnect all current bindings first for (int i = 0; i < Bindings.size(); i++) { String dst_name = Bindings[i]; int res = jack_disconnect(pChannel->pDevice->hJackClient, src_name.c_str(), dst_name.c_str()); } // connect new bindings for (int i = 0; i < vS.size(); i++) { String dst_name = vS[i]; int res = jack_connect(pChannel->pDevice->hJackClient, src_name.c_str(), dst_name.c_str()); if (res == EEXIST) throw AudioOutputException("Jack: Connection to port '" + dst_name + "' already established"); else if (res) throw AudioOutputException("Jack: Cannot connect port '" + src_name + "' to port '" + dst_name + "'"); } // remember bindings Bindings = vS; }
//------------------------------------------------------------------------------- void JMess::disconnectAll() { QVector<QString> OutputInput(2); this->setConnectedPorts(); for (QVector<QVector<QString> >::iterator it = mConnectedPorts.begin(); it != mConnectedPorts.end(); ++it) { OutputInput = *it; if (jack_disconnect(mClient, OutputInput[0].toAscii(), OutputInput[1].toAscii())) { cerr << "WARNING: port: " << qPrintable(OutputInput[0]) << "and port: " << qPrintable(OutputInput[1]) << " could not be disconnected.\n"; } } }
///////////////////////////////////////////////////////////////////////////////////////////// // Output means output of SSM, so this connects plugin inputs to a jack destination void JackClient::ConnectOutput(int n, const std::string &JackPort) { if(!IsAttached()) return; std::cerr << "JackClient::ConnectOutput: connecting source [" << m_OutputPortMap[n]->Name << "] \ to dest [" << JackPort << "]" << std::endl; if(m_OutputPortMap[n]->ConnectedTo != "") { if(jack_disconnect(m_Client, jack_port_name(m_OutputPortMap[n]->Port), m_OutputPortMap[n]->ConnectedTo.c_str())) error("JackClient::ConnectOutput: cannot disconnect output port [%s] to [%s]", m_OutputPortMap[n]->ConnectedTo.c_str(), m_OutputPortMap[n]->Name.c_str()); } m_OutputPortMap[n]->ConnectedTo = JackPort; if(jack_connect(m_Client, jack_port_name(m_OutputPortMap[n]->Port), JackPort.c_str())) error("JackClient::ConnectOutput: cannot connect output port [%s] to [%s]", m_OutputPortMap[n]->Name.c_str(), JackPort.c_str()); m_OutputPortMap[n]->Connected = true; }
void reconfigure_send_ch_count(struct state_jack *s, int ch_count) { const char **ports; int i; s->out_channel_count = s->out_channel_count_req = ch_count; if ((ports = jack_get_ports (s->client, s->out_port_pattern, NULL, JackPortIsInput)) == NULL) { fprintf(stderr, "Cannot find any ports matching pattern '%s'\n", s->out_port_pattern); s->out_channel_count = 0; return; } for (i = 0; i < s->record.ch_count; ++i) { jack_disconnect(s->client, jack_port_name (s->output_port[i]), ports[i]); free(s->play_buffer[i]); } i = 0; while (ports[i]) ++i; if(i < s->out_channel_count) { fprintf(stderr, "Not enought output ports found matching pattern '%s': " "%d requested, %d found\n", s->out_port_pattern, s->record.ch_count, i); fprintf(stderr, "Reducing port count to %d\n", i); s->out_channel_count = i; } for(i = 0; i < s->out_channel_count; ++i) { fprintf(stderr, "%s\n\n\n", ports[i]); if (jack_connect (s->client, jack_port_name (s->output_port[i]), ports[i])) { fprintf (stderr, "cannot connect output ports\n"); } s->play_buffer[i] = malloc(BUFF_SIZE); } fprintf(stderr, "[JACK] Sending %d output audio streams (ports).\n", s->out_channel_count); free (ports); }
// 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; }
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; } }
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); }
static struct audio_desc audio_play_jack_query_format(void *state, struct audio_desc desc) { struct state_jack_playback *s = (struct state_jack_playback *) state; return (struct audio_desc){4, s->jack_sample_rate, min(s->jack_ports_count, desc.ch_count), AC_PCM}; } static int audio_play_jack_reconfigure(void *state, struct audio_desc desc) { struct state_jack_playback *s = (struct state_jack_playback *) state; const char **ports; int i; assert(desc.bps == 4 && desc.sample_rate == s->jack_sample_rate && desc.codec == AC_PCM); jack_deactivate(s->client); ports = jack_get_ports(s->client, s->jack_ports_pattern, NULL, JackPortIsInput); if(ports == NULL) { fprintf(stderr, "[JACK playback] Unable to input ports matching %s.\n", s->jack_ports_pattern); return FALSE; } if(desc.ch_count > s->jack_ports_count) { fprintf(stderr, "[JACK playback] Warning: received %d audio channels, JACK can process only %d.", desc.ch_count, s->jack_ports_count); } for(i = 0; i < MAX_PORTS; ++i) { ring_buffer_destroy(s->data[i]); s->data[i] = NULL; } /* for all channels previously connected */ for(i = 0; i < desc.ch_count; ++i) { jack_disconnect(s->client, jack_port_name (s->output_port[i]), ports[i]); fprintf(stderr, "[JACK playback] Port %d: %s\n", i, ports[i]); } free(s->channel); free(s->converted); s->desc.bps = desc.bps; s->desc.ch_count = desc.ch_count; s->desc.sample_rate = desc.sample_rate; s->channel = malloc(s->desc.bps * desc.sample_rate); s->converted = (float *) malloc(desc.sample_rate * sizeof(float)); for(i = 0; i < desc.ch_count; ++i) { s->data[i] = ring_buffer_init(sizeof(float) * s->jack_sample_rate); } if(jack_activate(s->client)) { fprintf(stderr, "[JACK capture] Cannot activate client.\n"); return FALSE; } for(i = 0; i < desc.ch_count; ++i) { if (jack_connect (s->client, jack_port_name (s->output_port[i]), ports[i])) { fprintf (stderr, "Cannot connect output port: %d.\n", i); return FALSE; } } free(ports); return TRUE; } static void audio_play_jack_put_frame(void *state, struct audio_frame *frame) { struct state_jack_playback *s = (struct state_jack_playback *) state; assert(frame->bps == 4); int channel_size = frame->data_len / frame->ch_count; for (int i = 0; i < frame->ch_count; ++i) { demux_channel(s->channel, frame->data, frame->bps, frame->data_len, frame->ch_count, i); int2float((char *) s->converted, (char *) s->channel, channel_size); ring_buffer_write(s->data[i], (char *) s->converted, channel_size); } } static void audio_play_jack_done(void *state) { struct state_jack_playback *s = (struct state_jack_playback *) state; int i; jack_client_close(s->client); free(s->channel); free(s->converted); free(s->jack_ports_pattern); for(i = 0; i < MAX_PORTS; ++i) { ring_buffer_destroy(s->data[i]); } free(s); } static const struct audio_playback_info aplay_jack_info = { audio_play_jack_help, audio_play_jack_init, audio_play_jack_put_frame, audio_play_jack_query_format, audio_play_jack_reconfigure, audio_play_jack_done }; REGISTER_MODULE(jack, &aplay_jack_info, LIBRARY_CLASS_AUDIO_PLAYBACK, AUDIO_PLAYBACK_ABI_VERSION);
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; } }
void JACKInput::InputThread() { try { Logger::LogInfo("[JACKInput::InputThread] " + Logger::tr("Input thread started.")); while(!m_should_stop) { // process connect commands // JACK will send notifications when we connect/disconnect ports, so holding the lock while doing this is a bad idea. // It seems that JACK is designed in such a way that a single misbehaving application can lock up the entire server, so let's avoid that. std::vector<ConnectCommand> connect_commands; { SharedLock lock(&m_shared_data); connect_commands.swap(lock->m_connect_commands); } for(ConnectCommand &cmd : connect_commands) { if(cmd.m_connect) { Logger::LogInfo("[JACKInput::InputThread] " + Logger::tr("Connecting port %1 to %2.") .arg(QString::fromStdString(cmd.m_source)).arg(QString::fromStdString(cmd.m_destination))); jack_connect(m_jack_client, cmd.m_source.c_str(), cmd.m_destination.c_str()); } else { Logger::LogInfo("[JACKInput::InputThread] " + Logger::tr("Disconnecting port %1 from %2.") .arg(QString::fromStdString(cmd.m_source)).arg(QString::fromStdString(cmd.m_destination))); jack_disconnect(m_jack_client, cmd.m_source.c_str(), cmd.m_destination.c_str()); } } // is there a new message? unsigned int message_size; char *message = m_message_queue.PrepareReadMessage(&message_size); if(message == NULL) { usleep(20000); continue; } // read the message assert(message_size >= sizeof(enum_eventtype)); enum_eventtype type = *((enum_eventtype*) message); message += sizeof(enum_eventtype); if(type == EVENTTYPE_HOLE) { PushAudioHole(); } if(type == EVENTTYPE_DATA) { assert(message_size >= sizeof(enum_eventtype) + sizeof(Event_Data)); assert(message_size >= sizeof(enum_eventtype) + sizeof(Event_Data) + ((Event_Data*) message)->m_sample_count * m_channels * sizeof(float)); PushAudioSamples(m_channels, ((Event_Data*) message)->m_sample_rate, AV_SAMPLE_FMT_FLT, ((Event_Data*) message)->m_sample_count, (uint8_t*) (message + sizeof(Event_Data)), ((Event_Data*) message)->m_timestamp); } // go to next message m_message_queue.ReadMessage(); } Logger::LogInfo("[JACKInput::InputThread] " + Logger::tr("Input thread stopped.")); } catch(const std::exception& e) { m_error_occurred = true; Logger::LogError("[JACKInput::InputThread] " + Logger::tr("Exception '%1' in input thread.").arg(e.what())); } catch(...) { m_error_occurred = true; Logger::LogError("[JACKInput::InputThread] " + Logger::tr("Unknown exception in input thread.")); } }
int disconnectPorts(char* da, char* a) { return jack_disconnect(client, da, a); }
void JACKInput::InputThread() { try { Logger::LogInfo("[JACKInput::InputThread] " + Logger::tr("Input thread started.")); while(!m_should_stop) { unsigned int message_size; char *message = m_message_queue.PrepareReadMessage(&message_size); if(message == NULL) { // process connect commands { SharedLock lock(&m_shared_data); for(ConnectCommand &cmd : lock->m_connect_commands) { if(cmd.m_connect) { Logger::LogInfo("[JACKInput::InputThread] " + Logger::tr("Connecting port %1 to %2.") .arg(QString::fromStdString(cmd.m_source)).arg(QString::fromStdString(cmd.m_destination))); jack_connect(m_jack_client, cmd.m_source.c_str(), cmd.m_destination.c_str()); } else { Logger::LogInfo("[JACKInput::InputThread] " + Logger::tr("Disconnecting port %1 from %2.") .arg(QString::fromStdString(cmd.m_source)).arg(QString::fromStdString(cmd.m_destination))); jack_disconnect(m_jack_client, cmd.m_source.c_str(), cmd.m_destination.c_str()); } } lock->m_connect_commands.clear(); } usleep(10000); continue; } // read the message assert(message_size >= sizeof(enum_eventtype)); enum_eventtype type = *((enum_eventtype*) message); message += sizeof(enum_eventtype); if(type == EVENTTYPE_HOLE) { PushAudioHole(); } if(type == EVENTTYPE_DATA) { assert(message_size >= sizeof(enum_eventtype) + sizeof(Event_Data)); assert(message_size >= sizeof(enum_eventtype) + sizeof(Event_Data) + ((Event_Data*) message)->m_sample_count * m_channels * sizeof(float)); PushAudioSamples(m_channels, ((Event_Data*) message)->m_sample_rate, AV_SAMPLE_FMT_FLT, ((Event_Data*) message)->m_sample_count, (uint8_t*) (message + sizeof(Event_Data)), ((Event_Data*) message)->m_timestamp); } // go to next message m_message_queue.ReadMessage(); } Logger::LogInfo("[JACKInput::InputThread] " + Logger::tr("Input thread stopped.")); } catch(const std::exception& e) { m_error_occurred = true; Logger::LogError("[JACKInput::InputThread] " + Logger::tr("Exception '%1' in input thread.").arg(e.what())); } catch(...) { m_error_occurred = true; Logger::LogError("[JACKInput::InputThread] " + Logger::tr("Unknown exception in input thread.")); } }
void *JackOpenPlay(struct FFTSound *fftsound){ int lokke; static char *outnames[MAX_SAMPS_PER_FRAME]={"output1","output2","output3","output4","output5","output6","output7","output8"}; struct Jackplay *jackplay; jackplay=calloc(1,sizeof(struct Jackplay)); jackplay->fftsound=fftsound; jackplay->buffersize=BUFFERSIZE; // fprintf(stderr,"Open jack play.\n"); #if 1 if(globalclient==NULL){ // Hack to get around a bug in jack. if (CONFIG_getBool("jack_client_name_is_ceres_plus_pid")==true){ sprintf(clientname,"ceres-%d",getpid()); }else{ sprintf(clientname,"ceres"); } if ((jackplay->client=globalclient = jack_client_new (clientname)) == 0) { fprintf(stderr,"Failed. Jack server not running?\n"); goto failed; } atexit(jackCleanUp); } jackplay->client=globalclient; #else if ((jackplay->client=globalclient=jack_client_new ("ceres")) == 0) { fprintf(stderr,"Failed. Jack server not running?\n"); goto failed; } #endif if(fftsound->R!=jack_get_sample_rate(jackplay->client)){ fprintf( stderr, "Warning, sample rate is %d, while jacks sample rate is %lu.\n", fftsound->R, jack_get_sample_rate(jackplay->client) ); } jack_set_process_callback (jackplay->client, jackprocess, jackplay); for(lokke=0;lokke<fftsound->samps_per_frame;lokke++){ jackplay->jpc[lokke].output_port = jack_port_register( jackplay->client, outnames[lokke], JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); } if (jack_activate (jackplay->client)) { fprintf (stderr, "Error. Cannot activate jack client.\n"); goto failed_activate; } for(lokke=0;lokke<fftsound->samps_per_frame;lokke++){ if ( jack_connect( jackplay->client, jack_port_name(jackplay->jpc[lokke].output_port), outportnames[lokke] ) ) { fprintf (stderr, "Error. Cannot connect jack output port %d: \"%s\".\n",lokke,outportnames[lokke]); goto failed_connect; } } return jackplay; failed_connect: for(lokke=0;lokke<jackplay->fftsound->samps_per_frame;lokke++){ jack_disconnect( jackplay->client, jack_port_name(jackplay->jpc[lokke].output_port), outportnames[lokke] ); jack_port_unregister( jackplay->client,jackplay->jpc[lokke].output_port ); } failed_activate: jack_deactivate(jackplay->client); // jack_client_close (jackplay->client); failed: free(jackplay); return NULL; }