src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c
author neliasso
Mon, 01 Jul 2019 10:49:58 +0200
changeset 55536 8313c42345d5
parent 49289 148e29df1644
permissions -rw-r--r--
8226287: Make process_users_of_allocation handle gc barriers Reviewed-by: kvn, roland
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
42938
c0b3077af726 8170798: Fix minor issues in java2d and sound coding.
goetz
parents: 32111
diff changeset
     2
 * Copyright (c) 2003, 2016, 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: 2
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: 2
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: 2
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2
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 "Ports.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 <alsa/asoundlib.h>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
#if USE_PORTS == TRUE
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
#define MAX_ELEMS (300)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
#define MAX_CONTROLS (MAX_ELEMS * 4)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
#define CHANNELS_MONO (SND_MIXER_SCHN_LAST + 1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
#define CHANNELS_STEREO (SND_MIXER_SCHN_LAST + 2)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
typedef struct {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
    snd_mixer_elem_t* elem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
    INT32 portType; /* one of PORT_XXX_xx */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    char* controlType; /* one of CONTROL_TYPE_xx */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
    /* Values: either SND_MIXER_SCHN_FRONT_xx, CHANNELS_MONO or CHANNELS_STEREO.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
       For SND_MIXER_SCHN_FRONT_xx, exactly this channel is set/retrieved directly.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
       For CHANNELS_MONO, ALSA channel SND_MIXER_SCHN_MONO is set/retrieved directly.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
       For CHANNELS_STEREO, ALSA channels SND_MIXER_SCHN_FRONT_LEFT and SND_MIXER_SCHN_FRONT_RIGHT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
       are set after a calculation that takes balance into account. Retrieved? Average of both
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
       channels? (Using a cached value is not a good idea since the value in the HW may have been
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
       altered.) */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
    INT32 channel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
} PortControl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
90ce3da70b43 Initial load
duke
parents:
diff changeset
    56
typedef struct tag_PortMixer {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
    snd_mixer_t* mixer_handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
    /* Number of array elements used in elems and types. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
    int numElems;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
    snd_mixer_elem_t** elems;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
    /* Array of port types (PORT_SRC_UNKNOWN etc.). Indices are the same as in elems. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
    INT32* types;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
    /* Number of array elements used in controls. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    int numControls;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
    PortControl* controls;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
} PortMixer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
///// implemented functions of Ports.h
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
INT32 PORT_GetPortMixerCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
    INT32 mixerCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
    int card;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
    char devname[16];
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
    int err;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    snd_ctl_t *handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
    snd_ctl_card_info_t* info;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
    TRACE0("> PORT_GetPortMixerCount\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    initAlsaSupport();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    snd_ctl_card_info_malloc(&info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
    card = -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    mixerCount = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
    if (snd_card_next(&card) >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
        while (card >= 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
            sprintf(devname, ALSA_HARDWARE_CARD, card);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
            TRACE1("PORT_GetPortMixerCount: Opening alsa device \"%s\"...\n", devname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
            err = snd_ctl_open(&handle, devname, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
            if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
                ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
                mixerCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
                snd_ctl_close(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
            if (snd_card_next(&card) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
    snd_ctl_card_info_free(info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
    TRACE0("< PORT_GetPortMixerCount\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
    return mixerCount;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
    snd_ctl_t* handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
    snd_ctl_card_info_t* card_info;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    char devname[16];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
    int err;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
    char buffer[100];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
    TRACE0("> PORT_GetPortMixerDescription\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
    snd_ctl_card_info_malloc(&card_info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
    sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
    TRACE1("Opening alsa device \"%s\"...\n", devname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
    err = snd_ctl_open(&handle, devname, 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
    if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
        ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
    err = snd_ctl_card_info(handle, card_info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
        ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    strncpy(description->name, snd_ctl_card_info_get_id(card_info), PORT_STRING_LENGTH - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
    sprintf(buffer, " [%s]", devname);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
    strncat(description->name, buffer, PORT_STRING_LENGTH - 1 - strlen(description->name));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
    strncpy(description->vendor, "ALSA (http://www.alsa-project.org)", PORT_STRING_LENGTH - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
    strncpy(description->description, snd_ctl_card_info_get_name(card_info), PORT_STRING_LENGTH - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
    strncat(description->description, ", ", PORT_STRING_LENGTH - 1 - strlen(description->description));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
    strncat(description->description, snd_ctl_card_info_get_mixername(card_info), PORT_STRING_LENGTH - 1 - strlen(description->description));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
    getALSAVersion(description->version, PORT_STRING_LENGTH - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
    snd_ctl_close(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
    snd_ctl_card_info_free(card_info);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
    TRACE0("< PORT_GetPortMixerDescription\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
void* PORT_Open(INT32 mixerIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
    char devname[16];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
    snd_mixer_t* mixer_handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
    int err;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
    PortMixer* handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
    TRACE0("> PORT_Open\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
    sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
    if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
        ERROR2("Mixer %s open error: %s", devname, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   155
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
    if ((err = snd_mixer_attach(mixer_handle, devname)) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        ERROR2("Mixer attach %s error: %s", devname, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
        snd_mixer_close(mixer_handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
    if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
        ERROR1("Mixer register error: %s", snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
        snd_mixer_close(mixer_handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
    err = snd_mixer_load(mixer_handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
    if (err < 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
        ERROR2("Mixer %s load error: %s", devname, snd_strerror(err));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
        snd_mixer_close(mixer_handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
    handle = (PortMixer*) calloc(1, sizeof(PortMixer));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
    if (handle == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
        ERROR0("malloc() failed.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        snd_mixer_close(mixer_handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
    handle->numElems = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
    handle->elems = (snd_mixer_elem_t**) calloc(MAX_ELEMS, sizeof(snd_mixer_elem_t*));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
    if (handle->elems == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
        ERROR0("malloc() failed.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
        snd_mixer_close(mixer_handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
        free(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
    handle->types = (INT32*) calloc(MAX_ELEMS, sizeof(INT32));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
    if (handle->types == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        ERROR0("malloc() failed.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
        snd_mixer_close(mixer_handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   191
        free(handle->elems);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
        free(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
    handle->controls = (PortControl*) calloc(MAX_CONTROLS, sizeof(PortControl));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
    if (handle->controls == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
        ERROR0("malloc() failed.");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        snd_mixer_close(mixer_handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
        free(handle->elems);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        free(handle->types);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
        free(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
        return NULL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    handle->mixer_handle = mixer_handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
    // necessary to initialize data structures
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
    PORT_GetPortCount(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
    TRACE0("< PORT_Open\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
    return handle;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
void PORT_Close(void* id) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
    TRACE0("> PORT_Close\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
    if (id != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
        PortMixer* handle = (PortMixer*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
        if (handle->mixer_handle != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
            snd_mixer_close(handle->mixer_handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
        if (handle->elems != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
            free(handle->elems);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
        if (handle->types != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
            free(handle->types);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
        if (handle->controls != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
            free(handle->controls);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
        free(handle);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
    TRACE0("< PORT_Close\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
INT32 PORT_GetPortCount(void* id) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
    PortMixer* portMixer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
    snd_mixer_elem_t *elem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
    TRACE0("> PORT_GetPortCount\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
    if (id == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
        // $$mp: Should become a descriptive error code (invalid handle).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
    portMixer = (PortMixer*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
    if (portMixer->numElems == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
        for (elem = snd_mixer_first_elem(portMixer->mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
            if (!snd_mixer_selem_is_active(elem))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                continue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
            TRACE2("Simple mixer control '%s',%i\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
                   snd_mixer_selem_get_name(elem),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
                   snd_mixer_selem_get_index(elem));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
            if (snd_mixer_selem_has_playback_volume(elem)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                portMixer->elems[portMixer->numElems] = elem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
                portMixer->types[portMixer->numElems] = PORT_DST_UNKNOWN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
                portMixer->numElems++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
            // to prevent buffer overflow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
            if (portMixer->numElems >= MAX_ELEMS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
            /* If an element has both playback an capture volume, it is put into the arrays
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
               twice. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
            if (snd_mixer_selem_has_capture_volume(elem)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
                portMixer->elems[portMixer->numElems] = elem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
                portMixer->types[portMixer->numElems] = PORT_SRC_UNKNOWN;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
                portMixer->numElems++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
            // to prevent buffer overflow
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
            if (portMixer->numElems >= MAX_ELEMS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
    TRACE0("< PORT_GetPortCount\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
    return portMixer->numElems;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
INT32 PORT_GetPortType(void* id, INT32 portIndex) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
    PortMixer* portMixer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
    INT32 type;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
    TRACE0("> PORT_GetPortType\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
    if (id == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
        // $$mp: Should become a descriptive error code (invalid handle).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
        return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
    portMixer = (PortMixer*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
    if (portIndex < 0 || portIndex >= portMixer->numElems) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
        // $$mp: Should become a descriptive error code (index out of bounds).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
    type = portMixer->types[portIndex];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
    TRACE0("< PORT_GetPortType\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
    return type;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
    PortMixer* portMixer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
    const char* nam;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
    TRACE0("> PORT_GetPortName\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
    if (id == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
        // $$mp: Should become a descriptive error code (invalid handle).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
        return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
    portMixer = (PortMixer*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
    if (portIndex < 0 || portIndex >= portMixer->numElems) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        // $$mp: Should become a descriptive error code (index out of bounds).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
        return -1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
    nam = snd_mixer_selem_get_name(portMixer->elems[portIndex]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
    strncpy(name, nam, len - 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
    name[len - 1] = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
    TRACE0("< PORT_GetPortName\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
    return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
static int isPlaybackFunction(INT32 portType) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
        return (portType & PORT_DST_MASK);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
/* Sets portControl to a pointer to the next free array element in the PortControl (pointer)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
   array of the passed portMixer. Returns TRUE if successful. May return FALSE if there is no
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
   free slot. In this case, portControl is not altered */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
static int getControlSlot(PortMixer* portMixer, PortControl** portControl) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
    if (portMixer->numControls >= MAX_CONTROLS) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
        return FALSE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        *portControl = &(portMixer->controls[portMixer->numControls]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
        portMixer->numControls++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        return TRUE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
/* Protect against illegal min-max values, preventing divisions by zero.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
inline static long getRange(long min, long max) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
    if (max > min) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        return max - min;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
        return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
/* Idea: we may specify that if unit is an empty string, the values are linear and if unit is "dB",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
   the values are logarithmic.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
*/
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
static void* createVolumeControl(PortControlCreator* creator,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
                                 PortControl* portControl,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
                                 snd_mixer_elem_t* elem, int isPlayback) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
    void* control;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
    float precision;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
    long min, max;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
    if (isPlayback) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
    /* $$mp: The volume values retrieved with the ALSA API are strongly supposed to be logarithmic.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
       So the following calculation is wrong. However, there is no correct calculation, since
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
       for equal-distant logarithmic steps, the precision expressed in linear varies over the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
       scale. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
    precision = 1.0F / getRange(min, max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
    control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_VOLUME, 0.0F, +1.0F, precision, "");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
    return control;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
    PortMixer* portMixer;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
    snd_mixer_elem_t* elem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
    void* control;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
    PortControl* portControl;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
    void* controls[10];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
    int numControls;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
    char* portName;
7792
612315e0949d 6989702: sound native code compiler warnings
amenkov
parents: 5506
diff changeset
   383
    int isPlayback = 0;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
    int isMono;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
    int isStereo;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
    char* type;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
    snd_mixer_selem_channel_id_t channel;
42938
c0b3077af726 8170798: Fix minor issues in java2d and sound coding.
goetz
parents: 32111
diff changeset
   388
    memset(controls, 0, sizeof(controls));
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
    TRACE0("> PORT_GetControls\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
    if (id == NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
        ERROR0("Invalid handle!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
        // $$mp: an error code should be returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
    portMixer = (PortMixer*) id;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
    if (portIndex < 0 || portIndex >= portMixer->numElems) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
        ERROR0("Port index out of range!");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
        // $$mp: an error code should be returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
    numControls = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
    elem = portMixer->elems[portIndex];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
    if (snd_mixer_selem_has_playback_volume(elem) || snd_mixer_selem_has_capture_volume(elem)) {
21278
ef8a3a2a72f2 8022746: List of spelling errors in API doc
malenkov
parents: 7792
diff changeset
   405
        /* Since we've split/duplicated elements with both playback and capture on the recovery
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
           of elements, we now can assume that we handle only to deal with either playback or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
           capture. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
        isPlayback = isPlaybackFunction(portMixer->types[portIndex]);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
        isMono = (isPlayback && snd_mixer_selem_is_playback_mono(elem)) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
            (!isPlayback && snd_mixer_selem_is_capture_mono(elem));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
        isStereo = (isPlayback &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
                    snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
                    snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
            (!isPlayback &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
             snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
             snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
        // single volume control
90ce3da70b43 Initial load
duke
parents:
diff changeset
   418
        if (isMono || isStereo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            if (getControlSlot(portMixer, &portControl)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
                portControl->elem = elem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
                portControl->portType = portMixer->types[portIndex];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   422
                portControl->controlType = CONTROL_TYPE_VOLUME;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
                if (isMono) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
                    portControl->channel = CHANNELS_MONO;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
                } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                    portControl->channel = CHANNELS_STEREO;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   427
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
                control = createVolumeControl(creator, portControl, elem, isPlayback);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                if (control != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                    controls[numControls++] = control;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        } else { // more than two channels, each channels has its own control.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
            for (channel = SND_MIXER_SCHN_FRONT_LEFT; channel <= SND_MIXER_SCHN_LAST; channel++) {
32111
77f01a77573d 8074832: Resolve disabled warnings for libjsoundalsa
serb
parents: 25859
diff changeset
   435
                if ((isPlayback && snd_mixer_selem_has_playback_channel(elem, channel)) ||
77f01a77573d 8074832: Resolve disabled warnings for libjsoundalsa
serb
parents: 25859
diff changeset
   436
                    (!isPlayback && snd_mixer_selem_has_capture_channel(elem, channel))) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
                    if (getControlSlot(portMixer, &portControl)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
                        portControl->elem = elem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
                        portControl->portType = portMixer->types[portIndex];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   440
                        portControl->controlType = CONTROL_TYPE_VOLUME;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   441
                        portControl->channel = channel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   442
                        control = createVolumeControl(creator, portControl, elem, isPlayback);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                        // We wrap in a compound control to provide the channel name.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
                        if (control != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
                            /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                               declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   447
                               to take a const char* parameter. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                            control = (creator->newCompoundControl)(creator, (char*) snd_mixer_selem_channel_name(channel), &control, 1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                        if (control != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                            controls[numControls++] = control;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
        // BALANCE control
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
        if (isStereo) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
            if (getControlSlot(portMixer, &portControl)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                portControl->elem = elem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
                portControl->portType = portMixer->types[portIndex];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
                portControl->controlType = CONTROL_TYPE_BALANCE;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
                portControl->channel = CHANNELS_STEREO;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
                /* $$mp: The value for precision is chosen more or less arbitrarily. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
                control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_BALANCE, -1.0F, 1.0F, 0.01F, "");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
                if (control != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
                    controls[numControls++] = control;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
    if (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_capture_switch(elem)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
        if (getControlSlot(portMixer, &portControl)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   474
            type = isPlayback ? CONTROL_TYPE_MUTE : CONTROL_TYPE_SELECT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
            portControl->elem = elem;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
            portControl->portType = portMixer->types[portIndex];
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
            portControl->controlType = type;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   478
            control = (creator->newBooleanControl)(creator, portControl, type);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
            if (control != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
                controls[numControls++] = control;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
    /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
       declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
       to take a const char* parameter. */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
    portName = (char*) snd_mixer_selem_get_name(elem);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   488
    control = (creator->newCompoundControl)(creator, portName, controls, numControls);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
    if (control != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   490
        (creator->addControl)(creator, control);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
    TRACE0("< PORT_GetControls\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
INT32 PORT_GetIntValue(void* controlIDV) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
    PortControl* portControl = (PortControl*) controlIDV;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
    int value = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
    snd_mixer_selem_channel_id_t channel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
    if (portControl != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
        switch (portControl->channel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
        case CHANNELS_MONO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
            channel = SND_MIXER_SCHN_MONO;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
        case CHANNELS_STEREO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   508
            channel = SND_MIXER_SCHN_FRONT_LEFT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
            break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
90ce3da70b43 Initial load
duke
parents:
diff changeset
   511
        default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   512
            channel = portControl->channel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   513
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   514
        if (portControl->controlType == CONTROL_TYPE_MUTE ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   515
            portControl->controlType == CONTROL_TYPE_SELECT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   516
            if (isPlaybackFunction(portControl->portType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   517
                snd_mixer_selem_get_playback_switch(portControl->elem, channel, &value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   518
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   519
                snd_mixer_selem_get_capture_switch(portControl->elem, channel, &value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   520
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   521
            if (portControl->controlType == CONTROL_TYPE_MUTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   522
                value = ! value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   523
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   524
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   525
            ERROR1("PORT_GetIntValue(): inappropriate control type: %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   526
                   portControl->controlType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   527
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   528
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   529
    return (INT32) value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   530
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   531
90ce3da70b43 Initial load
duke
parents:
diff changeset
   532
90ce3da70b43 Initial load
duke
parents:
diff changeset
   533
void PORT_SetIntValue(void* controlIDV, INT32 value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
    PortControl* portControl = (PortControl*) controlIDV;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
    snd_mixer_selem_channel_id_t channel;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
90ce3da70b43 Initial load
duke
parents:
diff changeset
   537
    if (portControl != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   538
        if (portControl->controlType == CONTROL_TYPE_MUTE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   539
            value = ! value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   540
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   541
        if (portControl->controlType == CONTROL_TYPE_MUTE ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   542
            portControl->controlType == CONTROL_TYPE_SELECT) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   543
            if (isPlaybackFunction(portControl->portType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   544
                snd_mixer_selem_set_playback_switch_all(portControl->elem, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   545
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   546
                snd_mixer_selem_set_capture_switch_all(portControl->elem, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   547
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   548
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   549
            ERROR1("PORT_SetIntValue(): inappropriate control type: %s\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   550
                   portControl->controlType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   551
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   552
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
static float scaleVolumeValueToNormalized(long value, long min, long max) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
    return (float) (value - min) / getRange(min, max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
90ce3da70b43 Initial load
duke
parents:
diff changeset
   561
static long scaleVolumeValueToHardware(float value, long min, long max) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
    return (long)(value * getRange(min, max) + min);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   563
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
float getRealVolume(PortControl* portControl,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
                    snd_mixer_selem_channel_id_t channel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
    float fValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   569
    long lValue = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
    long min = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
    long max = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
    if (isPlaybackFunction(portControl->portType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
        snd_mixer_selem_get_playback_volume_range(portControl->elem,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                                                  &min, &max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
        snd_mixer_selem_get_playback_volume(portControl->elem,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
                                            channel, &lValue);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
        snd_mixer_selem_get_capture_volume_range(portControl->elem,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
                                                 &min, &max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
        snd_mixer_selem_get_capture_volume(portControl->elem,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
                                           channel, &lValue);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   583
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
    fValue = scaleVolumeValueToNormalized(lValue, min, max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   585
    return fValue;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
void setRealVolume(PortControl* portControl,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
                   snd_mixer_selem_channel_id_t channel, float value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
    long lValue = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
    long min = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   593
    long max = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   594
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
    if (isPlaybackFunction(portControl->portType)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
        snd_mixer_selem_get_playback_volume_range(portControl->elem,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   597
                                                  &min, &max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   598
        lValue = scaleVolumeValueToHardware(value, min, max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   599
        snd_mixer_selem_set_playback_volume(portControl->elem,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   600
                                            channel, lValue);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   601
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   602
        snd_mixer_selem_get_capture_volume_range(portControl->elem,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   603
                                                 &min, &max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   604
        lValue = scaleVolumeValueToHardware(value, min, max);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   605
        snd_mixer_selem_set_capture_volume(portControl->elem,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   606
                                           channel, lValue);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   607
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   608
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   609
90ce3da70b43 Initial load
duke
parents:
diff changeset
   610
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
static float getFakeBalance(PortControl* portControl) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
    float volL, volR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
    // pan is the ratio of left and right
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
    volL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
    volR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
    if (volL > volR) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
        return -1.0f + (volR / volL);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
    else if (volR > volL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
        return 1.0f - (volL / volR);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
    return 0.0f;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
static float getFakeVolume(PortControl* portControl) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
    float valueL;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
    float valueR;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   630
    float value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
    valueL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
    valueR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
    // volume is the greater value of both
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
    value = valueL > valueR ? valueL : valueR ;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
    return value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
 * sets the unsigned values for left and right volume according to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
 * the given volume (0...1) and balance (-1..0..+1)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
static void setFakeVolume(PortControl* portControl, float vol, float bal) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
    float volumeLeft;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
    float volumeRight;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
90ce3da70b43 Initial load
duke
parents:
diff changeset
   648
    if (bal < 0.0f) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   649
        volumeLeft = vol;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   650
        volumeRight = vol * (bal + 1.0f);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   651
    } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   652
        volumeLeft = vol * (1.0f - bal);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   653
        volumeRight = vol;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   654
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   655
    setRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT, volumeLeft);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   656
    setRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT, volumeRight);
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
float PORT_GetFloatValue(void* controlIDV) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   661
    PortControl* portControl = (PortControl*) controlIDV;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
    float value = 0.0F;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
    if (portControl != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   665
        if (portControl->controlType == CONTROL_TYPE_VOLUME) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
            switch (portControl->channel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
            case CHANNELS_MONO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
                value = getRealVolume(portControl, SND_MIXER_SCHN_MONO);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
            case CHANNELS_STEREO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
                value = getFakeVolume(portControl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
                value = getRealVolume(portControl, portControl->channel);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
        } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
            if (portControl->channel == CHANNELS_STEREO) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   680
                value = getFakeBalance(portControl);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
                ERROR0("PORT_GetFloatValue(): Balance only allowed for stereo channels!\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
            ERROR1("PORT_GetFloatValue(): inappropriate control type: %s!\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
                   portControl->controlType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
    return value;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
void PORT_SetFloatValue(void* controlIDV, float value) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
    PortControl* portControl = (PortControl*) controlIDV;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
    if (portControl != NULL) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
        if (portControl->controlType == CONTROL_TYPE_VOLUME) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
            switch (portControl->channel) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
            case CHANNELS_MONO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   700
                setRealVolume(portControl, SND_MIXER_SCHN_MONO, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
            case CHANNELS_STEREO:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
                setFakeVolume(portControl, value, getFakeBalance(portControl));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
                break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
            default:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
                setRealVolume(portControl, portControl->channel, value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
        } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
            if (portControl->channel == CHANNELS_STEREO) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
                setFakeVolume(portControl, getFakeVolume(portControl), value);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   713
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
                ERROR0("PORT_SetFloatValue(): Balance only allowed for stereo channels!\n");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
            ERROR1("PORT_SetFloatValue(): inappropriate control type: %s!\n",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   718
                   portControl->controlType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
#endif // USE_PORTS