📄 audio.c
字号:
sample_silence_dS(out_l, nframes); sample_silence_dS(out_r, nframes); } /* notify the client of completed wave headers */ wodHelper_NotifyCompletions(wwo, FALSE); LeaveCriticalSection(&wwo->access_crst); TRACE("ending\n"); return 0;}/****************************************************************** * JACK_bufsize * * Called whenever the jack server changes the the max number * of frames passed to JACK_callback */int JACK_bufsize (nframes_t nframes, void *arg){ WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg; DWORD buffer_required; TRACE("the maximum buffer size is now %lu frames\n", nframes); /* make sure the callback routine has adequate memory */ /* see if our buffer is large enough for the data we are writing */ /* ie. Buffer_size < (bytes we already wrote + bytes we are going to write in this loop) */ EnterCriticalSection(&wwo->access_crst); buffer_required = sizeof(sample_t) * nframes; if(wwo->buffer_size < buffer_required) { TRACE("expanding buffer from wwo->buffer_size == %ld, to %ld\n", wwo->buffer_size, buffer_required); TRACE("GetProcessHeap() == %p\n", GetProcessHeap()); wwo->buffer_size = buffer_required; if (wwo->sound_buffer) wwo->sound_buffer = HeapReAlloc(GetProcessHeap(), 0, wwo->sound_buffer, wwo->buffer_size); else wwo->sound_buffer = HeapAlloc(GetProcessHeap(), 0, wwo->buffer_size); /* if we don't have a buffer then error out */ if(!wwo->sound_buffer) { ERR("error allocating sound_buffer memory\n"); LeaveCriticalSection(&wwo->access_crst); return 0; } } LeaveCriticalSection(&wwo->access_crst); TRACE("called\n"); return 0;}/****************************************************************** * JACK_srate */int JACK_srate (nframes_t nframes, void *arg){ TRACE("the sample rate is now %lu/sec\n", nframes); return 0;}/****************************************************************** * JACK_shutdown *//* if this is called then jack shut down... handle this appropriately */void JACK_shutdown(void* arg){ WINE_WAVEOUT* wwo = (WINE_WAVEOUT*)arg; wwo->client = 0; /* reset client */ TRACE("trying to reconnect after sleeping for a short while...\n"); /* lets see if we can't reestablish the connection */ Sleep(750); /* pause for a short period of time */ if(!JACK_OpenDevice(wwo)) { ERR("unable to reconnect with jack...\n"); }}/****************************************************************** * JACK_OpenDevice */static int JACK_OpenDevice(WINE_WAVEOUT* wwo){ const char** ports; int i; char client_name[64]; jack_port_t* out_port_l; jack_port_t* out_port_r; jack_client_t* client; int failed = 0; TRACE("creating jack client and setting up callbacks\n");#if JACK_CLOSE_HACK /* see if this device is already open */ if(wwo->client) { /* if this device is already in use then it is bad for us to be in here */ if(wwo->in_use) return 0; TRACE("using existing client\n"); wwo->in_use = TRUE; return 1; }#endif /* zero out the buffer pointer and the size of the buffer */ wwo->sound_buffer = 0; wwo->buffer_size = 0; /* try to become a client of the JACK server */ snprintf(client_name, sizeof(client_name), "wine_jack_client %d", wwo->wDevID); TRACE("client name '%s'\n", client_name); if ((client = fp_jack_client_new (client_name)) == 0) { /* jack has problems with shutting down clients, so lets */ /* wait a short while and try once more before we give up */ Sleep(250); if ((client = fp_jack_client_new (client_name)) == 0) { ERR("jack server not running?\n"); return 0; } } /* tell the JACK server to call `JACK_callback()' whenever there is work to be done. */ fp_jack_set_process_callback (client, JACK_callback, wwo); /* tell the JACK server to call `JACK_bufsize()' whenever the maximum number of frames that will be passed to `JACK_Callback()' changes */ fp_jack_set_buffer_size_callback (client, JACK_bufsize, wwo); /* tell the JACK server to call `srate()' whenever the sample rate of the system changes. */ fp_jack_set_sample_rate_callback (client, JACK_srate, wwo); /* tell the JACK server to call `jack_shutdown()' if it ever shuts down, either entirely, or if it just decides to stop calling us. */ fp_jack_on_shutdown (client, JACK_shutdown, wwo); /* display the current sample rate. once the client is activated (see below), you should rely on your own sample rate callback (see above) for this value. */ wwo->sample_rate = fp_jack_get_sample_rate(client); TRACE("engine sample rate: %lu\n", wwo->sample_rate); /* create the left and right channel output ports */ /* jack's ports are all mono so for stereo you need two */ out_port_l = fp_jack_port_register (client, "out_l", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); out_port_r = fp_jack_port_register (client, "out_r", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); /* save away important values to the WINE_WAVEOUT struct */ wwo->client = client; wwo->out_port_l = out_port_l; wwo->out_port_r = out_port_r;#if JACK_CLOSE_HACK wwo->in_use = TRUE; /* mark this device as in use since it now is ;-) */#endif /* tell the JACK server that we are ready to roll */ if (fp_jack_activate (client)) { ERR( "cannot activate client\n"); return 0; } /* figure out what the ports that we want to output on are */ /* NOTE: we do this instead of using stuff like "alsa_pcm:playback_X" because */ /* this way works if names are changed */ ports = fp_jack_get_ports(client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); /* display a trace of the output ports we found */ for(i = 0; ports[i]; i++) { TRACE("ports[%d] = '%s'\n", i, ports[i]); } if(!ports) { ERR("jack_get_ports() failed to find 'JackPortIsPhysical|JackPortIsInput'\n"); } /* connect the ports. Note: you can't do this before the client is activated (this may change in the future). */ /* we want to connect to two ports so we have stereo output ;-) */ if(fp_jack_connect(client, fp_jack_port_name(out_port_l), ports[0])) { ERR ("cannot connect to output port %d('%s')\n", 0, ports[0]); failed = 1; } if(fp_jack_connect(client, fp_jack_port_name(out_port_r), ports[1])) { ERR ("cannot connect to output port %d('%s')\n", 1, ports[1]); failed = 1; } free(ports); /* free the returned array of ports */ /* if something failed we need to shut the client down and return 0 */ if(failed) { JACK_CloseDevice(wwo, TRUE); return 0; } return 1; /* return success */}/****************************************************************** * JACK_CloseDevice * * Close the connection to the server cleanly. * If close_client is TRUE we close the client for this device instead of * just marking the device as in_use(JACK_CLOSE_HACK only) */#if JACK_CLOSE_HACKstatic void JACK_CloseDevice(WINE_WAVEOUT* wwo, BOOL close_client)#elsestatic void JACK_CloseDevice(WINE_WAVEOUT* wwo)#endif{#if JACK_CLOSE_HACK TRACE("wDevID: %d, close_client: %d\n", wwo->wDevID, close_client);#else TRACE("wDevID: %d\n", wwo->wDevID);#endif#if JACK_CLOSE_HACK if(close_client) {#endif fp_jack_deactivate(wwo->client); /* supposed to help the jack_client_close() to succeed */ fp_jack_client_close (wwo->client); EnterCriticalSection(&wwo->access_crst); wwo->client = 0; /* reset client */ HeapFree(GetProcessHeap(), 0, wwo->sound_buffer); /* free buffer memory */ wwo->sound_buffer = 0; wwo->buffer_size = 0; /* zero out size of the buffer */ LeaveCriticalSection(&wwo->access_crst);#if JACK_CLOSE_HACK } else { EnterCriticalSection(&wwo->access_crst); TRACE("setting in_use to FALSE\n"); wwo->in_use = FALSE; LeaveCriticalSection(&wwo->access_crst); }#endif}/****************************************************************** * JACK_WaveRelease * * */LONG JACK_WaveRelease(void){ int iDevice; TRACE("closing all open devices\n"); /* close all open devices */ for(iDevice = 0; iDevice < MAX_WAVEOUTDRV; iDevice++) { TRACE("iDevice == %d\n", iDevice); if(WOutDev[iDevice].client) {#if JACK_CLOSE_HACK JACK_CloseDevice(&WOutDev[iDevice], TRUE); /* close the device, FORCE the client to close */#else JACK_CloseDevice(&WOutDev[iDevice]); /* close the device, FORCE the client to close */#endif DeleteCriticalSection(&(WOutDev[iDevice].access_crst)); /* delete the critical section */ } } TRACE("returning 1\n"); return 1;}/****************************************************************** * JACK_WaveInit * * Initialize internal structures from JACK server info */LONG JACK_WaveInit(void){ int i; TRACE("called\n"); /* setup function pointers */#define LOAD_FUNCPTR(f) if((fp_##f = wine_dlsym(jackhandle, #f, NULL, 0)) == NULL) goto sym_not_found; LOAD_FUNCPTR(jack_activate); LOAD_FUNCPTR(jack_connect); LOAD_FUNCPTR(jack_client_new); LOAD_FUNCPTR(jack_client_close); LOAD_FUNCPTR(jack_deactivate); LOAD_FUNCPTR(jack_set_process_callback); LOAD_FUNCPTR(jack_set_buffer_size_callback); LOAD_FUNCPTR(jack_set_sample_rate_callback); LOAD_FUNCPTR(jack_on_shutdown); LOAD_FUNCPTR(jack_get_sample_rate); LOAD_FUNCPTR(jack_port_register); LOAD_FUNCPTR(jack_port_get_buffer); LOAD_FUNCPTR(jack_get_ports); LOAD_FUNCPTR(jack_port_name);#undef LOAD_FUNCPTR /* start with output device */ for (i = 0; i < MAX_WAVEOUTDRV; ++i) { WOutDev[i].client = 0; /* initialize the client to 0 */#if JACK_CLOSE_HACK WOutDev[i].in_use = FALSE;#endif memset(&WOutDev[i].caps, 0, sizeof(WOutDev[i].caps)); /* FIXME: some programs compare this string against the content of the registry * for MM drivers. The names have to match in order for the program to work * (e.g. MS win9x mplayer.exe) */#ifdef EMULATE_SB16 WOutDev[i].caps.wMid = 0x0002; WOutDev[i].caps.wPid = 0x0104; strcpy(WOutDev[i].caps.szPname, "SB16 Wave Out");#else WOutDev[i].caps.wMid = 0x00FF; /* Manufac ID */ WOutDev[i].caps.wPid = 0x0001; /* Product ID */ /* strcpy(WOutDev[i].caps.szPname, "OpenSoundSystem WAVOUT Driver");*/ strcpy(WOutDev[i].caps.szPname, "CS4236/37/38");#endif WOutDev[i].caps.vDriverVersion = 0x0100; WOutDev[i].caps.dwFormats = 0x00000000; WOutDev[i].caps.dwSupport = WAVECAPS_VOLUME; WOutDev[i].caps.wChannels = 2; WOutDev[i].caps.dwSupport |= WAVECAPS_LRVOLUME;/* NOTE: we don't support any 8 bit modes so note that *//* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M08; WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S08; */ WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4S16; WOutDev[i].caps.dwFormats |= WAVE_FORMAT_4M16;/* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M08; WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S08; */ WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2M16; WOutDev[i].caps.dwFormats |= WAVE_FORMAT_2S16;/* WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M08; WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S08;*/ WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1M16; WOutDev[i].caps.dwFormats |= WAVE_FORMAT_1S16; } /* then do input device */ for (i = 0; i < MAX_WAVEINDRV; ++i) { /* TODO: we should initialize read stuff here */ memset(&WInDev[0].caps, 0, sizeof(WInDev[0].caps)); } return 1; /* return success *//* error path for function pointer loading errors */sym_not_found: WINE_MESSAGE( "Wine cannot find certain functions that it needs inside the jack" "library. To enable Wine to use the jack audio server please " "install libjack\n"); wine_dlclose(jackhandle, NULL, 0); jackhandle = NULL; return FALSE;}/*======================================================================* * Low level WAVE OUT implementation * *======================================================================*//************************************************************************** * wodNotifyClient [internal] */static DWORD wodNotifyClient(WINE_WAVEOUT* wwo, WORD wMsg, DWORD dwParam1, DWORD dwParam2){ TRACE("wMsg = 0x%04x dwParm1 = %04lX dwParam2 = %04lX\n", wMsg, dwParam1, dwParam2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -