src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c
author ihse
Fri, 23 Mar 2018 09:51:02 +0100
changeset 49289 148e29df1644
parent 47216 src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c@71c04702a3d5
permissions -rw-r--r--
8071469: Cleanup include and exclude of sound native libraries Reviewed-by: amenkov, erikj
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
23010
6dadb192ad81 8029235: Update copyright year to match last edit in jdk8 jdk repository for 2013
lana
parents: 9487
diff changeset
     2
 * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4387
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4387
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4387
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4387
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 4387
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
#define USE_ERROR
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
#define USE_TRACE
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
#include "PLATFORM_API_LinuxOS_ALSA_PCMUtils.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
#include "DirectAudio.h"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
#if USE_DAUDIO == TRUE
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
// GetPosition method 1: based on how many bytes are passed to the kernel driver
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
//                       + does not need much processor resources
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
//                       - not very exact, "jumps"
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
// GetPosition method 2: ask kernel about actual position of playback.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
//                       - very exact
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
//                       - switch to kernel layer for each call
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
// GetPosition method 3: use snd_pcm_avail() call - not yet in official ALSA
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
// quick tests on a Pentium 200MMX showed max. 1.5% processor usage
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
// for playing back a CD-quality file and printing 20x per second a line
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
// on the console with the current time. So I guess performance is not such a
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
// factor here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
//#define GET_POSITION_METHOD1
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
#define GET_POSITION_METHOD2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
// The default time for a period in microseconds.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
// For very small buffers, only 2 periods are used.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
#define DEFAULT_PERIOD_TIME 20000 /* 20ms */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
///// implemented functions of DirectAudio.h
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
INT32 DAUDIO_GetDirectAudioDeviceCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    return (INT32) getAudioDeviceCount();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription* description) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    ALSA_AudioDeviceDescription adesc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    adesc.index = (int) mixerIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    adesc.strLen = DAUDIO_STRING_LENGTH;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
    adesc.maxSimultaneousLines = (int*) (&(description->maxSimulLines));
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
    adesc.deviceID = &(description->deviceID);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
    adesc.name = description->name;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    adesc.vendor = description->vendor;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
    adesc.description = description->description;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    adesc.version = description->version;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    return getAudioDeviceDescriptionByIndex(&adesc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
#define MAX_BIT_INDEX 6
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
// returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
// 6: for anything above 24-bit
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
// 5: for 4 bytes sample size, 24-bit
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
// 4: for 3 bytes sample size, 24-bit
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
// 3: for 3 bytes sample size, 20-bit
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
// 2: for 2 bytes sample size, 16-bit
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
// 1: for 1 byte sample size, 8-bit
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
// 0: for anything else
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
int getBitIndex(int sampleSizeInBytes, int significantBits) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    if (significantBits > 24) return 6;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
    if (sampleSizeInBytes == 4 && significantBits == 24) return 5;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    if (sampleSizeInBytes == 3) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
        if (significantBits == 24) return 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
        if (significantBits == 20) return 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    if (sampleSizeInBytes == 2 && significantBits == 16) return 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
    if (sampleSizeInBytes == 1 && significantBits == 8) return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
    return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
int getSampleSizeInBytes(int bitIndex, int sampleSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    switch(bitIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
    case 1: return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    case 2: return 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    case 3: /* fall through */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    case 4: return 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
    case 5: return 4;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
    return sampleSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
int getSignificantBits(int bitIndex, int significantBits) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    switch(bitIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    case 1: return 8;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    case 2: return 16;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    case 3: return 20;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
    case 4: /* fall through */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    case 5: return 24;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
    return significantBits;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    snd_pcm_t* handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
    snd_pcm_format_mask_t* formatMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
    snd_pcm_format_t format;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    snd_pcm_hw_params_t* hwParams;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    int handledBits[MAX_BIT_INDEX+1];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    int sampleSizeInBytes, significantBits, isSigned, isBigEndian, enc;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    int origSampleSizeInBytes, origSignificantBits;
7792
612315e0949d 6989702: sound native code compiler warnings
amenkov
parents: 5506
diff changeset
   130
    unsigned int channels, minChannels, maxChannels;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
    int rate, bitIndex;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    for (bitIndex = 0; bitIndex <= MAX_BIT_INDEX; bitIndex++) handledBits[bitIndex] = FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    if (openPCMfromDeviceID(deviceID, &handle, isSource, TRUE /*query hardware*/) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
    ret = snd_pcm_format_mask_malloc(&formatMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
        ERROR1("snd_pcm_format_mask_malloc returned error %d\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
        ret = snd_pcm_hw_params_malloc(&hwParams);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
        if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
            ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
            ret = snd_pcm_hw_params_any(handle, hwParams);
4387
83ff9b5213c4 6832063: OpenJDK fails to open the default ALSA device when PulseAudio is enabled
amenkov
parents: 2
diff changeset
   146
            /* snd_pcm_hw_params_any can return a positive value on success too */
83ff9b5213c4 6832063: OpenJDK fails to open the default ALSA device when PulseAudio is enabled
amenkov
parents: 2
diff changeset
   147
            if (ret < 0) {
83ff9b5213c4 6832063: OpenJDK fails to open the default ALSA device when PulseAudio is enabled
amenkov
parents: 2
diff changeset
   148
                 ERROR1("snd_pcm_hw_params_any returned error %d\n", ret);
83ff9b5213c4 6832063: OpenJDK fails to open the default ALSA device when PulseAudio is enabled
amenkov
parents: 2
diff changeset
   149
            } else {
83ff9b5213c4 6832063: OpenJDK fails to open the default ALSA device when PulseAudio is enabled
amenkov
parents: 2
diff changeset
   150
                /* for the logic following this code, set ret to 0 to indicate success */
83ff9b5213c4 6832063: OpenJDK fails to open the default ALSA device when PulseAudio is enabled
amenkov
parents: 2
diff changeset
   151
                ret = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
        snd_pcm_hw_params_get_format_mask(hwParams, formatMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
        if (ret == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
            ret = snd_pcm_hw_params_get_channels_min(hwParams, &minChannels);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
            if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
                ERROR1("snd_pcm_hw_params_get_channels_min returned error %d\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
        if (ret == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
            ret = snd_pcm_hw_params_get_channels_max(hwParams, &maxChannels);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
            if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
                ERROR1("snd_pcm_hw_params_get_channels_max returned error %d\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
        // since we queried the hw: device, for many soundcards, it will only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        // report the maximum number of channels (which is the only way to talk
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        // to the hw: device). Since we will, however, open the plughw: device
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        // when opening the Source/TargetDataLine, we can safely assume that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
        // also the channels 1..maxChannels are available.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
#ifdef ALSA_PCM_USE_PLUGHW
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
        minChannels = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        if (ret == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
            // plughw: supports any sample rate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
            rate = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
            for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
                if (snd_pcm_format_mask_test(formatMask, format)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                    // format exists
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                    if (getFormatFromAlsaFormat(format, &origSampleSizeInBytes,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                                                &origSignificantBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                                                &isSigned, &isBigEndian, &enc)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
                        // now if we use plughw:, we can use any bit size below the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
                        // natively supported ones. Some ALSA drivers only support the maximum
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
                        // bit size, so we add any sample rates below the reported one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
                        // E.g. this iteration reports support for 16-bit.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
                        // getBitIndex will return 2, so it will add entries for
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
                        // 16-bit (bitIndex=2) and in the next do-while loop iteration,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
                        // it will decrease bitIndex and will therefore add 8-bit support.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
                        bitIndex = getBitIndex(origSampleSizeInBytes, origSignificantBits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
                        do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
                            if (bitIndex == 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
                                || bitIndex == MAX_BIT_INDEX
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
                                || !handledBits[bitIndex]) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
                                handledBits[bitIndex] = TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                                sampleSizeInBytes = getSampleSizeInBytes(bitIndex, origSampleSizeInBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
                                significantBits = getSignificantBits(bitIndex, origSignificantBits);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
                                if (maxChannels - minChannels > MAXIMUM_LISTED_CHANNELS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
                                    // avoid too many channels explicitly listed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
                                    // just add -1, min, and max
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
                                    DAUDIO_AddAudioFormat(creator, significantBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
                                                          -1, -1, rate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
                                                          enc, isSigned, isBigEndian);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
                                    DAUDIO_AddAudioFormat(creator, significantBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
                                                          sampleSizeInBytes * minChannels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
                                                          minChannels, rate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
                                                          enc, isSigned, isBigEndian);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
                                    DAUDIO_AddAudioFormat(creator, significantBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
                                                          sampleSizeInBytes * maxChannels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
                                                          maxChannels, rate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
                                                          enc, isSigned, isBigEndian);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
                                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
                                    for (channels = minChannels; channels <= maxChannels; channels++) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
                                        DAUDIO_AddAudioFormat(creator, significantBits,
7792
612315e0949d 6989702: sound native code compiler warnings
amenkov
parents: 5506
diff changeset
   217
                                                              sampleSizeInBytes * channels,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
                                                              channels, rate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
                                                              enc, isSigned, isBigEndian);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
                                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
                                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
#ifndef ALSA_PCM_USE_PLUGHW
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
                            // without plugin, do not add fake formats
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
                            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
                        } while (--bitIndex > 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
                    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
                        TRACE1("could not get format from alsa for format %d\n", format);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                    //TRACE1("Format %d not supported\n", format);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
            } // for loop
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
            snd_pcm_hw_params_free(hwParams);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
        snd_pcm_format_mask_free(formatMask);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
    snd_pcm_close(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   242
/** Workaround for cr 7033899, 7030629:
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   243
 * dmix plugin doesn't like flush (snd_pcm_drop) when the buffer is empty
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   244
 * (just opened, underruned or already flushed).
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   245
 * Sometimes it causes PCM falls to -EBADFD error,
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   246
 * sometimes causes bufferSize change.
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   247
 * To prevent unnecessary flushes AlsaPcmInfo::isRunning & isFlushed are used.
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   248
 */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
/* ******* ALSA PCM INFO ******************** */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
typedef struct tag_AlsaPcmInfo {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
    snd_pcm_t* handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
    snd_pcm_hw_params_t* hwParams;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
    snd_pcm_sw_params_t* swParams;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
    int bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
    int frameSize; // storage size in Bytes
7792
612315e0949d 6989702: sound native code compiler warnings
amenkov
parents: 5506
diff changeset
   256
    unsigned int periods;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
    snd_pcm_uframes_t periodSize;
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   258
    short int isRunning;    // see comment above
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   259
    short int isFlushed;    // see comment above
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
#ifdef GET_POSITION_METHOD2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
    // to be used exclusively by getBytePosition!
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
    snd_pcm_status_t* positionStatus;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
} AlsaPcmInfo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
int setStartThresholdNoCommit(AlsaPcmInfo* info, int useThreshold) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
    int threshold;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
    if (useThreshold) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        // start device whenever anything is written to the buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        threshold = 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
        // never start the device automatically
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
        threshold = 2000000000; /* near UINT_MAX */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
    ret = snd_pcm_sw_params_set_start_threshold(info->handle, info->swParams, threshold);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        ERROR1("Unable to set start threshold mode: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
int setStartThreshold(AlsaPcmInfo* info, int useThreshold) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
    int ret = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
    if (!setStartThresholdNoCommit(info, useThreshold)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        ret = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    if (ret == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
        // commit it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        ret = snd_pcm_sw_params(info->handle, info->swParams);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
        if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
            ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
    return (ret == 0)?TRUE:FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
// returns TRUE if successful
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
int setHWParams(AlsaPcmInfo* info,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
                float sampleRate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
                int channels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
                int bufferSizeInFrames,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
                snd_pcm_format_t format) {
7792
612315e0949d 6989702: sound native code compiler warnings
amenkov
parents: 5506
diff changeset
   309
    unsigned int rrate, periodTime, periods;
612315e0949d 6989702: sound native code compiler warnings
amenkov
parents: 5506
diff changeset
   310
    int ret, dir;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
    snd_pcm_uframes_t alsaBufferSizeInFrames = (snd_pcm_uframes_t) bufferSizeInFrames;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
    /* choose all parameters */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
    ret = snd_pcm_hw_params_any(info->handle, info->hwParams);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
        ERROR1("Broken configuration: no configurations available: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
    /* set the interleaved read/write format */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
    ret = snd_pcm_hw_params_set_access(info->handle, info->hwParams, SND_PCM_ACCESS_RW_INTERLEAVED);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
        ERROR1("SND_PCM_ACCESS_RW_INTERLEAVED access type not available: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
    /* set the sample format */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
    ret = snd_pcm_hw_params_set_format(info->handle, info->hwParams, format);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
        ERROR1("Sample format not available: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    /* set the count of channels */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
    ret = snd_pcm_hw_params_set_channels(info->handle, info->hwParams, channels);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        ERROR2("Channels count (%d) not available: %s\n", channels, snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
    /* set the stream rate */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
    rrate = (int) (sampleRate + 0.5f);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
    dir = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
    ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, &rrate, &dir);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        ERROR2("Rate %dHz not available for playback: %s\n", (int) (sampleRate+0.5f), snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
    if ((rrate-sampleRate > 2) || (rrate-sampleRate < - 2)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
        ERROR2("Rate doesn't match (requested %2.2fHz, got %dHz)\n", sampleRate, rrate);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
    /* set the buffer time */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
    ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, &alsaBufferSizeInFrames);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        ERROR2("Unable to set buffer size to %d frames: %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
               (int) alsaBufferSizeInFrames, snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
    bufferSizeInFrames = (int) alsaBufferSizeInFrames;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
    /* set the period time */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
    if (bufferSizeInFrames > 1024) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
        dir = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        periodTime = DEFAULT_PERIOD_TIME;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        ret = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, &periodTime, &dir);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
            ERROR2("Unable to set period time to %d: %s\n", DEFAULT_PERIOD_TIME, snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
            return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
        /* set the period count for very small buffer sizes to 2 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
        dir = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        periods = 2;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        ret = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, &periods, &dir);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
            ERROR2("Unable to set period count to %d: %s\n", /*periods*/ 2, snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
            return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
    /* write the parameters to device */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
    ret = snd_pcm_hw_params(info->handle, info->hwParams);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        ERROR1("Unable to set hw params: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
// returns 1 if successful
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
int setSWParams(AlsaPcmInfo* info) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
    /* get the current swparams */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
    ret = snd_pcm_sw_params_current(info->handle, info->swParams);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        ERROR1("Unable to determine current swparams: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
    /* never start the transfer automatically */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
    if (!setStartThresholdNoCommit(info, FALSE /* don't use threshold */)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
    /* allow the transfer when at least period_size samples can be processed */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    ret = snd_pcm_sw_params_set_avail_min(info->handle, info->swParams, info->periodSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
        ERROR1("Unable to set avail min for playback: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
    /* write the parameters to the playback device */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
    ret = snd_pcm_sw_params(info->handle, info->swParams);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
        ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
static snd_output_t* ALSA_OUTPUT = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
                  int encoding, float sampleRate, int sampleSizeInBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
                  int frameSize, int channels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                  int isSigned, int isBigEndian, int bufferSizeInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
    snd_pcm_format_mask_t* formatMask;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
    snd_pcm_format_t format;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
    int dir;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
    int ret = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
    AlsaPcmInfo* info = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
    /* snd_pcm_uframes_t is 64 bit on 64-bit systems */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
    snd_pcm_uframes_t alsaBufferSizeInFrames = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
    TRACE0("> DAUDIO_Open\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
#ifdef USE_TRACE
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
    // for using ALSA debug dump methods
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
    if (ALSA_OUTPUT == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
        snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
#endif
41566
f52207d194bf 8157753: Audio replay enhancement
serb
parents: 25859
diff changeset
   437
    if (channels <= 0) {
f52207d194bf 8157753: Audio replay enhancement
serb
parents: 25859
diff changeset
   438
        ERROR1("ERROR: Invalid number of channels=%d!\n", channels);
f52207d194bf 8157753: Audio replay enhancement
serb
parents: 25859
diff changeset
   439
        return NULL;
f52207d194bf 8157753: Audio replay enhancement
serb
parents: 25859
diff changeset
   440
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
    info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
    if (!info) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
        ERROR0("Out of memory\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
    memset(info, 0, sizeof(AlsaPcmInfo));
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   447
    // initial values are: stopped, flushed
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   448
    info->isRunning = 0;
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   449
    info->isFlushed = 1;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
    ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
    if (ret == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        // set to blocking mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
        snd_pcm_nonblock(info->handle, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
        ret = snd_pcm_hw_params_malloc(&(info->hwParams));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
            ERROR1("  snd_pcm_hw_params_malloc returned error %d\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
            ret = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
            if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
                                        isSigned, isBigEndian, encoding)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
                if (setHWParams(info,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
                                sampleRate,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
                                channels,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
                                bufferSizeInBytes / frameSize,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
                                format)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                    info->frameSize = frameSize;
7792
612315e0949d 6989702: sound native code compiler warnings
amenkov
parents: 5506
diff changeset
   468
                    ret = snd_pcm_hw_params_get_period_size(info->hwParams, &info->periodSize, &dir);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
                    if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
                        ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                    snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
                    snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
                    info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
                    TRACE3("  DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
                           (int) info->periodSize, info->periods, info->bufferSizeInBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
        if (ret == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
            // set software parameters
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
            ret = snd_pcm_sw_params_malloc(&(info->swParams));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
            if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                if (!setSWParams(info)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                    ret = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
        if (ret == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
            // prepare device
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
            ret = snd_pcm_prepare(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
#ifdef GET_POSITION_METHOD2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
        if (ret == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
            ret = snd_pcm_status_malloc(&(info->positionStatus));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
            if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
                ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
    if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
        DAUDIO_Close((void*) info, isSource);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
        info = NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
        // set to non-blocking mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        snd_pcm_nonblock(info->handle, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
        TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
               (void*) info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
    return (void*) info;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
#ifdef USE_TRACE
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
void printState(snd_pcm_state_t state) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
    if (state == SND_PCM_STATE_OPEN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
        TRACE0("State: SND_PCM_STATE_OPEN\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
    else if (state == SND_PCM_STATE_SETUP) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
        TRACE0("State: SND_PCM_STATE_SETUP\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
    else if (state == SND_PCM_STATE_PREPARED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
        TRACE0("State: SND_PCM_STATE_PREPARED\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
    else if (state == SND_PCM_STATE_RUNNING) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
        TRACE0("State: SND_PCM_STATE_RUNNING\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
    else if (state == SND_PCM_STATE_XRUN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
        TRACE0("State: SND_PCM_STATE_XRUN\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
    else if (state == SND_PCM_STATE_DRAINING) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        TRACE0("State: SND_PCM_STATE_DRAINING\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
    else if (state == SND_PCM_STATE_PAUSED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
        TRACE0("State: SND_PCM_STATE_PAUSED\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
    else if (state == SND_PCM_STATE_SUSPENDED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
        TRACE0("State: SND_PCM_STATE_SUSPENDED\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
int DAUDIO_Start(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
    snd_pcm_state_t state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
    TRACE0("> DAUDIO_Start\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
    // set to blocking mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
    snd_pcm_nonblock(info->handle, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
    // set start mode so that it always starts as soon as data is there
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
    setStartThreshold(info, TRUE /* use threshold */);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
    state = snd_pcm_state(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
    if (state == SND_PCM_STATE_PAUSED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
        // in case it was stopped previously
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
        TRACE0("  Un-pausing...\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
        ret = snd_pcm_pause(info->handle, FALSE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
            ERROR2("  NOTE: error in snd_pcm_pause:%d: %s\n", ret, snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
    if (state == SND_PCM_STATE_SUSPENDED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
        TRACE0("  Resuming...\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
        ret = snd_pcm_resume(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
        if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
            if ((ret != -EAGAIN) && (ret != -ENOSYS)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
                ERROR2("  ERROR: error in snd_pcm_resume:%d: %s\n", ret, snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
    if (state == SND_PCM_STATE_SETUP) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        TRACE0("need to call prepare again...\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
        // prepare device
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        ret = snd_pcm_prepare(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
        if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
            ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
    // in case there is still data in the buffers
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
    ret = snd_pcm_start(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
    if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
        if (ret != -EPIPE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
            ERROR2("  NOTE: error in snd_pcm_start: %d: %s\n", ret, snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
    // set to non-blocking mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
    ret = snd_pcm_nonblock(info->handle, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
    if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
        ERROR1("  ERROR in snd_pcm_nonblock: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
    state = snd_pcm_state(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
#ifdef USE_TRACE
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
    printState(state);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
    ret = (state == SND_PCM_STATE_PREPARED)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
        || (state == SND_PCM_STATE_RUNNING)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
        || (state == SND_PCM_STATE_XRUN)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
        || (state == SND_PCM_STATE_SUSPENDED);
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   605
    if (ret) {
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   606
        info->isRunning = 1;
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   607
        // source line should keep isFlushed value until Write() is called;
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   608
        // for target data line reset it right now.
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   609
        if (!isSource) {
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   610
            info->isFlushed = 0;
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   611
        }
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   612
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
    TRACE1("< DAUDIO_Start %s\n", ret?"success":"error");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
    return ret?TRUE:FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
int DAUDIO_Stop(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
    TRACE0("> DAUDIO_Stop\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
    // set to blocking mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
    snd_pcm_nonblock(info->handle, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
    setStartThreshold(info, FALSE /* don't use threshold */); // device will not start after buffer xrun
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
    ret = snd_pcm_pause(info->handle, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
    // set to non-blocking mode
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
    snd_pcm_nonblock(info->handle, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
    if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
        ERROR1("ERROR in snd_pcm_pause: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
    }
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   632
    info->isRunning = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
    TRACE0("< DAUDIO_Stop success\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
void DAUDIO_Close(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
    TRACE0("DAUDIO_Close\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
    if (info != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
        if (info->handle != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
            snd_pcm_close(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        if (info->hwParams) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
            snd_pcm_hw_params_free(info->hwParams);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
        if (info->swParams) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
            snd_pcm_sw_params_free(info->swParams);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
#ifdef GET_POSITION_METHOD2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        if (info->positionStatus) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
            snd_pcm_status_free(info->positionStatus);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
        free(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   657
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   658
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   659
90ce3da70b43 Initial load
duke
parents:
diff changeset
   660
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
 * Underrun and suspend recovery
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
 * returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
 * 0:  exit native and return 0
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
 * 1:  try again to write/read
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
 * -1: error - exit native with return value -1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
int xrun_recovery(AlsaPcmInfo* info, int err) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
    if (err == -EPIPE) {    /* underrun / overflow */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
        TRACE0("xrun_recovery: underrun/overflow.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
        ret = snd_pcm_prepare(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
        if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
            ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
            return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
        return 1;
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   678
    } else if (err == -ESTRPIPE) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
        TRACE0("xrun_recovery: suspended.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
        ret = snd_pcm_resume(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
        if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
            if (ret == -EAGAIN) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
                return 0; /* wait until the suspend flag is released */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
            return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
        ret = snd_pcm_prepare(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
        if (ret < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
            ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
            return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
        return 1;
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   693
    } else if (err == -EAGAIN) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        TRACE0("xrun_recovery: EAGAIN try again flag.\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
        return 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
    }
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   697
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
    TRACE2("xrun_recovery: unexpected error %d: %s\n", err, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
    return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
// returns -1 on error
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
int DAUDIO_Write(void* id, char* data, int byteSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
    int ret, count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
    snd_pcm_sframes_t frameSize, writtenFrames;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
    TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
    /* sanity */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
    if (byteSize <= 0 || info->frameSize <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
        ERROR2(" DAUDIO_Write: byteSize=%d, frameSize=%d!\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
               (int) byteSize, (int) info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
        TRACE0("< DAUDIO_Write returning -1\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
        return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
    }
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   717
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
    count = 2; // maximum number of trials to recover from underrun
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
    //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
    frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
    do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
        writtenFrames = snd_pcm_writei(info->handle, (const void*) data, (snd_pcm_uframes_t) frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
        if (writtenFrames < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
            ret = xrun_recovery(info, (int) writtenFrames);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
            if (ret <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
                TRACE1("DAUDIO_Write: xrun recovery returned %d -> return.\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
                return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
            if (count-- <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
                ERROR0("DAUDIO_Write: too many attempts to recover from xrun/suspend\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
                return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
    } while (TRUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
    //ret =  snd_pcm_frames_to_bytes(info->handle, writtenFrames);
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   739
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   740
    if (writtenFrames > 0) {
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   741
        // reset "flushed" flag
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   742
        info->isFlushed = 0;
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   743
    }
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   744
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
    ret =  (int) (writtenFrames * info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
    TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
    return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
// returns -1 on error
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
int DAUDIO_Read(void* id, char* data, int byteSize) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
    int ret, count;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
    snd_pcm_sframes_t frameSize, readFrames;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
    TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
    /*TRACE3("  info=%p, data=%p, byteSize=%d\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
      (void*) info, (void*) data, (int) byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
      TRACE2("  info->frameSize=%d, info->handle=%p\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
      (int) info->frameSize, (void*) info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
    */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
    /* sanity */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
    if (byteSize <= 0 || info->frameSize <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
        ERROR2(" DAUDIO_Read: byteSize=%d, frameSize=%d!\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
               (int) byteSize, (int) info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
        TRACE0("< DAUDIO_Read returning -1\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
        return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
    }
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   769
    if (!info->isRunning && info->isFlushed) {
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   770
        // PCM has nothing to read
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   771
        return 0;
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   772
    }
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   773
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
    count = 2; // maximum number of trials to recover from error
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
    //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
    frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
    do {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
        readFrames = snd_pcm_readi(info->handle, (void*) data, (snd_pcm_uframes_t) frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
        if (readFrames < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
            ret = xrun_recovery(info, (int) readFrames);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
            if (ret <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
                TRACE1("DAUDIO_Read: xrun recovery returned %d -> return.\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
                return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
            if (count-- <= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
                ERROR0("DAUDIO_Read: too many attempts to recover from xrun/suspend\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
                return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
    } while (TRUE);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
    //ret =  snd_pcm_frames_to_bytes(info->handle, readFrames);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
    ret =  (int) (readFrames * info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
    TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
    return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
90ce3da70b43 Initial load
duke
parents:
diff changeset
   800
int DAUDIO_GetBufferSize(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
    return info->bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
int DAUDIO_StillDraining(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
    snd_pcm_state_t state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   809
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
    state = snd_pcm_state(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
    //printState(state);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
    //TRACE1("Still draining: %s\n", (state != SND_PCM_STATE_XRUN)?"TRUE":"FALSE");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
    return (state == SND_PCM_STATE_RUNNING)?TRUE:FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
int DAUDIO_Flush(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
    TRACE0("DAUDIO_Flush\n");
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   822
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   823
    if (info->isFlushed) {
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   824
        // nothing to drop
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   825
        return 1;
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   826
    }
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   827
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
    ret = snd_pcm_drop(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   829
    if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   830
        ERROR1("ERROR in snd_pcm_drop: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   831
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   832
    }
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   833
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   834
    info->isFlushed = 1;
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   835
    if (info->isRunning) {
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   836
        ret = DAUDIO_Start(id, isSource);
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   837
    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
    return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
int DAUDIO_GetAvailable(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
    snd_pcm_sframes_t availableInFrames;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
    snd_pcm_state_t state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
    state = snd_pcm_state(info->handle);
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   848
    if (info->isFlushed || state == SND_PCM_STATE_XRUN) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
        // if in xrun state then we have the entire buffer available,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
        // not 0 as alsa reports
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
        ret = info->bufferSizeInBytes;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
        availableInFrames = snd_pcm_avail_update(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
        if (availableInFrames < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
            ret = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
            //ret = snd_pcm_frames_to_bytes(info->handle, availableInFrames);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
            ret = (int) (availableInFrames * info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
    TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
    return ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
INT64 estimatePositionFromAvail(AlsaPcmInfo* info, int isSource, INT64 javaBytePos, int availInBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
    // estimate the current position with the buffer size and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
    // the available bytes to read or write in the buffer.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
    // not an elegant solution - bytePos will stop on xruns,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
    // and in race conditions it may jump backwards
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
    // Advantage is that it is indeed based on the samples that go through
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
    // the system (rather than time-based methods)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
    if (isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
        // javaBytePos is the position that is reached when the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
        // buffer is played completely
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
        return (INT64) (javaBytePos - info->bufferSizeInBytes + availInBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
        // javaBytePos is the position that was when the current buffer was empty
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
        return (INT64) (javaBytePos + availInBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   880
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   881
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
    int ret;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
    INT64 result = javaBytePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
    snd_pcm_state_t state;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
    state = snd_pcm_state(info->handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   888
9487
cee25570116b 7030629: closed/sun/audio/AudioClipClose/AudioClipClose.java test fails just against jdk7 b134
amenkov
parents: 7792
diff changeset
   889
    if (!info->isFlushed && state != SND_PCM_STATE_XRUN) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   890
#ifdef GET_POSITION_METHOD2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   891
        snd_timestamp_t* ts;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   892
        snd_pcm_uframes_t framesAvail;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   893
90ce3da70b43 Initial load
duke
parents:
diff changeset
   894
        // note: slight race condition if this is called simultaneously from 2 threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
        ret = snd_pcm_status(info->handle, info->positionStatus);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   896
        if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
            ERROR1("ERROR in snd_pcm_status: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
            result = javaBytePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
            // calculate from time value, or from available bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
            framesAvail = snd_pcm_status_get_avail(info->positionStatus);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
            result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
#ifdef GET_POSITION_METHOD3
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        snd_pcm_uframes_t framesAvail;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
        ret = snd_pcm_avail(info->handle, &framesAvail);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
        if (ret != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
            ERROR1("ERROR in snd_pcm_avail: %s\n", snd_strerror(ret));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
            result = javaBytePos;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
            result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
#ifdef GET_POSITION_METHOD1
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
        result = estimatePositionFromAvail(info, isSource, javaBytePos, DAUDIO_GetAvailable(id, isSource));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
#endif
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
    //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
    return result;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
    /* save to ignore, since GetBytePosition
90ce3da70b43 Initial load
duke
parents:
diff changeset
   927
     * takes the javaBytePos param into account
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
int DAUDIO_RequiresServicing(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   932
    // never need servicing on Linux
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
    return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
void DAUDIO_Service(void* id, int isSource) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
    // never need servicing on Linux
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
#endif // USE_DAUDIO