static int init(struct ao *ao) { MP_VERBOSE(ao, "init!\n"); ao->format = af_fmt_from_planar(ao->format); struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_waveext(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) return -1; struct wasapi_state *state = (struct wasapi_state *)ao->priv; state->log = ao->log; wasapi_fill_VistaBlob(state); if (state->opt_list) { wasapi_enumerate_devices(state->log, NULL, NULL); } if (state->opt_exclusive) { state->share_mode = AUDCLNT_SHAREMODE_EXCLUSIVE; } else { state->share_mode = AUDCLNT_SHAREMODE_SHARED; } state->init_done = CreateEventW(NULL, FALSE, FALSE, NULL); state->hUninit = CreateEventW(NULL, FALSE, FALSE, NULL); state->hFeed = CreateEventW(NULL, FALSE, FALSE, NULL); /* for wasapi event mode */ state->hForceFeed = CreateEventW(NULL, FALSE, FALSE, NULL); state->hFeedDone = CreateEventW(NULL, FALSE, FALSE, NULL); if (!state->init_done || !state->hFeed || !state->hUninit || !state->hForceFeed || !state->hFeedDone) { closehandles(ao); /* failed to init events */ return -1; } state->init_ret = -1; state->threadLoop = (HANDLE)CreateThread(NULL, 0, &ThreadLoop, ao, 0, NULL); if (!state->threadLoop) { /* failed to init thread */ MP_ERR(ao, "fail to create thread!\n"); return -1; } WaitForSingleObject(state->init_done, INFINITE); /* wait on init complete */ if (state->init_ret) { if (!ao->probing) { MP_ERR(ao, "thread_init failed!\n"); } } else MP_VERBOSE(ao, "Init Done!\n"); wasapi_setup_proxies(state); return state->init_ret; }
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; }
/** \brief setup sound device \param rate samplerate \param channels number of channels \param format format \param flags unused \return 0=success -1=fail */ static int init(struct ao *ao) { struct priv *p = ao->priv; int res; if (!InitDirectSound(ao)) return -1; ao->no_persistent_volume = true; p->audio_volume = 100; // ok, now create the buffers WAVEFORMATEXTENSIBLE wformat; DSBUFFERDESC dsbpridesc; DSBUFFERDESC dsbdesc; int format = af_fmt_from_planar(ao->format); int rate = ao->samplerate; if (AF_FORMAT_IS_AC3(format)) format = AF_FORMAT_AC3; else { struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_waveext(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) return -1; } switch (format) { case AF_FORMAT_AC3: case AF_FORMAT_S24_LE: case AF_FORMAT_S16_LE: case AF_FORMAT_U8: break; default: MP_VERBOSE(ao, "format %s not supported defaulting to Signed 16-bit Little-Endian\n", af_fmt_to_str(format)); format = AF_FORMAT_S16_LE; } //set our audio parameters ao->samplerate = rate; ao->format = format; ao->bps = ao->channels.num * rate * (af_fmt2bits(format) >> 3); int buffersize = ao->bps; // space for 1 sec MP_VERBOSE(ao, "Samplerate:%iHz Channels:%i Format:%s\n", rate, ao->channels.num, af_fmt_to_str(format)); MP_VERBOSE(ao, "Buffersize:%d bytes (%d msec)\n", buffersize, buffersize / ao->bps * 1000); //fill waveformatex ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE)); wformat.Format.cbSize = (ao->channels.num > 2) ? sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX) : 0; wformat.Format.nChannels = ao->channels.num; wformat.Format.nSamplesPerSec = rate; if (AF_FORMAT_IS_AC3(format)) { wformat.Format.wFormatTag = WAVE_FORMAT_DOLBY_AC3_SPDIF; wformat.Format.wBitsPerSample = 16; wformat.Format.nBlockAlign = 4; } else { wformat.Format.wFormatTag = (ao->channels.num > 2) ? WAVE_FORMAT_EXTENSIBLE : WAVE_FORMAT_PCM; wformat.Format.wBitsPerSample = af_fmt2bits(format); wformat.Format.nBlockAlign = wformat.Format.nChannels * (wformat.Format.wBitsPerSample >> 3); } // fill in primary sound buffer descriptor memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC)); dsbpridesc.dwSize = sizeof(DSBUFFERDESC); dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbpridesc.dwBufferBytes = 0; dsbpridesc.lpwfxFormat = NULL; // fill in the secondary sound buffer (=stream buffer) descriptor memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); dsbdesc.dwSize = sizeof(DSBUFFERDESC); dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */ | DSBCAPS_GLOBALFOCUS /** Allows background playing */ | DSBCAPS_CTRLVOLUME; /** volume control enabled */ if (ao->channels.num > 2) { wformat.dwChannelMask = mp_chmap_to_waveext(&ao->channels); wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample; // Needed for 5.1 on emu101k - shit soundblaster dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE; } wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign; dsbdesc.dwBufferBytes = buffersize; dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat; p->buffer_size = dsbdesc.dwBufferBytes; p->write_offset = 0; p->min_free_space = wformat.Format.nBlockAlign; p->outburst = wformat.Format.nBlockAlign * 512; // create primary buffer and set its format res = IDirectSound_CreateSoundBuffer(p->hds, &dsbpridesc, &p->hdspribuf, NULL); if (res != DS_OK) { UninitDirectSound(ao); MP_ERR(ao, "cannot create primary buffer (%s)\n", dserr2str(res)); return -1; } res = IDirectSoundBuffer_SetFormat(p->hdspribuf, (WAVEFORMATEX *)&wformat); if (res != DS_OK) { MP_WARN(ao, "cannot set primary buffer format (%s), using " "standard setting (bad quality)", dserr2str(res)); } MP_VERBOSE(ao, "primary buffer created\n"); // now create the stream buffer res = IDirectSound_CreateSoundBuffer(p->hds, &dsbdesc, &p->hdsbuf, NULL); if (res != DS_OK) { if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) { // Try without DSBCAPS_LOCHARDWARE dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE; res = IDirectSound_CreateSoundBuffer(p->hds, &dsbdesc, &p->hdsbuf, NULL); } if (res != DS_OK) { UninitDirectSound(ao); MP_ERR(ao, "cannot create secondary (stream)buffer (%s)\n", dserr2str(res)); return -1; } } MP_VERBOSE(ao, "secondary (stream)buffer created\n"); return 0; }
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) { 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; }