static int init(struct ao *ao) { struct priv *p = ao->priv; const char **matching_ports = NULL; char *port_name = p->cfg_port && p->cfg_port[0] ? p->cfg_port : NULL; jack_options_t open_options = JackNullOption; int port_flags = JackPortIsInput; int i; struct mp_chmap_sel sel = {0}; if (p->stdlayout == 0) { mp_chmap_sel_add_waveext(&sel); } else if (p->stdlayout == 1) { mp_chmap_sel_add_alsa_def(&sel); } else { mp_chmap_sel_add_any(&sel); } if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) goto err_out; if (!p->autostart) open_options |= JackNoStartServer; p->client = jack_client_open(p->cfg_client_name, open_options, NULL); if (!p->client) { MP_FATAL(ao, "cannot open server\n"); goto err_out; } jack_set_process_callback(p->client, outputaudio, ao); // list matching ports if connections should be made if (p->connect) { if (!port_name) port_flags |= JackPortIsPhysical; matching_ports = jack_get_ports(p->client, port_name, NULL, port_flags); if (!matching_ports || !matching_ports[0]) { MP_FATAL(ao, "no physical ports available\n"); goto err_out; } i = 1; p->num_ports = ao->channels.num; while (matching_ports[i]) i++; if (p->num_ports > i) p->num_ports = i; } // create out output ports for (i = 0; i < p->num_ports; i++) { char pname[30]; snprintf(pname, 30, "out_%d", i); p->ports[i] = jack_port_register(p->client, pname, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (!p->ports[i]) { MP_FATAL(ao, "not enough ports available\n"); goto err_out; } } if (jack_activate(p->client)) { MP_FATAL(ao, "activate failed\n"); goto err_out; } for (i = 0; i < p->num_ports; i++) { if (jack_connect(p->client, jack_port_name(p->ports[i]), matching_ports[i])) { MP_FATAL(ao, "connecting failed\n"); goto err_out; } } ao->samplerate = jack_get_sample_rate(p->client); jack_latency_range_t jack_latency_range; jack_port_get_latency_range(p->ports[0], JackPlaybackLatency, &jack_latency_range); p->jack_latency = (float)(jack_latency_range.max + jack_get_buffer_size(p->client)) / (float)ao->samplerate; p->callback_interval = 0; if (!ao_chmap_sel_get_def(ao, &sel, &ao->channels, p->num_ports)) goto err_out; ao->format = AF_FORMAT_FLOAT_NE; int unitsize = ao->channels.num * sizeof(float); p->outburst = (CHUNK_SIZE + unitsize - 1) / unitsize * unitsize; p->ring = mp_ring_new(p, NUM_CHUNKS * p->outburst); free(matching_ports); return 0; err_out: free(matching_ports); if (p->client) jack_client_close(p->client); return -1; }
static int init(struct ao *ao) { if (SDL_WasInit(SDL_INIT_AUDIO)) { mp_msg(MSGT_AO, MSGL_ERR, "[sdl] already initialized\n"); return -1; } struct priv *priv = ao->priv; if (SDL_InitSubSystem(SDL_INIT_AUDIO)) { if (!ao->probing) mp_msg(MSGT_AO, MSGL_ERR, "[sdl] SDL_Init failed\n"); uninit(ao, true); return -1; } struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_waveext_def(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) { uninit(ao, true); return -1; } SDL_AudioSpec desired, obtained; switch (ao->format) { case AF_FORMAT_U8: desired.format = AUDIO_U8; break; case AF_FORMAT_S8: desired.format = AUDIO_S8; break; case AF_FORMAT_U16_LE: desired.format = AUDIO_U16LSB; break; case AF_FORMAT_U16_BE: desired.format = AUDIO_U16MSB; break; default: case AF_FORMAT_S16_LE: desired.format = AUDIO_S16LSB; break; case AF_FORMAT_S16_BE: desired.format = AUDIO_S16MSB; break; #ifdef AUDIO_S32LSB case AF_FORMAT_S32_LE: desired.format = AUDIO_S32LSB; break; #endif #ifdef AUDIO_S32MSB case AF_FORMAT_S32_BE: desired.format = AUDIO_S32MSB; break; #endif #ifdef AUDIO_F32LSB case AF_FORMAT_FLOAT_LE: desired.format = AUDIO_F32LSB; break; #endif #ifdef AUDIO_F32MSB case AF_FORMAT_FLOAT_BE: desired.format = AUDIO_F32MSB; break; #endif } desired.freq = ao->samplerate; desired.channels = ao->channels.num; desired.samples = FFMIN(32768, ceil_power_of_two(ao->samplerate * priv->buflen)); desired.callback = audio_callback; desired.userdata = ao; mp_msg(MSGT_AO, MSGL_V, "[sdl] requested format: %d Hz, %d channels, %x, " "buffer size: %d samples\n", (int) desired.freq, (int) desired.channels, (int) desired.format, (int) desired.samples); obtained = desired; if (SDL_OpenAudio(&desired, &obtained)) { if (!ao->probing) mp_msg(MSGT_AO, MSGL_ERR, "[sdl] could not open audio: %s\n", SDL_GetError()); uninit(ao, true); return -1; } mp_msg(MSGT_AO, MSGL_V, "[sdl] obtained format: %d Hz, %d channels, %x, " "buffer size: %d samples\n", (int) obtained.freq, (int) obtained.channels, (int) obtained.format, (int) obtained.samples); switch (obtained.format) { case AUDIO_U8: ao->format = AF_FORMAT_U8; break; case AUDIO_S8: ao->format = AF_FORMAT_S8; break; case AUDIO_S16LSB: ao->format = AF_FORMAT_S16_LE; break; case AUDIO_S16MSB: ao->format = AF_FORMAT_S16_BE; break; case AUDIO_U16LSB: ao->format = AF_FORMAT_U16_LE; break; case AUDIO_U16MSB: ao->format = AF_FORMAT_U16_BE; break; #ifdef AUDIO_S32LSB case AUDIO_S32LSB: ao->format = AF_FORMAT_S32_LE; break; #endif #ifdef AUDIO_S32MSB case AUDIO_S32MSB: ao->format = AF_FORMAT_S32_BE; break; #endif #ifdef AUDIO_F32LSB case AUDIO_F32LSB: ao->format = AF_FORMAT_FLOAT_LE; break; #endif #ifdef AUDIO_F32MSB case AUDIO_F32MSB: ao->format = AF_FORMAT_FLOAT_BE; break; #endif default: if (!ao->probing) mp_msg(MSGT_AO, MSGL_ERR, "[sdl] could not find matching format\n"); uninit(ao, true); return -1; } if (!ao_chmap_sel_get_def(ao, &sel, &ao->channels, obtained.channels)) { uninit(ao, true); return -1; } ao->samplerate = obtained.freq; priv->buffer = av_fifo_alloc(obtained.size * priv->bufcnt); priv->buffer_mutex = SDL_CreateMutex(); if (!priv->buffer_mutex) { mp_msg(MSGT_AO, MSGL_ERR, "[sdl] SDL_CreateMutex failed\n"); uninit(ao, true); return -1; } priv->underrun_cond = SDL_CreateCond(); if (!priv->underrun_cond) { mp_msg(MSGT_AO, MSGL_ERR, "[sdl] SDL_CreateCond failed\n"); uninit(ao, true); return -1; } priv->unpause = 1; priv->paused = 1; priv->callback_time0 = priv->callback_time1 = mp_time_us(); return 1; }
static int init(int rate, const struct mp_chmap *channels, int format, int flags) { const char **matching_ports = NULL; char *port_name = NULL; char *client_name = NULL; int autostart = 0; int connect = 1; const opt_t subopts[] = { {"port", OPT_ARG_MSTRZ, &port_name, NULL}, {"name", OPT_ARG_MSTRZ, &client_name, NULL}, {"estimate", OPT_ARG_BOOL, &estimate, NULL}, {"autostart", OPT_ARG_BOOL, &autostart, NULL}, {"connect", OPT_ARG_BOOL, &connect, NULL}, {NULL} }; jack_options_t open_options = JackUseExactName; int port_flags = JackPortIsInput; int i; estimate = 1; if (subopt_parse(ao_subdevice, subopts) != 0) { print_help(); return 0; } struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_waveext(&sel); if (!ao_chmap_sel_adjust(&ao_data, &sel, &ao_data.channels)) goto err_out; if (!client_name) { client_name = malloc(40); sprintf(client_name, "mpv [%d]", getpid()); } if (!autostart) open_options |= JackNoStartServer; client = jack_client_open(client_name, open_options, NULL); if (!client) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] cannot open server\n"); goto err_out; } buffer = av_fifo_alloc(BUFFSIZE); jack_set_process_callback(client, outputaudio, 0); // list matching ports if connections should be made if (connect) { if (!port_name) port_flags |= JackPortIsPhysical; matching_ports = jack_get_ports(client, port_name, NULL, port_flags); if (!matching_ports || !matching_ports[0]) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] no physical ports available\n"); goto err_out; } i = 1; num_ports = ao_data.channels.num; while (matching_ports[i]) i++; if (num_ports > i) num_ports = i; } // create out output ports for (i = 0; i < num_ports; i++) { char pname[30]; snprintf(pname, 30, "out_%d", i); ports[i] = jack_port_register(client, pname, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); if (!ports[i]) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] not enough ports available\n"); goto err_out; } } if (jack_activate(client)) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] activate failed\n"); goto err_out; } for (i = 0; i < num_ports; i++) { if (jack_connect(client, jack_port_name(ports[i]), matching_ports[i])) { mp_msg(MSGT_AO, MSGL_FATAL, "[JACK] connecting failed\n"); goto err_out; } } rate = jack_get_sample_rate(client); jack_latency_range_t jack_latency_range; jack_port_get_latency_range(ports[0], JackPlaybackLatency, &jack_latency_range); jack_latency = (float)(jack_latency_range.max + jack_get_buffer_size(client)) / (float)rate; callback_interval = 0; if (!ao_chmap_sel_get_def(&ao_data, &sel, &ao_data.channels, num_ports)) goto err_out; ao_data.samplerate = rate; ao_data.format = AF_FORMAT_FLOAT_NE; ao_data.bps = ao_data.channels.num * rate * sizeof(float); ao_data.buffersize = CHUNK_SIZE * NUM_CHUNKS; ao_data.outburst = CHUNK_SIZE; free(matching_ports); free(port_name); free(client_name); return 1; err_out: free(matching_ports); free(port_name); free(client_name); if (client) jack_client_close(client); av_fifo_free(buffer); buffer = NULL; return 0; }
static int init(struct ao *ao) { if (SDL_WasInit(SDL_INIT_AUDIO)) { MP_ERR(ao, "already initialized\n"); return -1; } struct priv *priv = ao->priv; if (SDL_InitSubSystem(SDL_INIT_AUDIO)) { if (!ao->probing) MP_ERR(ao, "SDL_Init failed\n"); uninit(ao); return -1; } struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_waveext_def(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) { uninit(ao); return -1; } ao->format = af_fmt_from_planar(ao->format); SDL_AudioSpec desired, obtained; desired.format = AUDIO_S16SYS; for (int n = 0; fmtmap[n][0]; n++) { if (ao->format == fmtmap[n][0]) { desired.format = fmtmap[n][1]; break; } } desired.freq = ao->samplerate; desired.channels = ao->channels.num; desired.samples = MPMIN(32768, ceil_power_of_two(ao->samplerate * priv->buflen)); desired.callback = audio_callback; desired.userdata = ao; MP_VERBOSE(ao, "requested format: %d Hz, %d channels, %x, " "buffer size: %d samples\n", (int) desired.freq, (int) desired.channels, (int) desired.format, (int) desired.samples); obtained = desired; if (SDL_OpenAudio(&desired, &obtained)) { if (!ao->probing) MP_ERR(ao, "could not open audio: %s\n", SDL_GetError()); uninit(ao); return -1; } MP_VERBOSE(ao, "obtained format: %d Hz, %d channels, %x, " "buffer size: %d samples\n", (int) obtained.freq, (int) obtained.channels, (int) obtained.format, (int) obtained.samples); // The sample count is usually the number of samples the callback requests, // which we assume is the period size. Normally, ao.c will allocate a large // enough buffer. But in case the period size should be pathologically // large, this will help. ao->device_buffer = 3 * obtained.samples; ao->format = 0; for (int n = 0; fmtmap[n][0]; n++) { if (obtained.format == fmtmap[n][1]) { ao->format = fmtmap[n][0]; break; } } if (!ao->format) { if (!ao->probing) MP_ERR(ao, "could not find matching format\n"); uninit(ao); return -1; } if (!ao_chmap_sel_get_def(ao, &sel, &ao->channels, obtained.channels)) { uninit(ao); return -1; } ao->samplerate = obtained.freq; priv->paused = 1; return 1; }
static int init(struct ao *ao) { struct priv *p = ao->priv; struct mp_chmap_sel sel = {0}; jack_options_t open_options; ao->format = AF_FORMAT_FLOATP; switch (p->stdlayout) { case 0: mp_chmap_sel_add_waveext(&sel); break; case 1: mp_chmap_sel_add_alsa_def(&sel); break; default: mp_chmap_sel_add_any(&sel); } if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) goto err_chmap; open_options = JackNullOption; if (!p->autostart) open_options |= JackNoStartServer; p->client = jack_client_open(p->cfg_client_name, open_options, NULL); if (!p->client) { MP_FATAL(ao, "cannot open server\n"); goto err_client_open; } if (create_ports(ao, ao->channels.num)) goto err_create_ports; jack_set_process_callback(p->client, process, ao); if (jack_activate(p->client)) { MP_FATAL(ao, "activate failed\n"); goto err_activate; } ao->samplerate = jack_get_sample_rate(p->client); if (p->connect) if (connect_to_outports(ao)) goto err_connect; jack_latency_range_t jack_latency_range; jack_port_get_latency_range(p->ports[0], JackPlaybackLatency, &jack_latency_range); p->jack_latency = (float)(jack_latency_range.max + jack_get_buffer_size(p->client)) / (float)ao->samplerate; if (!ao_chmap_sel_get_def(ao, &sel, &ao->channels, p->num_ports)) goto err_chmap_sel_get_def; return 0; err_chmap_sel_get_def: err_connect: jack_deactivate(p->client); err_activate: err_create_ports: jack_client_close(p->client); err_client_open: err_chmap: return -1; }