3312N/A * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 0N/A// GetPosition method 1: based on how many bytes are passed to the kernel driver 0N/A// + does not need much processor resources 0N/A// - not very exact, "jumps" 0N/A// GetPosition method 2: ask kernel about actual position of playback. 0N/A// - switch to kernel layer for each call 0N/A// GetPosition method 3: use snd_pcm_avail() call - not yet in official ALSA 0N/A// quick tests on a Pentium 200MMX showed max. 1.5% processor usage 0N/A// for playing back a CD-quality file and printing 20x per second a line 0N/A// on the console with the current time. So I guess performance is not such a 0N/A//#define GET_POSITION_METHOD1 0N/A// The default time for a period in microseconds. 0N/A// For very small buffers, only 2 periods are used. 0N/A// 6: for anything above 24-bit 0N/A// 5: for 4 bytes sample size, 24-bit 0N/A// 4: for 3 bytes sample size, 24-bit 0N/A// 3: for 3 bytes sample size, 20-bit 0N/A// 2: for 2 bytes sample size, 16-bit 0N/A// 1: for 1 byte sample size, 8-bit 0N/A// 0: for anything else 0N/A case 3:
/* fall through */ 0N/A case 4:
/* fall through */ 0N/A ERROR1(
"snd_pcm_format_mask_malloc returned error %d\n",
ret);
0N/A ERROR1(
"snd_pcm_hw_params_malloc returned error %d\n",
ret);
1992N/A /* snd_pcm_hw_params_any can return a positive value on success too */ 1992N/A /* for the logic following this code, set ret to 0 to indicate success */ 0N/A ERROR1(
"snd_pcm_hw_params_get_channels_min returned error %d\n",
ret);
0N/A ERROR1(
"snd_pcm_hw_params_get_channels_max returned error %d\n",
ret);
0N/A // since we queried the hw: device, for many soundcards, it will only 0N/A // report the maximum number of channels (which is the only way to talk 0N/A // to the hw: device). Since we will, however, open the plughw: device 0N/A // also the channels 1..maxChannels are available. 0N/A // plughw: supports any sample rate 0N/A // now if we use plughw:, we can use any bit size below the 0N/A // natively supported ones. Some ALSA drivers only support the maximum 0N/A // bit size, so we add any sample rates below the reported one. 0N/A // E.g. this iteration reports support for 16-bit. 0N/A // getBitIndex will return 2, so it will add entries for 0N/A // 16-bit (bitIndex=2) and in the next do-while loop iteration, 0N/A // it will decrease bitIndex and will therefore add 8-bit support. 0N/A // avoid too many channels explicitly listed 0N/A // just add -1, min, and max 0N/A // without plugin, do not add fake formats 0N/A //TRACE1("Format %d not supported\n", format); 4090N/A/** Workaround for cr 7033899, 7030629: 4090N/A * dmix plugin doesn't like flush (snd_pcm_drop) when the buffer is empty 4090N/A * (just opened, underruned or already flushed). 4090N/A * Sometimes it causes PCM falls to -EBADFD error, 4090N/A * sometimes causes bufferSize change. 4090N/A * To prevent unnecessary flushes AlsaPcmInfo::isRunning & isFlushed are used. 0N/A/* ******* ALSA PCM INFO ******************** */ 0N/A // to be used exclusively by getBytePosition! 0N/A // start device whenever anything is written to the buffer 0N/A // never start the device automatically 0N/A// returns TRUE if successful 0N/A /* choose all parameters */ 0N/A /* set the sample format */ 0N/A /* set the count of channels */ 0N/A /* set the stream rate */ 0N/A /* set the buffer time */ 0N/A ERROR2(
"Unable to set buffer size to %d frames: %s\n",
0N/A /* set the period time */ 0N/A /* set the period count for very small buffer sizes to 2 */ 0N/A /* write the parameters to device */ 0N/A// returns 1 if successful 0N/A /* get the current swparams */ 0N/A /* never start the transfer automatically */ 0N/A /* allow the transfer when at least period_size samples can be processed */ 0N/A /* write the parameters to the playback device */ 0N/A /* snd_pcm_uframes_t is 64 bit on 64-bit systems */ 0N/A // for using ALSA debug dump methods 4090N/A // initial values are: stopped, flushed 0N/A // set to blocking mode 0N/A ERROR1(
" snd_pcm_hw_params_malloc returned error %d\n",
ret);
0N/A TRACE3(
" DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n",
0N/A // set software parameters 0N/A ERROR1(
"snd_pcm_hw_params_malloc returned error %d\n",
ret);
0N/A // set to non-blocking mode 0N/A TRACE1(
"< DAUDIO_Open: Opened device successfully. Handle=%p\n",
0N/A // set to blocking mode 0N/A // set start mode so that it always starts as soon as data is there 0N/A // in case it was stopped previously 0N/A // in case there is still data in the buffers 0N/A // set to non-blocking mode 4090N/A // source line should keep isFlushed value until Write() is called; 4090N/A // for target data line reset it right now. 0N/A // set to blocking mode 0N/A // set to non-blocking mode 0N/A * Underrun and suspend recovery 0N/A * 0: exit native and return 0 0N/A * -1: error - exit native with return value -1 0N/A return 0;
/* wait until the suspend flag is released */ 0N/A TRACE0(
"xrun_recovery: EAGAIN try again flag.\n");
0N/A// returns -1 on error 0N/A ERROR2(
" DAUDIO_Write: byteSize=%d, frameSize=%d!\n",
0N/A count =
2;
// maximum number of trials to recover from underrun 0N/A //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize); 0N/A TRACE1(
"DAUDIO_Write: xrun recovery returned %d -> return.\n",
ret);
0N/A //ret = snd_pcm_frames_to_bytes(info->handle, writtenFrames); 0N/A// returns -1 on error 0N/A /*TRACE3(" info=%p, data=%p, byteSize=%d\n", 0N/A (void*) info, (void*) data, (int) byteSize); 0N/A TRACE2(" info->frameSize=%d, info->handle=%p\n", 0N/A (int) info->frameSize, (void*) info->handle); 0N/A ERROR2(
" DAUDIO_Read: byteSize=%d, frameSize=%d!\n",
0N/A count =
2;
// maximum number of trials to recover from error 0N/A //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize); 0N/A TRACE1(
"DAUDIO_Read: xrun recovery returned %d -> return.\n",
ret);
0N/A //ret = snd_pcm_frames_to_bytes(info->handle, readFrames); 0N/A //printState(state); 0N/A //TRACE1("Still draining: %s\n", (state != SND_PCM_STATE_XRUN)?"TRUE":"FALSE"); 0N/A // if in xrun state then we have the entire buffer available, 0N/A // not 0 as alsa reports 0N/A //ret = snd_pcm_frames_to_bytes(info->handle, availableInFrames); 0N/A // estimate the current position with the buffer size and 0N/A // the available bytes to read or write in the buffer. 0N/A // not an elegant solution - bytePos will stop on xruns, 0N/A // and in race conditions it may jump backwards 0N/A // Advantage is that it is indeed based on the samples that go through 0N/A // the system (rather than time-based methods) 0N/A // javaBytePos is the position that is reached when the current 0N/A // buffer is played completely 0N/A // javaBytePos is the position that was when the current buffer was empty 0N/A // note: slight race condition if this is called simultaneously from 2 threads 0N/A // calculate from time value, or from available bytes 0N/A //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result); 0N/A /* save to ignore, since GetBytePosition 0N/A * takes the javaBytePos param into account 0N/A // never need servicing on Linux 0N/A // never need servicing on Linux