|
Java example source code file (PLATFORM_API_SolarisOS_PCM.c)
The PLATFORM_API_SolarisOS_PCM.c Java example source code/* * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #define USE_ERROR #define USE_TRACE #include "PLATFORM_API_SolarisOS_Utils.h" #include "DirectAudio.h" #if USE_DAUDIO == TRUE // The default buffer time #define DEFAULT_PERIOD_TIME_MILLIS 50 ///// implemented functions of DirectAudio.h INT32 DAUDIO_GetDirectAudioDeviceCount() { return (INT32) getAudioDeviceCount(); } INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription* description) { AudioDeviceDescription desc; if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) { description->maxSimulLines = desc.maxSimulLines; strncpy(description->name, desc.name, DAUDIO_STRING_LENGTH-1); description->name[DAUDIO_STRING_LENGTH-1] = 0; strncpy(description->vendor, desc.vendor, DAUDIO_STRING_LENGTH-1); description->vendor[DAUDIO_STRING_LENGTH-1] = 0; strncpy(description->version, desc.version, DAUDIO_STRING_LENGTH-1); description->version[DAUDIO_STRING_LENGTH-1] = 0; /*strncpy(description->description, desc.description, DAUDIO_STRING_LENGTH-1);*/ strncpy(description->description, "Solaris Mixer", DAUDIO_STRING_LENGTH-1); description->description[DAUDIO_STRING_LENGTH-1] = 0; return TRUE; } return FALSE; } #define MAX_SAMPLE_RATES 20 void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) { int fd = -1; AudioDeviceDescription desc; am_sample_rates_t *sr; /* hardcoded bits and channels */ int bits[] = {8, 16}; int bitsCount = 2; int channels[] = {1, 2}; int channelsCount = 2; /* for querying sample rates */ int err; int ch, b, s; TRACE2("DAUDIO_GetFormats, mixer %d, isSource=%d\n", mixerIndex, isSource); if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) { fd = open(desc.pathctl, O_RDONLY); } if (fd < 0) { ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex); return; } /* get sample rates */ sr = (am_sample_rates_t*) malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(MAX_SAMPLE_RATES)); if (sr == NULL) { ERROR1("DAUDIO_GetFormats: out of memory for mixer %d\n", (int) mixerIndex); close(fd); return; } sr->num_samp_rates = MAX_SAMPLE_RATES; sr->type = isSource?AUDIO_PLAY:AUDIO_RECORD; sr->samp_rates[0] = -2; err = ioctl(fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr); if (err < 0) { ERROR1(" DAUDIO_GetFormats: AUDIO_MIXER_GET_SAMPLE_RATES failed for mixer %d!\n", (int)mixerIndex); ERROR2(" -> num_sample_rates=%d sample_rates[0] = %d\n", (int) sr->num_samp_rates, (int) sr->samp_rates[0]); /* Some Solaris 8 drivers fail for get sample rates! * Do as if we support all sample rates */ sr->flags = MIXER_SR_LIMITS; } if ((sr->flags & MIXER_SR_LIMITS) || (sr->num_samp_rates > MAX_SAMPLE_RATES)) { #ifdef USE_TRACE if ((sr->flags & MIXER_SR_LIMITS)) { TRACE1(" DAUDIO_GetFormats: floating sample rate allowed by mixer %d\n", (int)mixerIndex); } if (sr->num_samp_rates > MAX_SAMPLE_RATES) { TRACE2(" DAUDIO_GetFormats: more than %d formats. Use -1 for sample rates mixer %d\n", MAX_SAMPLE_RATES, (int)mixerIndex); } #endif /* * Fake it to have only one sample rate: -1 */ sr->num_samp_rates = 1; sr->samp_rates[0] = -1; } close(fd); for (ch = 0; ch < channelsCount; ch++) { for (b = 0; b < bitsCount; b++) { for (s = 0; s < sr->num_samp_rates; s++) { DAUDIO_AddAudioFormat(creator, bits[b], /* significant bits */ 0, /* frameSize: let it be calculated */ channels[ch], (float) ((int) sr->samp_rates[s]), DAUDIO_PCM, /* encoding - let's only do PCM */ (bits[b] > 8)?TRUE:TRUE, /* isSigned */ #ifdef _LITTLE_ENDIAN FALSE /* little endian */ #else (bits[b] > 8)?TRUE:FALSE /* big endian */ #endif ); } } } free(sr); } typedef struct { int fd; audio_info_t info; int bufferSizeInBytes; int frameSize; /* storage size in Bytes */ /* how many bytes were written or read */ INT32 transferedBytes; /* if transferedBytes exceed 32-bit boundary, * it will be reset and positionOffset will receive * the offset */ INT64 positionOffset; } SolPcmInfo; void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource, int encoding, float sampleRate, int sampleSizeInBits, int frameSize, int channels, int isSigned, int isBigEndian, int bufferSizeInBytes) { int err = 0; int openMode; AudioDeviceDescription desc; SolPcmInfo* info; TRACE0("> DAUDIO_Open\n"); if (encoding != DAUDIO_PCM) { ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding); return NULL; } info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo)); if (!info) { ERROR0("Out of memory\n"); return NULL; } memset(info, 0, sizeof(SolPcmInfo)); info->frameSize = frameSize; info->fd = -1; if (isSource) { openMode = O_WRONLY; } else { openMode = O_RDONLY; } #ifndef __linux__ /* blackdown does not use NONBLOCK */ openMode |= O_NONBLOCK; #endif if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) { info->fd = open(desc.path, openMode); } if (info->fd < 0) { ERROR1("Couldn't open audio device for mixer %d!\n", mixerIndex); free(info); return NULL; } /* set to multiple open */ if (ioctl(info->fd, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) { TRACE1("DAUDIO_Open: %s set to multiple open\n", desc.path); } else { ERROR1("DAUDIO_Open: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", desc.path); } AUDIO_INITINFO(&(info->info)); /* need AUDIO_GETINFO ioctl to get this to work on solaris x86 */ err = ioctl(info->fd, AUDIO_GETINFO, &(info->info)); /* not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO. */ AUDIO_INITINFO(&(info->info)); if (isSource) { info->info.play.sample_rate = sampleRate; info->info.play.precision = sampleSizeInBits; info->info.play.channels = channels; info->info.play.encoding = AUDIO_ENCODING_LINEAR; info->info.play.buffer_size = bufferSizeInBytes; info->info.play.pause = 1; } else { info->info.record.sample_rate = sampleRate; info->info.record.precision = sampleSizeInBits; info->info.record.channels = channels; info->info.record.encoding = AUDIO_ENCODING_LINEAR; info->info.record.buffer_size = bufferSizeInBytes; info->info.record.pause = 1; } err = ioctl(info->fd, AUDIO_SETINFO, &(info->info)); if (err < 0) { ERROR0("DAUDIO_Open: could not set info!\n"); DAUDIO_Close((void*) info, isSource); return NULL; } DAUDIO_Flush((void*) info, isSource); err = ioctl(info->fd, AUDIO_GETINFO, &(info->info)); if (err >= 0) { if (isSource) { info->bufferSizeInBytes = info->info.play.buffer_size; } else { info->bufferSizeInBytes = info->info.record.buffer_size; } TRACE2("DAUDIO: buffersize in bytes: requested=%d, got %d\n", (int) bufferSizeInBytes, (int) info->bufferSizeInBytes); } else { ERROR0("DAUDIO_Open: cannot get info!\n"); DAUDIO_Close((void*) info, isSource); return NULL; } TRACE0("< DAUDIO_Open: Opened device successfully.\n"); return (void*) info; } int DAUDIO_Start(void* id, int isSource) { SolPcmInfo* info = (SolPcmInfo*) id; int err, modified; audio_info_t audioInfo; TRACE0("> DAUDIO_Start\n"); AUDIO_INITINFO(&audioInfo); err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo); if (err >= 0) { // unpause modified = FALSE; if (isSource && audioInfo.play.pause) { audioInfo.play.pause = 0; modified = TRUE; } if (!isSource && audioInfo.record.pause) { audioInfo.record.pause = 0; modified = TRUE; } if (modified) { err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo); } } TRACE1("< DAUDIO_Start %s\n", (err>=0)?"success":"error"); return (err >= 0)?TRUE:FALSE; } int DAUDIO_Stop(void* id, int isSource) { SolPcmInfo* info = (SolPcmInfo*) id; int err, modified; audio_info_t audioInfo; TRACE0("> DAUDIO_Stop\n"); AUDIO_INITINFO(&audioInfo); err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo); if (err >= 0) { // pause modified = FALSE; if (isSource && !audioInfo.play.pause) { audioInfo.play.pause = 1; modified = TRUE; } if (!isSource && !audioInfo.record.pause) { audioInfo.record.pause = 1; modified = TRUE; } if (modified) { err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo); } } TRACE1("< DAUDIO_Stop %s\n", (err>=0)?"success":"error"); return (err >= 0)?TRUE:FALSE; } void DAUDIO_Close(void* id, int isSource) { SolPcmInfo* info = (SolPcmInfo*) id; TRACE0("DAUDIO_Close\n"); if (info != NULL) { if (info->fd >= 0) { DAUDIO_Flush(id, isSource); close(info->fd); } free(info); } } #ifndef USE_TRACE /* close to 2^31 */ #define POSITION_MAX 2000000000 #else /* for testing */ #define POSITION_MAX 1000000 #endif void resetErrorFlagAndAdjustPosition(SolPcmInfo* info, int isSource, int count) { audio_info_t audioInfo; audio_prinfo_t* prinfo; int err; int offset = -1; int underrun = FALSE; int devBytes = 0; if (count > 0) { info->transferedBytes += count; if (isSource) { prinfo = &(audioInfo.play); } else { prinfo = &(audioInfo.record); } AUDIO_INITINFO(&audioInfo); err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo); if (err >= 0) { underrun = prinfo->error; devBytes = prinfo->samples * info->frameSize; } AUDIO_INITINFO(&audioInfo); if (underrun) { /* if an underrun occurred, reset */ ERROR1("DAUDIO_Write/Read: Underrun/overflow: adjusting positionOffset by %d:\n", (devBytes - info->transferedBytes)); ERROR1(" devBytes from %d to 0, ", devBytes); ERROR2(" positionOffset from %d to %d ", (int) info->positionOffset, (int) (info->positionOffset + info->transferedBytes)); ERROR1(" transferedBytes from %d to 0\n", (int) info->transferedBytes); prinfo->samples = 0; info->positionOffset += info->transferedBytes; info->transferedBytes = 0; } else if (info->transferedBytes > POSITION_MAX) { /* we will reset transferedBytes and * the samples field in prinfo */ offset = devBytes; prinfo->samples = 0; } /* reset error flag */ prinfo->error = 0; err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo); if (err >= 0) { if (offset > 0) { /* upon exit of AUDIO_SETINFO, the samples parameter * was set to the previous value. This is our * offset. */ TRACE1("Adjust samplePos: offset=%d, ", (int) offset); TRACE2("transferedBytes=%d -> %d, ", (int) info->transferedBytes, (int) (info->transferedBytes - offset)); TRACE2("positionOffset=%d -> %d\n", (int) (info->positionOffset), (int) (((int) info->positionOffset) + offset)); info->transferedBytes -= offset; info->positionOffset += offset; } } else { ERROR0("DAUDIO: resetErrorFlagAndAdjustPosition ioctl failed!\n"); } } } // returns -1 on error int DAUDIO_Write(void* id, char* data, int byteSize) { SolPcmInfo* info = (SolPcmInfo*) id; int ret = -1; TRACE1("> DAUDIO_Write %d bytes\n", byteSize); if (info!=NULL) { ret = write(info->fd, data, byteSize); resetErrorFlagAndAdjustPosition(info, TRUE, ret); /* sets ret to -1 if buffer full, no error! */ if (ret < 0) { ret = 0; } } TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret); return ret; } // returns -1 on error int DAUDIO_Read(void* id, char* data, int byteSize) { SolPcmInfo* info = (SolPcmInfo*) id; int ret = -1; TRACE1("> DAUDIO_Read %d bytes\n", byteSize); if (info != NULL) { ret = read(info->fd, data, byteSize); resetErrorFlagAndAdjustPosition(info, TRUE, ret); /* sets ret to -1 if buffer full, no error! */ if (ret < 0) { ret = 0; } } TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret); return ret; } int DAUDIO_GetBufferSize(void* id, int isSource) { SolPcmInfo* info = (SolPcmInfo*) id; if (info) { return info->bufferSizeInBytes; } return 0; } int DAUDIO_StillDraining(void* id, int isSource) { SolPcmInfo* info = (SolPcmInfo*) id; audio_info_t audioInfo; audio_prinfo_t* prinfo; int ret = FALSE; if (info!=NULL) { if (isSource) { prinfo = &(audioInfo.play); } else { prinfo = &(audioInfo.record); } /* check error flag */ AUDIO_INITINFO(&audioInfo); ioctl(info->fd, AUDIO_GETINFO, &audioInfo); ret = (prinfo->error != 0)?FALSE:TRUE; } return ret; } int getDevicePosition(SolPcmInfo* info, int isSource) { audio_info_t audioInfo; audio_prinfo_t* prinfo; int err; if (isSource) { prinfo = &(audioInfo.play); } else { prinfo = &(audioInfo.record); } AUDIO_INITINFO(&audioInfo); err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo); if (err >= 0) { /*TRACE2("---> device paused: %d eof=%d\n", prinfo->pause, prinfo->eof); */ return (int) (prinfo->samples * info->frameSize); } ERROR0("DAUDIO: getDevicePosition: ioctl failed!\n"); return -1; } int DAUDIO_Flush(void* id, int isSource) { SolPcmInfo* info = (SolPcmInfo*) id; int err = -1; int pos; TRACE0("DAUDIO_Flush\n"); if (info) { if (isSource) { err = ioctl(info->fd, I_FLUSH, FLUSHW); } else { err = ioctl(info->fd, I_FLUSH, FLUSHR); } if (err >= 0) { /* resets the transferedBytes parameter to * the current samples count of the device */ pos = getDevicePosition(info, isSource); if (pos >= 0) { info->transferedBytes = pos; } } } if (err < 0) { ERROR0("ERROR in DAUDIO_Flush\n"); } return (err < 0)?FALSE:TRUE; } int DAUDIO_GetAvailable(void* id, int isSource) { SolPcmInfo* info = (SolPcmInfo*) id; int ret = 0; int pos; if (info) { /* unfortunately, the STREAMS architecture * seems to not have a method for querying * the available bytes to read/write! * estimate it... */ pos = getDevicePosition(info, isSource); if (pos >= 0) { if (isSource) { /* we usually have written more bytes * to the queue than the device position should be */ ret = (info->bufferSizeInBytes) - (info->transferedBytes - pos); } else { /* for record, the device stream should * be usually ahead of our read actions */ ret = pos - info->transferedBytes; } if (ret > info->bufferSizeInBytes) { ERROR2("DAUDIO_GetAvailable: available=%d, too big at bufferSize=%d!\n", (int) ret, (int) info->bufferSizeInBytes); ERROR2(" devicePos=%d, transferedBytes=%d\n", (int) pos, (int) info->transferedBytes); ret = info->bufferSizeInBytes; } else if (ret < 0) { ERROR1("DAUDIO_GetAvailable: available=%d, in theory not possible!\n", (int) ret); ERROR2(" devicePos=%d, transferedBytes=%d\n", (int) pos, (int) info->transferedBytes); ret = 0; } } } TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret); return ret; } INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) { SolPcmInfo* info = (SolPcmInfo*) id; int ret; int pos; INT64 result = javaBytePos; if (info) { pos = getDevicePosition(info, isSource); if (pos >= 0) { result = info->positionOffset + pos; } } //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result); return result; } void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) { SolPcmInfo* info = (SolPcmInfo*) id; int ret; int pos; if (info) { pos = getDevicePosition(info, isSource); if (pos >= 0) { info->positionOffset = javaBytePos - pos; } } } int DAUDIO_RequiresServicing(void* id, int isSource) { // never need servicing on Solaris return FALSE; } void DAUDIO_Service(void* id, int isSource) { // never need servicing on Solaris } #endif // USE_DAUDIO Other Java examples (source code examples)Here is a short list of links related to this Java PLATFORM_API_SolarisOS_PCM.c source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.