src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_PCM.c
branchhttp-client-branch
changeset 56346 514c68575523
parent 56345 eb72d194235c
parent 49316 73da889306b7
child 56347 bac3a660249a
equal deleted inserted replaced
56345:eb72d194235c 56346:514c68575523
     1 /*
       
     2  * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #define USE_ERROR
       
    27 #define USE_TRACE
       
    28 
       
    29 #include "PLATFORM_API_SolarisOS_Utils.h"
       
    30 #include "DirectAudio.h"
       
    31 
       
    32 #if USE_DAUDIO == TRUE
       
    33 
       
    34 
       
    35 // The default buffer time
       
    36 #define DEFAULT_PERIOD_TIME_MILLIS 50
       
    37 
       
    38 ///// implemented functions of DirectAudio.h
       
    39 
       
    40 INT32 DAUDIO_GetDirectAudioDeviceCount() {
       
    41     return (INT32) getAudioDeviceCount();
       
    42 }
       
    43 
       
    44 
       
    45 INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex,
       
    46                                              DirectAudioDeviceDescription* description) {
       
    47     AudioDeviceDescription desc;
       
    48 
       
    49     if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
       
    50         description->maxSimulLines = desc.maxSimulLines;
       
    51         strncpy(description->name, desc.name, DAUDIO_STRING_LENGTH-1);
       
    52         description->name[DAUDIO_STRING_LENGTH-1] = 0;
       
    53         strncpy(description->vendor, desc.vendor, DAUDIO_STRING_LENGTH-1);
       
    54         description->vendor[DAUDIO_STRING_LENGTH-1] = 0;
       
    55         strncpy(description->version, desc.version, DAUDIO_STRING_LENGTH-1);
       
    56         description->version[DAUDIO_STRING_LENGTH-1] = 0;
       
    57         /*strncpy(description->description, desc.description, DAUDIO_STRING_LENGTH-1);*/
       
    58         strncpy(description->description, "Solaris Mixer", DAUDIO_STRING_LENGTH-1);
       
    59         description->description[DAUDIO_STRING_LENGTH-1] = 0;
       
    60         return TRUE;
       
    61     }
       
    62     return FALSE;
       
    63 
       
    64 }
       
    65 
       
    66 #define MAX_SAMPLE_RATES   20
       
    67 
       
    68 void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
       
    69     int fd = -1;
       
    70     AudioDeviceDescription desc;
       
    71     am_sample_rates_t      *sr;
       
    72     /* hardcoded bits and channels */
       
    73     int bits[] = {8, 16};
       
    74     int bitsCount = 2;
       
    75     int channels[] = {1, 2};
       
    76     int channelsCount = 2;
       
    77     /* for querying sample rates */
       
    78     int err;
       
    79     int ch, b, s;
       
    80 
       
    81     TRACE2("DAUDIO_GetFormats, mixer %d, isSource=%d\n", mixerIndex, isSource);
       
    82     if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
       
    83         fd = open(desc.pathctl, O_RDONLY);
       
    84     }
       
    85     if (fd < 0) {
       
    86         ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
       
    87         return;
       
    88     }
       
    89 
       
    90     /* get sample rates */
       
    91     sr = (am_sample_rates_t*) malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(MAX_SAMPLE_RATES));
       
    92     if (sr == NULL) {
       
    93         ERROR1("DAUDIO_GetFormats: out of memory for mixer %d\n", (int) mixerIndex);
       
    94         close(fd);
       
    95         return;
       
    96     }
       
    97 
       
    98     sr->num_samp_rates = MAX_SAMPLE_RATES;
       
    99     sr->type = isSource?AUDIO_PLAY:AUDIO_RECORD;
       
   100     sr->samp_rates[0] = -2;
       
   101     err = ioctl(fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr);
       
   102     if (err < 0) {
       
   103         ERROR1("  DAUDIO_GetFormats: AUDIO_MIXER_GET_SAMPLE_RATES failed for mixer %d!\n",
       
   104                (int)mixerIndex);
       
   105         ERROR2(" -> num_sample_rates=%d sample_rates[0] = %d\n",
       
   106                (int) sr->num_samp_rates,
       
   107                (int) sr->samp_rates[0]);
       
   108         /* Some Solaris 8 drivers fail for get sample rates!
       
   109          * Do as if we support all sample rates
       
   110          */
       
   111         sr->flags = MIXER_SR_LIMITS;
       
   112     }
       
   113     if ((sr->flags & MIXER_SR_LIMITS)
       
   114         || (sr->num_samp_rates > MAX_SAMPLE_RATES)) {
       
   115 #ifdef USE_TRACE
       
   116         if ((sr->flags & MIXER_SR_LIMITS)) {
       
   117             TRACE1("  DAUDIO_GetFormats: floating sample rate allowed by mixer %d\n",
       
   118                    (int)mixerIndex);
       
   119         }
       
   120         if (sr->num_samp_rates > MAX_SAMPLE_RATES) {
       
   121             TRACE2("  DAUDIO_GetFormats: more than %d formats. Use -1 for sample rates mixer %d\n",
       
   122                    MAX_SAMPLE_RATES, (int)mixerIndex);
       
   123         }
       
   124 #endif
       
   125         /*
       
   126          * Fake it to have only one sample rate: -1
       
   127          */
       
   128         sr->num_samp_rates = 1;
       
   129         sr->samp_rates[0] = -1;
       
   130     }
       
   131     close(fd);
       
   132 
       
   133     for (ch = 0; ch < channelsCount; ch++) {
       
   134         for (b = 0; b < bitsCount; b++) {
       
   135             for (s = 0; s < sr->num_samp_rates; s++) {
       
   136                 DAUDIO_AddAudioFormat(creator,
       
   137                                       bits[b], /* significant bits */
       
   138                                       0, /* frameSize: let it be calculated */
       
   139                                       channels[ch],
       
   140                                       (float) ((int) sr->samp_rates[s]),
       
   141                                       DAUDIO_PCM, /* encoding - let's only do PCM */
       
   142                                       (bits[b] > 8)?TRUE:TRUE, /* isSigned */
       
   143 #ifdef _LITTLE_ENDIAN
       
   144                                       FALSE /* little endian */
       
   145 #else
       
   146                                       (bits[b] > 8)?TRUE:FALSE  /* big endian */
       
   147 #endif
       
   148                                       );
       
   149             }
       
   150         }
       
   151     }
       
   152     free(sr);
       
   153 }
       
   154 
       
   155 
       
   156 typedef struct {
       
   157     int fd;
       
   158     audio_info_t info;
       
   159     int bufferSizeInBytes;
       
   160     int frameSize; /* storage size in Bytes */
       
   161     /* how many bytes were written or read */
       
   162     INT32 transferedBytes;
       
   163     /* if transferedBytes exceed 32-bit boundary,
       
   164      * it will be reset and positionOffset will receive
       
   165      * the offset
       
   166      */
       
   167     INT64 positionOffset;
       
   168 } SolPcmInfo;
       
   169 
       
   170 
       
   171 void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
       
   172                   int encoding, float sampleRate, int sampleSizeInBits,
       
   173                   int frameSize, int channels,
       
   174                   int isSigned, int isBigEndian, int bufferSizeInBytes) {
       
   175     int err = 0;
       
   176     int openMode;
       
   177     AudioDeviceDescription desc;
       
   178     SolPcmInfo* info;
       
   179 
       
   180     TRACE0("> DAUDIO_Open\n");
       
   181     if (encoding != DAUDIO_PCM) {
       
   182         ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding);
       
   183         return NULL;
       
   184     }
       
   185     if (channels <= 0) {
       
   186         ERROR1(" DAUDIO_Open: Invalid number of channels=%d!\n", channels);
       
   187         return NULL;
       
   188     }
       
   189 
       
   190     info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo));
       
   191     if (!info) {
       
   192         ERROR0("Out of memory\n");
       
   193         return NULL;
       
   194     }
       
   195     memset(info, 0, sizeof(SolPcmInfo));
       
   196     info->frameSize = frameSize;
       
   197     info->fd = -1;
       
   198 
       
   199     if (isSource) {
       
   200         openMode = O_WRONLY;
       
   201     } else {
       
   202         openMode = O_RDONLY;
       
   203     }
       
   204 
       
   205 #ifndef __linux__
       
   206     /* blackdown does not use NONBLOCK */
       
   207     openMode |= O_NONBLOCK;
       
   208 #endif
       
   209 
       
   210     if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
       
   211         info->fd = open(desc.path, openMode);
       
   212     }
       
   213     if (info->fd < 0) {
       
   214         ERROR1("Couldn't open audio device for mixer %d!\n", mixerIndex);
       
   215         free(info);
       
   216         return NULL;
       
   217     }
       
   218     /* set to multiple open */
       
   219     if (ioctl(info->fd, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) {
       
   220         TRACE1("DAUDIO_Open: %s set to multiple open\n", desc.path);
       
   221     } else {
       
   222         ERROR1("DAUDIO_Open: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", desc.path);
       
   223     }
       
   224 
       
   225     AUDIO_INITINFO(&(info->info));
       
   226     /* need AUDIO_GETINFO ioctl to get this to work on solaris x86  */
       
   227     err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
       
   228 
       
   229     /* not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO. */
       
   230     AUDIO_INITINFO(&(info->info));
       
   231 
       
   232     if (isSource) {
       
   233         info->info.play.sample_rate = sampleRate;
       
   234         info->info.play.precision = sampleSizeInBits;
       
   235         info->info.play.channels = channels;
       
   236         info->info.play.encoding = AUDIO_ENCODING_LINEAR;
       
   237         info->info.play.buffer_size = bufferSizeInBytes;
       
   238         info->info.play.pause = 1;
       
   239     } else {
       
   240         info->info.record.sample_rate = sampleRate;
       
   241         info->info.record.precision = sampleSizeInBits;
       
   242         info->info.record.channels = channels;
       
   243         info->info.record.encoding = AUDIO_ENCODING_LINEAR;
       
   244         info->info.record.buffer_size = bufferSizeInBytes;
       
   245         info->info.record.pause = 1;
       
   246     }
       
   247     err = ioctl(info->fd, AUDIO_SETINFO,  &(info->info));
       
   248     if (err < 0) {
       
   249         ERROR0("DAUDIO_Open: could not set info!\n");
       
   250         DAUDIO_Close((void*) info, isSource);
       
   251         return NULL;
       
   252     }
       
   253     DAUDIO_Flush((void*) info, isSource);
       
   254 
       
   255     err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
       
   256     if (err >= 0) {
       
   257         if (isSource) {
       
   258             info->bufferSizeInBytes = info->info.play.buffer_size;
       
   259         } else {
       
   260             info->bufferSizeInBytes = info->info.record.buffer_size;
       
   261         }
       
   262         TRACE2("DAUDIO: buffersize in bytes: requested=%d, got %d\n",
       
   263                (int) bufferSizeInBytes,
       
   264                (int) info->bufferSizeInBytes);
       
   265     } else {
       
   266         ERROR0("DAUDIO_Open: cannot get info!\n");
       
   267         DAUDIO_Close((void*) info, isSource);
       
   268         return NULL;
       
   269     }
       
   270     TRACE0("< DAUDIO_Open: Opened device successfully.\n");
       
   271     return (void*) info;
       
   272 }
       
   273 
       
   274 
       
   275 int DAUDIO_Start(void* id, int isSource) {
       
   276     SolPcmInfo* info = (SolPcmInfo*) id;
       
   277     int err, modified;
       
   278     audio_info_t audioInfo;
       
   279 
       
   280     TRACE0("> DAUDIO_Start\n");
       
   281 
       
   282     AUDIO_INITINFO(&audioInfo);
       
   283     err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
       
   284     if (err >= 0) {
       
   285         // unpause
       
   286         modified = FALSE;
       
   287         if (isSource && audioInfo.play.pause) {
       
   288             audioInfo.play.pause = 0;
       
   289             modified = TRUE;
       
   290         }
       
   291         if (!isSource && audioInfo.record.pause) {
       
   292             audioInfo.record.pause = 0;
       
   293             modified = TRUE;
       
   294         }
       
   295         if (modified) {
       
   296             err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
       
   297         }
       
   298     }
       
   299 
       
   300     TRACE1("< DAUDIO_Start %s\n", (err>=0)?"success":"error");
       
   301     return (err >= 0)?TRUE:FALSE;
       
   302 }
       
   303 
       
   304 int DAUDIO_Stop(void* id, int isSource) {
       
   305     SolPcmInfo* info = (SolPcmInfo*) id;
       
   306     int err, modified;
       
   307     audio_info_t audioInfo;
       
   308 
       
   309     TRACE0("> DAUDIO_Stop\n");
       
   310 
       
   311     AUDIO_INITINFO(&audioInfo);
       
   312     err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
       
   313     if (err >= 0) {
       
   314         // pause
       
   315         modified = FALSE;
       
   316         if (isSource && !audioInfo.play.pause) {
       
   317             audioInfo.play.pause = 1;
       
   318             modified = TRUE;
       
   319         }
       
   320         if (!isSource && !audioInfo.record.pause) {
       
   321             audioInfo.record.pause = 1;
       
   322             modified = TRUE;
       
   323         }
       
   324         if (modified) {
       
   325             err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
       
   326         }
       
   327     }
       
   328 
       
   329     TRACE1("< DAUDIO_Stop %s\n", (err>=0)?"success":"error");
       
   330     return (err >= 0)?TRUE:FALSE;
       
   331 }
       
   332 
       
   333 void DAUDIO_Close(void* id, int isSource) {
       
   334     SolPcmInfo* info = (SolPcmInfo*) id;
       
   335 
       
   336     TRACE0("DAUDIO_Close\n");
       
   337     if (info != NULL) {
       
   338         if (info->fd >= 0) {
       
   339             DAUDIO_Flush(id, isSource);
       
   340             close(info->fd);
       
   341         }
       
   342         free(info);
       
   343     }
       
   344 }
       
   345 
       
   346 #ifndef USE_TRACE
       
   347 /* close to 2^31 */
       
   348 #define POSITION_MAX 2000000000
       
   349 #else
       
   350 /* for testing */
       
   351 #define POSITION_MAX 1000000
       
   352 #endif
       
   353 
       
   354 void resetErrorFlagAndAdjustPosition(SolPcmInfo* info, int isSource, int count) {
       
   355     audio_info_t audioInfo;
       
   356     audio_prinfo_t* prinfo;
       
   357     int err;
       
   358     int offset = -1;
       
   359     int underrun = FALSE;
       
   360     int devBytes = 0;
       
   361 
       
   362     if (count > 0) {
       
   363         info->transferedBytes += count;
       
   364 
       
   365         if (isSource) {
       
   366             prinfo = &(audioInfo.play);
       
   367         } else {
       
   368             prinfo = &(audioInfo.record);
       
   369         }
       
   370         AUDIO_INITINFO(&audioInfo);
       
   371         err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
       
   372         if (err >= 0) {
       
   373             underrun = prinfo->error;
       
   374             devBytes = prinfo->samples * info->frameSize;
       
   375         }
       
   376         AUDIO_INITINFO(&audioInfo);
       
   377         if (underrun) {
       
   378             /* if an underrun occurred, reset */
       
   379             ERROR1("DAUDIO_Write/Read: Underrun/overflow: adjusting positionOffset by %d:\n",
       
   380                    (devBytes - info->transferedBytes));
       
   381             ERROR1("    devBytes from %d to 0, ", devBytes);
       
   382             ERROR2(" positionOffset from %d to %d ",
       
   383                    (int) info->positionOffset,
       
   384                    (int) (info->positionOffset + info->transferedBytes));
       
   385             ERROR1(" transferedBytes from %d to 0\n",
       
   386                    (int) info->transferedBytes);
       
   387             prinfo->samples = 0;
       
   388             info->positionOffset += info->transferedBytes;
       
   389             info->transferedBytes = 0;
       
   390         }
       
   391         else if (info->transferedBytes > POSITION_MAX) {
       
   392             /* we will reset transferedBytes and
       
   393              * the samples field in prinfo
       
   394              */
       
   395             offset = devBytes;
       
   396             prinfo->samples = 0;
       
   397         }
       
   398         /* reset error flag */
       
   399         prinfo->error = 0;
       
   400 
       
   401         err = ioctl(info->fd, AUDIO_SETINFO, &audioInfo);
       
   402         if (err >= 0) {
       
   403             if (offset > 0) {
       
   404                 /* upon exit of AUDIO_SETINFO, the samples parameter
       
   405                  * was set to the previous value. This is our
       
   406                  * offset.
       
   407                  */
       
   408                 TRACE1("Adjust samplePos: offset=%d, ", (int) offset);
       
   409                 TRACE2("transferedBytes=%d -> %d, ",
       
   410                        (int) info->transferedBytes,
       
   411                        (int) (info->transferedBytes - offset));
       
   412                 TRACE2("positionOffset=%d -> %d\n",
       
   413                        (int) (info->positionOffset),
       
   414                        (int) (((int) info->positionOffset) + offset));
       
   415                 info->transferedBytes -= offset;
       
   416                 info->positionOffset += offset;
       
   417             }
       
   418         } else {
       
   419             ERROR0("DAUDIO: resetErrorFlagAndAdjustPosition ioctl failed!\n");
       
   420         }
       
   421     }
       
   422 }
       
   423 
       
   424 // returns -1 on error
       
   425 int DAUDIO_Write(void* id, char* data, int byteSize) {
       
   426     SolPcmInfo* info = (SolPcmInfo*) id;
       
   427     int ret = -1;
       
   428 
       
   429     TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
       
   430     if (info!=NULL) {
       
   431         ret = write(info->fd, data, byteSize);
       
   432         resetErrorFlagAndAdjustPosition(info, TRUE, ret);
       
   433         /* sets ret to -1 if buffer full, no error! */
       
   434         if (ret < 0) {
       
   435             ret = 0;
       
   436         }
       
   437     }
       
   438     TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
       
   439     return ret;
       
   440 }
       
   441 
       
   442 // returns -1 on error
       
   443 int DAUDIO_Read(void* id, char* data, int byteSize) {
       
   444     SolPcmInfo* info = (SolPcmInfo*) id;
       
   445     int ret = -1;
       
   446 
       
   447     TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
       
   448     if (info != NULL) {
       
   449         ret = read(info->fd, data, byteSize);
       
   450         resetErrorFlagAndAdjustPosition(info, TRUE, ret);
       
   451         /* sets ret to -1 if buffer full, no error! */
       
   452         if (ret < 0) {
       
   453             ret = 0;
       
   454         }
       
   455     }
       
   456     TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
       
   457     return ret;
       
   458 }
       
   459 
       
   460 
       
   461 int DAUDIO_GetBufferSize(void* id, int isSource) {
       
   462     SolPcmInfo* info = (SolPcmInfo*) id;
       
   463     if (info) {
       
   464         return info->bufferSizeInBytes;
       
   465     }
       
   466     return 0;
       
   467 }
       
   468 
       
   469 int DAUDIO_StillDraining(void* id, int isSource) {
       
   470     SolPcmInfo* info = (SolPcmInfo*) id;
       
   471     audio_info_t audioInfo;
       
   472     audio_prinfo_t* prinfo;
       
   473     int ret = FALSE;
       
   474 
       
   475     if (info!=NULL) {
       
   476         if (isSource) {
       
   477             prinfo = &(audioInfo.play);
       
   478         } else {
       
   479             prinfo = &(audioInfo.record);
       
   480         }
       
   481         /* check error flag */
       
   482         AUDIO_INITINFO(&audioInfo);
       
   483         ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
       
   484         ret = (prinfo->error != 0)?FALSE:TRUE;
       
   485     }
       
   486     return ret;
       
   487 }
       
   488 
       
   489 
       
   490 int getDevicePosition(SolPcmInfo* info, int isSource) {
       
   491     audio_info_t audioInfo;
       
   492     audio_prinfo_t* prinfo;
       
   493     int err;
       
   494 
       
   495     if (isSource) {
       
   496         prinfo = &(audioInfo.play);
       
   497     } else {
       
   498         prinfo = &(audioInfo.record);
       
   499     }
       
   500     AUDIO_INITINFO(&audioInfo);
       
   501     err = ioctl(info->fd, AUDIO_GETINFO, &audioInfo);
       
   502     if (err >= 0) {
       
   503         /*TRACE2("---> device paused: %d  eof=%d\n",
       
   504                prinfo->pause, prinfo->eof);
       
   505         */
       
   506         return (int) (prinfo->samples * info->frameSize);
       
   507     }
       
   508     ERROR0("DAUDIO: getDevicePosition: ioctl failed!\n");
       
   509     return -1;
       
   510 }
       
   511 
       
   512 int DAUDIO_Flush(void* id, int isSource) {
       
   513     SolPcmInfo* info = (SolPcmInfo*) id;
       
   514     int err = -1;
       
   515     int pos;
       
   516 
       
   517     TRACE0("DAUDIO_Flush\n");
       
   518     if (info) {
       
   519         if (isSource) {
       
   520             err = ioctl(info->fd, I_FLUSH, FLUSHW);
       
   521         } else {
       
   522             err = ioctl(info->fd, I_FLUSH, FLUSHR);
       
   523         }
       
   524         if (err >= 0) {
       
   525             /* resets the transferedBytes parameter to
       
   526              * the current samples count of the device
       
   527              */
       
   528             pos = getDevicePosition(info, isSource);
       
   529             if (pos >= 0) {
       
   530                 info->transferedBytes = pos;
       
   531             }
       
   532         }
       
   533     }
       
   534     if (err < 0) {
       
   535         ERROR0("ERROR in DAUDIO_Flush\n");
       
   536     }
       
   537     return (err < 0)?FALSE:TRUE;
       
   538 }
       
   539 
       
   540 int DAUDIO_GetAvailable(void* id, int isSource) {
       
   541     SolPcmInfo* info = (SolPcmInfo*) id;
       
   542     int ret = 0;
       
   543     int pos;
       
   544 
       
   545     if (info) {
       
   546         /* unfortunately, the STREAMS architecture
       
   547          * seems to not have a method for querying
       
   548          * the available bytes to read/write!
       
   549          * estimate it...
       
   550          */
       
   551         pos = getDevicePosition(info, isSource);
       
   552         if (pos >= 0) {
       
   553             if (isSource) {
       
   554                 /* we usually have written more bytes
       
   555                  * to the queue than the device position should be
       
   556                  */
       
   557                 ret = (info->bufferSizeInBytes) - (info->transferedBytes - pos);
       
   558             } else {
       
   559                 /* for record, the device stream should
       
   560                  * be usually ahead of our read actions
       
   561                  */
       
   562                 ret = pos - info->transferedBytes;
       
   563             }
       
   564             if (ret > info->bufferSizeInBytes) {
       
   565                 ERROR2("DAUDIO_GetAvailable: available=%d, too big at bufferSize=%d!\n",
       
   566                        (int) ret, (int) info->bufferSizeInBytes);
       
   567                 ERROR2("                     devicePos=%d, transferedBytes=%d\n",
       
   568                        (int) pos, (int) info->transferedBytes);
       
   569                 ret = info->bufferSizeInBytes;
       
   570             }
       
   571             else if (ret < 0) {
       
   572                 ERROR1("DAUDIO_GetAvailable: available=%d, in theory not possible!\n",
       
   573                        (int) ret);
       
   574                 ERROR2("                     devicePos=%d, transferedBytes=%d\n",
       
   575                        (int) pos, (int) info->transferedBytes);
       
   576                 ret = 0;
       
   577             }
       
   578         }
       
   579     }
       
   580 
       
   581     TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
       
   582     return ret;
       
   583 }
       
   584 
       
   585 INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
       
   586     SolPcmInfo* info = (SolPcmInfo*) id;
       
   587     int ret;
       
   588     int pos;
       
   589     INT64 result = javaBytePos;
       
   590 
       
   591     if (info) {
       
   592         pos = getDevicePosition(info, isSource);
       
   593         if (pos >= 0) {
       
   594             result = info->positionOffset + pos;
       
   595         }
       
   596     }
       
   597 
       
   598     //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
       
   599     return result;
       
   600 }
       
   601 
       
   602 
       
   603 void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
       
   604     SolPcmInfo* info = (SolPcmInfo*) id;
       
   605     int ret;
       
   606     int pos;
       
   607 
       
   608     if (info) {
       
   609         pos = getDevicePosition(info, isSource);
       
   610         if (pos >= 0) {
       
   611             info->positionOffset = javaBytePos - pos;
       
   612         }
       
   613     }
       
   614 }
       
   615 
       
   616 int DAUDIO_RequiresServicing(void* id, int isSource) {
       
   617     // never need servicing on Solaris
       
   618     return FALSE;
       
   619 }
       
   620 
       
   621 void DAUDIO_Service(void* id, int isSource) {
       
   622     // never need servicing on Solaris
       
   623 }
       
   624 
       
   625 
       
   626 #endif // USE_DAUDIO