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 int ja_connect_client(void) { char **ports; int i; ports = (char **) jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput); if (ports == NULL) return 1; for (i = 0; i < ja_in_channels && ports[i] != NULL; i++) jack_connect(client, ports[i], jack_port_name(input_ports[i])); jack_free(ports); ports = (char **) jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); if (ports == NULL) return 1; for (i = 0; i < ja_out_channels && ports[i] != NULL; i++) jack_connect(client, jack_port_name(output_ports[i]), ports[i]); jack_free(ports); return 0; }
int JackSapaProxy::Setup(jack_client_t* client) { jack_log("JackSapaProxy::Setup"); //refer to system ports and create sapaproxy ports unsigned int i = 0, j = 0; const char **ports_system_capture; const char **ports_system_playback; unsigned int ports_system_capture_cnt = 0; unsigned int ports_system_playback_cnt = 0; char port_name[JACK_PORT_NAME_SIZE] = {0,}; ports_system_capture = jack_get_ports(client, "system:.*", NULL, JackPortIsPhysical | JackPortIsOutput); if (ports_system_capture != NULL) { for (i = 0; i < fCapturePorts && ports_system_capture[i]; i++) { sprintf(port_name, "__system_capture_%d", i + 1); fInputPorts[i] = jack_port_register(client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); sprintf(port_name, "capture_%d", i + 1); fOutputPorts[i] = jack_port_register(client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); ports_system_capture_cnt++; } jack_free(ports_system_capture); } ports_system_playback = jack_get_ports(client, "system:.*", NULL, JackPortIsPhysical | JackPortIsInput); if (ports_system_playback != NULL) { for (j = 0; j < fPlaybackPorts && ports_system_playback[j]; j++, i++) { sprintf(port_name, "playback_%d", j + 1); fInputPorts[i] = jack_port_register(client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); sprintf(port_name, "__system_playback_%d", j + 1); fOutputPorts[i] = jack_port_register(client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); ports_system_playback_cnt++; } jack_free(ports_system_playback); } //store actual number of system ports fCapturePorts = ports_system_capture_cnt; fPlaybackPorts = ports_system_playback_cnt; jack_set_process_callback(client, Process, this); jack_activate(client); //conenct between sapaproxy and system ports for (unsigned int i = 0; i < ports_system_capture_cnt; i++) { sprintf(port_name, "system:capture_%d", i + 1); jack_connect(client, port_name, jack_port_name(fInputPorts[i])); } for (unsigned int i = 0; i < ports_system_playback_cnt; i++) { sprintf(port_name, "system:playback_%d", i + 1); jack_connect(client, jack_port_name(fOutputPorts[ports_system_capture_cnt + i]), port_name); } return 0; }
void AudioReader::stop() { if(!running) return; jack_client_close(client); delete[] buffer; delete[] sounds; jack_free(output_left); jack_free(output_right); jack_free(input_left); jack_free(input_right); free(cfg); running = false; }
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 main (int argc, char* argv[]) { jack_client_t* client; char const default_name[] = "connector"; // this is moderately retarded aliases[0] = (char *) malloc (jack_port_name_size()); aliases[1] = (char *) malloc (jack_port_name_size()); client = jack_client_open(default_name, JackNullOption, NULL); while (1) { const char **portnames; const char **orig; orig = portnames = jack_get_ports(client, "", "", 0); desired_connection *desired = desired_connections; while (desired->from_port) { ensure_connected(client, orig, desired); desired++; } printf("\n"); sleep(5); jack_free(orig); } }
/* 0 on error */ static int autoconnect_jack_ports(out123_handle *ao, jack_handle_t* handle) { const char **all_ports; unsigned int ch=0; int err,i; /* Get a list of all the jack ports*/ all_ports = jack_get_ports (handle->client, NULL, NULL, JackPortIsInput); if(!all_ports) { if(!AOQUIET) error("connect_jack_ports(): jack_get_ports() returned NULL."); return 0; } /* Step through each port name*/ for (i = 0; all_ports[i]; ++i) { const char* in = jack_port_name( handle->ports[ch] ); const char* out = all_ports[i]; if ((err = jack_connect(handle->client, in, out)) != 0 && err != EEXIST) { if(!AOQUIET) error1("connect_jack_ports(): failed to jack_connect() ports: %d",err); return 0; } /* Found enough ports ?*/ if (++ch >= handle->channels) break; } jack_free(all_ports); return 1; }
void JackProxyDriver::ConnectPorts() { jack_log("JackProxyDriver::ConnectPorts"); const char** ports = jack_get_ports(fClient, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsOutput); if (ports != NULL) { for (int i = 0; i < fCaptureChannels && ports[i]; i++) { jack_connect(fClient, ports[i], jack_port_name(fUpstreamPlaybackPorts[i])); } jack_free(ports); } ports = jack_get_ports(fClient, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsInput); if (ports != NULL) { for (int i = 0; i < fPlaybackChannels && ports[i]; i++) { jack_connect(fClient, jack_port_name(fUpstreamCapturePorts[i]), ports[i]); } jack_free(ports); } }
int JackProxyDriver::CountIO(const char* type, int flags) { int count = 0; const char** ports = jack_get_ports(fClient, NULL, type, flags); if (ports != NULL) { while (ports[count]) { count++; } jack_free(ports); } return count; }
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); } }
static void connect_jack_ports() { int i; int c=0; for (i = 0; i < AUDIO_CHANNELS; i++) { if (!jack_port[i]) continue; if (jack_connect(j_client, jack_port_name(j_output_port[i]), jack_port[i] )) { fprintf(stderr, "cannot connect port %s to %s\n", jack_port_name(j_output_port[i]), jack_port[i]); } c++; } if (c==0 && jack_ports && strlen(jack_ports)>0) { /* all of jack_port[] were NULL, try regexp */ const char **found_ports = jack_get_ports(j_client, jack_ports, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput); if (found_ports) { for (i = 0; found_ports[i] && i < AUDIO_CHANNELS; ++i) { if (jack_connect(j_client, jack_port_name(j_output_port[i]), found_ports[i])) { fprintf(stderr, "JACK: cannot connect port %s to %s\n", jack_port_name(j_output_port[i]), found_ports[i]); } } jack_free(found_ports); } } /* Midi Port */ if (use_jack_midi && midi_port && strlen(midi_port)>0) { const char **found_ports = jack_get_ports(j_client, midi_port, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput); if (found_ports) { for (i = 0; found_ports[i]; ++i) { if (jack_connect(j_client, found_ports[i], jack_port_name(jack_midi_port))) { fprintf(stderr, "JACK: cannot connect port %s to %s\n", found_ports[i], jack_port_name(jack_midi_port)); } } jack_free(found_ports); } } }
static void cbjack_connect_ports (cubeb_stream * stream) { const char **physical_ports = jack_get_ports (stream->context->jack_client, NULL, NULL, JackPortIsInput | JackPortIsPhysical); if (physical_ports == NULL) { return; } // Connect to all physical ports for (unsigned int c = 0; c < stream->params.channels && physical_ports[c]; c++) { const char *src_port = jack_port_name (stream->output_ports[c]); jack_connect (stream->context->jack_client, src_port, physical_ports[c]); } jack_free(physical_ports); }
void jack_start() { jack_set_error_function(error); client = jack_client_open("MicToMIDI", JackNullOption, NULL); if (client == 0) { fprintf(stderr, "jack server not running?\n"); exit(1); } jack_set_process_callback(client, process, 0); jack_set_sample_rate_callback(client, sample_rate, 0); jack_on_shutdown(client, jack_shutdown, 0); input_port = jack_port_register(client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); output_port = jack_port_register(client, "output", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); if(jack_activate(client)) { fprintf(stderr, "cannot activate client"); exit(1); } atexit(jack_stop); const char **ports; if((ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsOutput)) == NULL) { fprintf(stderr, "cannot find any physical capture ports\n"); exit(1); } if(jack_connect(client, ports[0], jack_port_name(input_port))) fprintf(stderr, "cannot connect to physical capture port\n"); jack_free(ports); if((ports = jack_get_ports(client, NULL, "midi", JackPortIsInput)) == NULL) { fprintf(stderr, "cannot find any MIDI playback ports\n"); exit(1); } if(jack_connect(client, jack_port_name(output_port), ports[0])) fprintf(stderr, "cannot connect to MIDI playback port\n"); }
GList * get_jack_ports (gboolean midi, gboolean output) { GList *list = NULL; // open a temporary connection to the JACK server jack_client_t *client = jack_client_open ("denemo", JackNoStartServer, NULL); if (!client) { return NULL; } char const *type = midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE; unsigned long flags = output ? JackPortIsOutput : JackPortIsInput; // get all input port names of the given type char const **ports = jack_get_ports (client, NULL, type, flags); if (!ports) { return NULL; } // copy all port names to our own list char const **p = ports; while (*p) { char *s = g_strdup (*p++); list = g_list_append (list, s); } jack_free (ports); jack_client_close (client); return list; }
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); }
static Data *create_data(const SoundPluginType *plugin_type, jack_client_t *client, int num_inputs, int num_outputs, const char **input_portnames, const char **output_portnames){ Data *data = (Data*)V_calloc(1,sizeof(Data)); data->client = client; data->input_ports=(jack_port_t**)V_calloc(num_outputs,sizeof(jack_port_t*)); data->output_ports=(jack_port_t**)V_calloc(num_inputs,sizeof(jack_port_t*)); int i; for(i=0;i<num_outputs;i++){ static int n=0; char temp[500]; if(input_portnames[i] != NULL) sprintf(temp, "%s", input_portnames[i]); else sprintf(temp, "in_%d",++n); if((data->input_ports[i] = jack_port_register(client, V_strdup(temp), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ) )==NULL) GFX_Message(NULL, "Error. Could not register jack port.\n"); } if(!strcmp(plugin_type->name,"System In")){ int ch; const char **outportnames=jack_get_ports(client,NULL,NULL,JackPortIsPhysical|JackPortIsOutput); for (ch=0;outportnames && outportnames[ch]!=NULL && ch<num_outputs;ch++){ if ( data->input_ports[ch]!= NULL && jack_connect( client, outportnames[ch], jack_port_name(data->input_ports[ch]) ) ) GFX_Message(NULL, "Warning. Cannot connect to jack capture port %d: \"%s\".\n",ch,outportnames[ch]); } jack_free(outportnames); } for(i=0;i<num_inputs;i++){ static int n=0; char temp[500]; if(output_portnames[i] != NULL) sprintf(temp, "%s",output_portnames[i]); else sprintf(temp, "out_%d",++n); if((data->output_ports[i] = jack_port_register( client, V_strdup(temp), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ) )==NULL) GFX_Message(NULL, "Error. Could not register jack port.\n"); } if(!strcmp(plugin_type->name,"System Out") || !strcmp(plugin_type->name,"System Out 8")){ int ch; const char **inportnames=jack_get_ports(client,NULL,NULL,JackPortIsPhysical|JackPortIsInput); for (ch=0;inportnames && inportnames[ch]!=NULL && ch<num_inputs;ch++){ if ( data->output_ports[ch] != NULL && jack_connect( client, jack_port_name(data->output_ports[ch]), inportnames[ch] ) ) GFX_addMessage("Warning. Cannot connect to jack playback port %d: \"%s\".\n",ch,inportnames[ch]); } jack_free(inportnames); } return data; }
bool JackAudioInterface::setPhysicalInputs(unsigned int* inputChannels) { // get all jack ports that correspond to physical inputs if (!m_client) return false; const char** inputPorts = jack_get_ports(m_client, NULL, NULL, JackPortIsOutput | JackPortIsPhysical); // count the number of physical input ports const char** currentPort = inputPorts; unsigned int numPhysicalPortsIn = 0; while (*currentPort != NULL) { numPhysicalPortsIn++; qDebug("JackAudioInterface::SetPhysicalInputs() counted port %s", *currentPort); currentPort++; } qDebug("JackAudioInterface::SetPhysicalInputs() counted %d physical inputs", numPhysicalPortsIn); jack_free(inputPorts); if (m_channels > numPhysicalPortsIn) { return false; // requested more input ports than actually exist } // allocate array of input port pointers m_inputPorts = new jack_port_t*[m_channels]; for (unsigned int ch = 0; ch < m_channels; ch++) { m_inputPorts[ch] = NULL; } // register JACK input ports and connect physical inputs to client inputs char portName[MAX_PORT_NAME]; for (unsigned int i = 0; i < m_channels; i++) { // register input port snprintf(portName, MAX_PORT_NAME, "input_%d", i + 1); m_inputPorts[i] = jack_port_register(m_client, portName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); if (!m_inputPorts[i]) { qDebug() << "JackAudioInterface::SetPhysicalInputs ERROR: couldn't register input port for channel " << i + 1 << endl; return false; } qDebug() << "JackAudioInterface::SetPhysicalInputs registered input port " << i << endl; // connect the specified physical input to the newly-created input port char systemIn[MAX_PORT_NAME]; snprintf(systemIn, MAX_PORT_NAME, "system:capture_%d", inputChannels[i]); // TODO: handle case where system ports have non-standard names (is this possible?)? const char* inputPortName = jack_port_name(m_inputPorts[i]); // TODO: handle case where input port requested doesn't exist? int result = jack_connect(m_client, systemIn, inputPortName); if (result == EEXIST) { qWarning("JackAudioInterface::SetPhysicalInputs WARNING: %s and %s were already connected", systemIn, inputPortName); // TODO: decide how to handle this case } else if (result != 0) { qWarning("JackAudioInterface::SetPhysicalInputs ERROR: couldn't connect %s to %s", systemIn, inputPortName); return false; } else { qDebug("JackAudioInterface::SetPhysicalInputs connected %s to %s", systemIn, inputPortName); } } qDebug() << "JackAudioInterface::SetPhysicalInputs registered input ports" << endl; return true; }
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; }
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; } }
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); }
int pa__init(pa_module*m) { struct userdata *u = NULL; pa_sample_spec ss; pa_channel_map map; pa_modargs *ma = NULL; jack_status_t status; const char *server_name, *client_name; uint32_t channels = 0; bool do_connect = true; unsigned i; const char **ports = NULL, **p; pa_sink_new_data data; jack_latency_range_t r; size_t n; pa_assert(m); jack_set_error_function(jack_error_func); if (!(ma = pa_modargs_new(m->argument, valid_modargs))) { pa_log("Failed to parse module arguments."); goto fail; } if (pa_modargs_get_value_boolean(ma, "connect", &do_connect) < 0) { pa_log("Failed to parse connect= argument."); goto fail; } server_name = pa_modargs_get_value(ma, "server_name", NULL); client_name = pa_modargs_get_value(ma, "client_name", "PulseAudio JACK Sink"); m->userdata = u = pa_xnew0(struct userdata, 1); u->core = m->core; u->module = m; u->saved_frame_time_valid = false; u->rtpoll = pa_rtpoll_new(); pa_thread_mq_init(&u->thread_mq, m->core->mainloop, u->rtpoll); /* The queue linking the JACK thread and our RT thread */ u->jack_msgq = pa_asyncmsgq_new(0); /* The msgq from the JACK RT thread should have an even higher * priority than the normal message queues, to match the guarantee * all other drivers make: supplying the audio device with data is * the top priority -- and as long as that is possible we don't do * anything else */ u->rtpoll_item = pa_rtpoll_item_new_asyncmsgq_read(u->rtpoll, PA_RTPOLL_EARLY-1, u->jack_msgq); if (!(u->client = jack_client_open(client_name, server_name ? JackServerName : JackNullOption, &status, server_name))) { pa_log("jack_client_open() failed."); goto fail; } ports = jack_get_ports(u->client, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical|JackPortIsInput); channels = 0; if (ports) for (p = ports; *p; p++) channels++; if (!channels) channels = m->core->default_sample_spec.channels; if (pa_modargs_get_value_u32(ma, "channels", &channels) < 0 || !pa_channels_valid(channels)) { pa_log("Failed to parse channels= argument."); goto fail; } if (channels == m->core->default_channel_map.channels) map = m->core->default_channel_map; else pa_channel_map_init_extend(&map, channels, PA_CHANNEL_MAP_ALSA); if (pa_modargs_get_channel_map(ma, NULL, &map) < 0 || map.channels != channels) { pa_log("Failed to parse channel_map= argument."); goto fail; } pa_log_info("Successfully connected as '%s'", jack_get_client_name(u->client)); u->channels = ss.channels = (uint8_t) channels; ss.rate = jack_get_sample_rate(u->client); ss.format = PA_SAMPLE_FLOAT32NE; pa_assert(pa_sample_spec_valid(&ss)); for (i = 0; i < ss.channels; i++) { if (!(u->port[i] = jack_port_register(u->client, pa_channel_position_to_string(map.map[i]), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput|JackPortIsTerminal, 0))) { pa_log("jack_port_register() failed."); goto fail; } } pa_sink_new_data_init(&data); data.driver = __FILE__; data.module = m; pa_sink_new_data_set_name(&data, pa_modargs_get_value(ma, "sink_name", DEFAULT_SINK_NAME)); pa_sink_new_data_set_sample_spec(&data, &ss); pa_sink_new_data_set_channel_map(&data, &map); pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "jack"); if (server_name) pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server_name); pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Jack sink (%s)", jack_get_client_name(u->client)); pa_proplist_sets(data.proplist, "jack.client_name", jack_get_client_name(u->client)); if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) { pa_log("Invalid properties"); pa_sink_new_data_done(&data); goto fail; } u->sink = pa_sink_new(m->core, &data, PA_SINK_LATENCY); pa_sink_new_data_done(&data); if (!u->sink) { pa_log("Failed to create sink."); goto fail; } u->sink->parent.process_msg = sink_process_msg; u->sink->userdata = u; pa_sink_set_asyncmsgq(u->sink, u->thread_mq.inq); pa_sink_set_rtpoll(u->sink, u->rtpoll); pa_sink_set_max_request(u->sink, jack_get_buffer_size(u->client) * pa_frame_size(&u->sink->sample_spec)); jack_set_process_callback(u->client, jack_process, u); jack_on_shutdown(u->client, jack_shutdown, u); jack_set_thread_init_callback(u->client, jack_init, u); jack_set_buffer_size_callback(u->client, jack_buffer_size, u); if (!(u->thread = pa_thread_new("jack-sink", thread_func, u))) { pa_log("Failed to create thread."); goto fail; } if (jack_activate(u->client)) { pa_log("jack_activate() failed"); goto fail; } if (do_connect) { for (i = 0, p = ports; i < ss.channels; i++, p++) { if (!p || !*p) { pa_log("Not enough physical output ports, leaving unconnected."); break; } pa_log_info("Connecting %s to %s", jack_port_name(u->port[i]), *p); if (jack_connect(u->client, jack_port_name(u->port[i]), *p)) { pa_log("Failed to connect %s to %s, leaving unconnected.", jack_port_name(u->port[i]), *p); break; } } } jack_port_get_latency_range(u->port[0], JackPlaybackLatency, &r); n = r.max * pa_frame_size(&u->sink->sample_spec); pa_sink_set_fixed_latency(u->sink, pa_bytes_to_usec(n, &u->sink->sample_spec)); pa_sink_put(u->sink); if (ports) jack_free(ports); pa_modargs_free(ma); return 0; fail: if (ma) pa_modargs_free(ma); if (ports) jack_free(ports); pa__done(m); return -1; }
static int start_jack(struct auplay_st *st) { const char **ports; const char *client_name = "baresip"; const char *server_name = NULL; jack_options_t options = JackNullOption; jack_status_t status; unsigned ch; jack_nframes_t engine_srate; /* open a client connection to the JACK server */ st->client = jack_client_open(client_name, options, &status, server_name); if (st->client == NULL) { warning("jack: jack_client_open() failed, " "status = 0x%2.0x\n", status); if (status & JackServerFailed) { warning("jack: Unable to connect to JACK server\n"); } return ENODEV; } if (status & JackServerStarted) { info("jack: JACK server started\n"); } if (status & JackNameNotUnique) { client_name = jack_get_client_name(st->client); info("jack: unique name `%s' assigned\n", client_name); } jack_set_process_callback(st->client, process_handler, st); engine_srate = jack_get_sample_rate(st->client); st->nframes = jack_get_buffer_size(st->client); info("jack: engine sample rate: %" PRIu32 " max_frames=%u\n", engine_srate, st->nframes); /* currently the application must use the same sample-rate as the jack server backend */ if (engine_srate != st->prm.srate) { warning("jack: samplerate %uHz expected\n", engine_srate); return EINVAL; } /* create one port per channel */ for (ch=0; ch<st->prm.ch; ch++) { char buf[32]; re_snprintf(buf, sizeof(buf), "output_%u", ch+1); st->portv[ch] = jack_port_register (st->client, buf, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if ( st->portv[ch] == NULL) { warning("jack: no more JACK ports available\n"); return ENODEV; } } /* Tell the JACK server that we are ready to roll. Our * process() callback will start running now. */ if (jack_activate (st->client)) { warning("jack: cannot activate client"); return ENODEV; } /* Connect the ports. You can't do this before the client is * activated, because we can't make connections to clients * that aren't running. Note the confusing (but necessary) * orientation of the driver backend ports: playback ports are * "input" to the backend, and capture ports are "output" from * it. */ ports = jack_get_ports (st->client, NULL, NULL, JackPortIsInput); if (ports == NULL) { warning("jack: no physical playback ports\n"); return ENODEV; } for (ch=0; ch<st->prm.ch; ch++) { if (jack_connect (st->client, jack_port_name (st->portv[ch]), ports[ch])) { warning("jack: cannot connect output ports\n"); } } jack_free(ports); return 0; }
int main (int argc, char *argv[]) { const char **ports; const char *client_name; const char *server_name = NULL; jack_options_t options = JackNullOption; jack_status_t status; if (argc >= 2) { /* client name specified? */ client_name = argv[1]; if (argc >= 3) { /* server name specified? */ server_name = argv[2]; options |= JackServerName; } } else { /* use basename of argv[0] */ client_name = strrchr(argv[0], '/'); if (client_name == 0) { client_name = argv[0]; } else { client_name++; } } /* open a client connection to the JACK server */ client = jack_client_open (client_name, options, &status, server_name); if (client == NULL) { fprintf (stderr, "jack_client_open() failed, " "status = 0x%2.0x\n", status); if (status & JackServerFailed) { fprintf (stderr, "Unable to connect to JACK server\n"); } exit (1); } if (status & JackServerStarted) { fprintf (stderr, "JACK server started\n"); } if (status & JackNameNotUnique) { client_name = jack_get_client_name(client); fprintf (stderr, "unique name `%s' assigned\n", client_name); } /* tell the JACK server to call `process()' whenever there is work to be done. */ if (jack_set_process_thread(client, jack_thread, client) < 0) exit(1); /* tell the JACK server to call `jack_shutdown()' if it ever shuts down, either entirely, or if it just decides to stop calling us. */ jack_on_shutdown (client, jack_shutdown, 0); /* display the current sample rate. */ printf ("engine sample rate: %" PRIu32 "\n", jack_get_sample_rate (client)); /* create two ports */ input_port = jack_port_register (client, "input", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); output_port = jack_port_register (client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if ((input_port == NULL) || (output_port == NULL)) { fprintf(stderr, "no more JACK ports available\n"); exit (1); } /* Tell the JACK server that we are ready to roll. Our * process() callback will start running now. */ if (jack_activate (client)) { fprintf (stderr, "cannot activate client"); exit (1); } /* Connect the ports. You can't do this before the client is * activated, because we can't make connections to clients * that aren't running. Note the confusing (but necessary) * orientation of the driver backend ports: playback ports are * "input" to the backend, and capture ports are "output" from * it. */ ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput); if (ports == NULL) { fprintf(stderr, "no physical capture ports\n"); exit (1); } if (jack_connect (client, ports[0], jack_port_name (input_port))) { fprintf (stderr, "cannot connect input ports\n"); } jack_free (ports); ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); if (ports == NULL) { fprintf(stderr, "no physical playback ports\n"); exit (1); } if (jack_connect (client, jack_port_name (output_port), ports[0])) { fprintf (stderr, "cannot connect output ports\n"); } jack_free (ports); /* install a signal handler to properly quits jack client */ signal(SIGQUIT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGHUP, signal_handler); signal(SIGINT, signal_handler); /* keep running until the transport stops */ while (client_state != Exit) { sleep (1); } jack_client_close (client); exit (0); }
AudioDevJack::AudioDevJack(QObject *parent): AudioDev(parent) { this->m_curChannels = 0; this->m_curSampleRate = 0; this->m_maxBufferSize = 0; this->m_isInput = false; this->m_client = NULL; this->m_descriptions = { {":jackinput:" , "JACK Audio Connection Kit Input" }, {":jackoutput:", "JACK Audio Connection Kit Output"}, }; auto appName = QCoreApplication::applicationName() + QString("_%1").arg(Ak::id()); int maxNameSize = jack_client_name_size() - 1; if (appName.size() > maxNameSize) appName = appName.mid(0, maxNameSize); jack_status_t status; this->m_client = jack_client_open(appName.toStdString().c_str(), JackNullOption, &status); if (!this->m_client) { this->m_error = jackErrorCodes->value(status); Q_EMIT this->errorChanged(this->m_error); return; } // Setup callbacks jack_set_process_callback(this->m_client, AudioDevJack::onProcessCallback, this); jack_on_shutdown(this->m_client, AudioDevJack::onShutdownCallback, this); AkAudioCaps audioCaps; audioCaps.isValid() = true; audioCaps.format() = AkAudioCaps::SampleFormat_flt; audioCaps.bps() = AkAudioCaps::bitsPerSample(audioCaps.format()); audioCaps.rate() = int(jack_get_sample_rate(this->m_client)); audioCaps.layout() = AkAudioCaps::defaultChannelLayout(audioCaps.channels()); audioCaps.align() = false; QMap<QString, JackPortFlags> portTypeMap = { {":jackinput:" , JackPortIsOutput}, {":jackoutput:", JackPortIsInput } }; // Query the number orr channels for (auto deviceId: portTypeMap.keys()) { auto ports = jack_get_ports(this->m_client, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | portTypeMap[deviceId]); int channels = 0; for (auto portName = ports; portName && *portName; portName++, channels++) this->m_devicePorts[deviceId] << *portName; if (ports) jack_free(ports); if (channels > 0) { audioCaps.channels() = channels; this->m_caps[deviceId] = audioCaps; } } }
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; } }
static void autoconnect_by_spec(jack_client_t *client, const char *port, const char *orig_spec, int is_cbox_input, int is_midi, const jack_port_t *only_connect_port, struct cbox_command_target *fb) { char *name, *copy_spec, *dpos; const char *use_name; copy_spec = g_strdup(orig_spec); name = copy_spec; do { dpos = strchr(name, ';'); if (dpos) *dpos = '\0'; use_name = name; if (use_name[0] == '#') { char *endptr = NULL; long portidx = strtol(use_name + 1, &endptr, 10) - 1; if (endptr == use_name + strlen(use_name)) { const char **names = jack_get_ports(client, ".*", is_midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE, is_cbox_input ? JackPortIsOutput : JackPortIsInput); // Client killed by JACK if (!names) return; int i; for (i = 0; i < portidx && names[i]; i++) ; if (names[i]) autoconnect_port(client, port, names[i], is_cbox_input, only_connect_port, fb); else g_message("Connect: unmatched port index %d", (int)portidx); jack_free(names); } } else if (use_name[0] == '~' || use_name[0] == '*') { const char **names = jack_get_ports(client, use_name + 1, is_midi ? JACK_DEFAULT_MIDI_TYPE : JACK_DEFAULT_AUDIO_TYPE, is_cbox_input ? JackPortIsOutput : JackPortIsInput); // Client killed by JACK if (!names) return; if (names && names[0]) { if (use_name[0] == '*') { int i; for (i = 0; names[i]; i++) autoconnect_port(client, port, names[i], is_cbox_input, only_connect_port, fb); } else autoconnect_port(client, port, names[0], is_cbox_input, only_connect_port, fb); } else g_message("Connect: unmatched port regexp %s", use_name); jack_free(names); } else autoconnect_port(client, port, use_name, is_cbox_input, only_connect_port, fb); if (dpos) name = dpos + 1; } while(dpos); g_free(copy_spec); }
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; }
static void *ja_init(const char *device, unsigned rate, unsigned latency) { jack_t *jd = (jack_t*)calloc(1, sizeof(jack_t)); if (!jd) return NULL; pthread_cond_init(&jd->cond, NULL); pthread_mutex_init(&jd->cond_lock, NULL); const char **jports = NULL; char *dest_ports[2]; size_t bufsize = 0; int parsed = 0; jd->client = jack_client_open("RetroArch", JackNullOption, NULL); if (jd->client == NULL) goto error; g_settings.audio.out_rate = jack_get_sample_rate(jd->client); jack_set_process_callback(jd->client, process_cb, jd); jack_on_shutdown(jd->client, shutdown_cb, jd); jd->ports[0] = jack_port_register(jd->client, "left", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); jd->ports[1] = jack_port_register(jd->client, "right", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (jd->ports[0] == NULL || jd->ports[1] == NULL) { RARCH_ERR("Failed to register ports.\n"); goto error; } jports = jack_get_ports(jd->client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); if (jports == NULL) { RARCH_ERR("Failed to get ports.\n"); goto error; } bufsize = find_buffersize(jd, latency); jd->buffer_size = bufsize; RARCH_LOG("JACK: Internal buffer size: %d frames.\n", (int)(bufsize / sizeof(jack_default_audio_sample_t))); for (int i = 0; i < 2; i++) { jd->buffer[i] = jack_ringbuffer_create(bufsize); if (jd->buffer[i] == NULL) { RARCH_ERR("Failed to create buffers.\n"); goto error; } } parsed = parse_ports(dest_ports, jports); if (jack_activate(jd->client) < 0) { RARCH_ERR("Failed to activate Jack...\n"); goto error; } for (int i = 0; i < 2; i++) { if (jack_connect(jd->client, jack_port_name(jd->ports[i]), dest_ports[i])) { RARCH_ERR("Failed to connect to Jack port.\n"); goto error; } } for (int i = 0; i < parsed; i++) free(dest_ports[i]); jack_free(jports); return jd; error: if (jports != NULL) jack_free(jports); return NULL; }
static int op_jack_init(void) { #ifdef HAVE_SAMPLERATE for (int i = 0; i < CHANNELS; i++) { src_state[i] = src_new(src_quality, 1, NULL); if (src_state[i] == NULL) { d_print("src_new failed"); for (i = i - 1; i >= 0; i--) { src_delete(src_state[i]); } return -OP_ERROR_INTERNAL; } } #endif jack_set_error_function(op_jack_error_cb); jack_options_t options = JackNullOption; if (fail) { /* since jackd failed, it will not be autostarted. Either jackd * was killed intentionaly or it died by heartattack. * Until it is restarted, init will happily fail again * and again and again.. */ options |= JackNoStartServer; } jack_status_t status; client = jack_client_open("cmus", options, &status, server_name); if (client == NULL) { d_print("jack_client_new failed\n"); return -OP_ERROR_INTERNAL; } if (status & JackServerStarted) { d_print("jackd started\n"); } jack_nframes_t jack_buffer_size = jack_get_buffer_size(client); jack_sample_rate = jack_get_sample_rate(client); op_jack_buffer_init(jack_buffer_size, NULL); jack_set_process_callback(client, op_jack_cb, NULL); jack_set_sample_rate_callback(client, op_jack_sample_rate_cb, NULL); jack_set_buffer_size_callback(client, op_jack_buffer_init, NULL); jack_on_shutdown(client, op_jack_shutdown_cb, NULL); for (int i = 0; i < CHANNELS; i++) { char port_name[20]; snprintf(port_name, sizeof(port_name)-1, "output %d", i); output_ports[i] = jack_port_register( client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); if (output_ports[i] == NULL) { d_print("no jack ports available\n"); return -OP_ERROR_INTERNAL; } } if (jack_activate(client)) { d_print("jack_client_activate failed\n"); return -OP_ERROR_INTERNAL; } const char **ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsInput); if (ports == NULL) { d_print("cannot get playback ports\n"); return -OP_ERROR_INTERNAL; } for (int i = 0; i < CHANNELS; i++) { if (ports[i] == NULL) { d_print("could not connect output %d. too few ports.\n", i); break; } if (jack_connect(client, jack_port_name(output_ports[i]), ports[i])) { d_print("connot connect port %s\n", ports[i]); jack_free(ports); return -OP_ERROR_INTERNAL; } } jack_free(ports); fail = 0; return OP_ERROR_SUCCESS; }