2
* KMix -- KDE's full featured mini mixer
5
* Copyright (C) 1996-2000 Christian Esken <esken@kde.org>
6
* 2000 Brian Hanson <bhanson@hotmail.com>
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Library General Public
10
* License as published by the Free Software Foundation; either
11
* version 2 of the License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* Library General Public License for more details.
18
* You should have received a copy of the GNU Library General Public
19
* License along with this program; if not, write to the Free
20
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
#include <sys/types.h>
27
#include <sys/audioio.h>
31
#include "mixer_sun.h"
34
//======================================================================
35
// CONSTANT/ENUM DEFINITIONS
36
//======================================================================
39
// Mixer Device Numbers
41
// Note: We can't just use the Sun port #defines because :
42
// 1) Some logical devices don't correspond to ports (master&recmon)
43
// 2) The play and record port definitions reuse the same values
47
MIXERDEV_MASTER_VOLUME,
48
MIXERDEV_INTERNAL_SPEAKER,
51
MIXERDEV_RECORD_MONITOR,
55
// Insert new devices before this marker
58
const int numDevs = MIXERDEV_END_MARKER;
61
// Device name strings
63
const char* MixerDevNames[] =
65
I18N_NOOP("Master Volume"),
66
I18N_NOOP("Internal Speaker"),
67
I18N_NOOP("Headphone"),
68
I18N_NOOP("Line Out"),
69
I18N_NOOP("Record Monitor"),
70
I18N_NOOP("Microphone"),
76
// Channel types (this specifies which icon to display)
78
const MixDevice::ChannelType MixerChannelTypes[] =
80
MixDevice::VOLUME, // MASTER_VOLUME
81
MixDevice::AUDIO, // INTERNAL_SPEAKER
82
MixDevice::EXTERNAL, // HEADPHONE (we really need an icon for this)
83
MixDevice::EXTERNAL, // LINE_OUT
84
MixDevice::RECMONITOR, // RECORD_MONITOR
85
MixDevice::MICROPHONE, // MICROPHONE
86
MixDevice::EXTERNAL, // LINE_IN
91
// Mapping from device numbers to Sun port mask values
93
const uint_t MixerSunPortMasks[] =
95
0, // MASTER_VOLUME - no associated port
99
0, // RECORD_MONITOR - no associated port
106
//======================================================================
107
// FUNCTION/METHOD DEFINITIONS
108
//======================================================================
111
//======================================================================
112
// FUNCTION : SUN_getMixer
113
// DESCRIPTION : Creates and returns a new mixer object.
114
//======================================================================
115
Mixer* SUN_getMixer( int devnum, int SetNum )
118
l_mixer = new Mixer_SUN( devnum, SetNum );
119
l_mixer->setupMixer();
123
//======================================================================
124
// FUNCTION : SUN_getMixerSet
125
// DESCRIPTION : Creates and returns a new mixer object.
126
//======================================================================
127
Mixer* SUN_getMixerSet( MixSet set, int device, int card )
130
l_mixer = new Mixer_SUN( device, card );
131
l_mixer->setupMixer( set );
135
//======================================================================
136
// FUNCTION : Mixer::Mixer
137
// DESCRIPTION : Class constructor.
138
//======================================================================
139
Mixer_SUN::Mixer_SUN(int devnum, int card) : Mixer(devnum, card)
147
//======================================================================
148
// FUNCTION : Mixer::openMixer
149
// DESCRIPTION : Initialize the mixer and open the hardware driver.
150
//======================================================================
151
int Mixer_SUN::openMixer()
154
// We don't support multiple cards or devices
156
if ( m_cardnum != 0 )
157
return Mixer::ERR_OPEN;
159
return Mixer::ERR_OPEN;
162
// Release mixer before (re-)opening
167
// Open the mixer hardware driver
169
if ( ( fd = open( "/dev/audioctl", O_RDWR ) ) < 0 )
171
if ( errno == EACCES )
172
return Mixer::ERR_PERM;
174
return Mixer::ERR_OPEN;
179
// Mixer is open. Now define all of the mix devices.
182
if( m_mixDevices.isEmpty() )
184
for ( int idx = 0; idx < numDevs; idx++ )
186
Volume vol( 2, AUDIO_MAX_GAIN );
187
readVolumeFromHW( idx, vol );
188
MixDevice* md = new MixDevice( idx, vol, 0,
189
QString(MixerDevNames[idx]), MixerChannelTypes[idx]);
190
md->setRecsrc( isRecsrcHW( idx ) );
191
m_mixDevices.append( md );
196
for( unsigned int idx = 0; idx < m_mixDevices.count(); idx++ )
198
MixDevice* md = m_mixDevices.at( idx );
200
return ERR_INCOMPATIBLESET;
201
writeVolumeToHW( idx, md->getVolume() );
205
m_mixerName = "SUN Audio Mixer";
212
//======================================================================
213
// FUNCTION : Mixer::releaseMixer
214
// DESCRIPTION : Close the hardware driver.
215
//======================================================================
216
int Mixer_SUN::releaseMixer()
218
int l_i_ret = ::close( fd );
222
//======================================================================
223
// FUNCTION : Mixer::errorText
224
// DESCRIPTION : Convert an error code enum to a text string.
225
//======================================================================
226
QString Mixer_SUN::errorText( int mixer_error )
233
"kmix: You do not have permission to access the mixer device.\n"
234
"Ask your system administrator to fix /dev/audioctl to allow access."
238
errmsg = Mixer::errorText( mixer_error );
244
//======================================================================
245
// FUNCTION : Mixer::readVolumeFrmoHW
246
// DESCRIPTION : Read the audio information from the driver.
247
//======================================================================
248
int Mixer_SUN::readVolumeFromHW( int devnum, Volume& volume )
250
audio_info_t audioinfo;
251
uint_t devMask = MixerSunPortMasks[devnum];
254
// Read the current audio information from the driver
256
if ( ioctl( fd, AUDIO_GETINFO, &audioinfo ) < 0 )
258
return( Mixer::ERR_READ );
263
// Extract the appropriate fields based on the requested device
267
case MIXERDEV_MASTER_VOLUME :
268
volume.setMuted( audioinfo.output_muted );
269
GainBalanceToVolume( audioinfo.play.gain,
270
audioinfo.play.balance,
274
case MIXERDEV_RECORD_MONITOR :
275
volume.setMuted(FALSE);
276
volume.setAllVolumes( audioinfo.monitor_gain );
279
case MIXERDEV_INTERNAL_SPEAKER :
280
case MIXERDEV_HEADPHONE :
281
case MIXERDEV_LINE_OUT :
282
volume.setMuted( (audioinfo.play.port & devMask) ? FALSE : TRUE );
283
GainBalanceToVolume( audioinfo.play.gain,
284
audioinfo.play.balance,
288
case MIXERDEV_MICROPHONE :
289
case MIXERDEV_LINE_IN :
291
volume.setMuted( (audioinfo.record.port & devMask) ? FALSE : TRUE );
292
GainBalanceToVolume( audioinfo.record.gain,
293
audioinfo.record.balance,
298
return Mixer::ERR_NODEV;
304
//======================================================================
305
// FUNCTION : Mixer::writeVolumeToHW
306
// DESCRIPTION : Write the specified audio settings to the hardware.
307
//======================================================================
308
int Mixer_SUN::writeVolumeToHW( int devnum, Volume volume )
315
// Convert the Volume(left vol, right vol) to the Gain/Balance Sun uses
317
VolumeToGainBalance( volume, gain, balance );
318
mute = volume.isMuted() ? 1 : 0;
321
// Read the current audio settings from the hardware
323
audio_info_t audioinfo;
324
if ( ioctl( fd, AUDIO_GETINFO, &audioinfo ) < 0 )
326
return( Mixer::ERR_READ );
330
// Now, based on the devnum that we are writing to, update the appropriate
331
// volume field and twiddle the appropriate bitmask to enable/mute the
332
// device as necessary.
336
case MIXERDEV_MASTER_VOLUME :
337
audioinfo.play.gain = gain;
338
audioinfo.play.balance = balance;
339
audioinfo.output_muted = mute;
342
case MIXERDEV_RECORD_MONITOR :
343
audioinfo.monitor_gain = gain;
344
// no mute or balance for record monitor
347
case MIXERDEV_INTERNAL_SPEAKER :
348
case MIXERDEV_HEADPHONE :
349
case MIXERDEV_LINE_OUT :
350
audioinfo.play.gain = gain;
351
audioinfo.play.balance = balance;
353
audioinfo.play.port &= ~MixerSunPortMasks[devnum];
355
audioinfo.play.port |= MixerSunPortMasks[devnum];
358
case MIXERDEV_MICROPHONE :
359
case MIXERDEV_LINE_IN :
361
audioinfo.record.gain = gain;
362
audioinfo.record.balance = balance;
364
audioinfo.record.port &= ~MixerSunPortMasks[devnum];
366
audioinfo.record.port |= MixerSunPortMasks[devnum];
370
return Mixer::ERR_NODEV;
374
// Now that we've updated the audioinfo struct, write it back to the hardware
376
if ( ioctl( fd, AUDIO_SETINFO, &audioinfo ) < 0 )
378
return( Mixer::ERR_WRITE );
386
//======================================================================
387
// FUNCTION : Mixer::setRecsrcHW
389
//======================================================================
390
bool Mixer_SUN::setRecsrcHW( int /* devnum */, bool /* on */ )
395
//======================================================================
396
// FUNCTION : Mixer::isRecsrcHW
397
// DESCRIPTION : Returns true if the specified device is a record source.
398
//======================================================================
399
bool Mixer_SUN::isRecsrcHW( int devnum )
403
case MIXERDEV_MICROPHONE :
404
case MIXERDEV_LINE_IN :
413
//======================================================================
414
// FUNCTION : Mixer::VolumeToGainBalance
415
// DESCRIPTION : Converts a Volume(left vol + right vol) into the
416
// Gain/Balance values used by Sun.
417
//======================================================================
418
void Mixer_SUN::VolumeToGainBalance( Volume& volume, uint_t& gain, uchar_t& balance )
420
if ( ( volume.channels() == 1 ) ||
421
( volume[Volume::LEFT] == volume[Volume::RIGHT] ) )
423
gain = volume[Volume::LEFT];
424
balance = AUDIO_MID_BALANCE;
428
if ( volume[Volume::LEFT] > volume[Volume::RIGHT] )
430
gain = volume[Volume::LEFT];
431
balance = AUDIO_LEFT_BALANCE +
432
( AUDIO_MID_BALANCE - AUDIO_LEFT_BALANCE ) *
433
volume[Volume::RIGHT] / volume[Volume::LEFT];
437
gain = volume[Volume::RIGHT];
438
balance = AUDIO_RIGHT_BALANCE -
439
( AUDIO_RIGHT_BALANCE - AUDIO_MID_BALANCE ) *
440
volume[Volume::LEFT] / volume[Volume::RIGHT];
445
//======================================================================
446
// FUNCTION : Mixer::GainBalanceToVolume
447
// DESCRIPTION : Converts Gain/Balance returned by Sun driver to the
448
// Volume(left vol + right vol) format used by kmix.
449
//======================================================================
450
void Mixer_SUN::GainBalanceToVolume( uint_t& gain, uchar_t& balance, Volume& volume )
452
if ( volume.channels() == 1 )
454
volume.setVolume( Volume::LEFT, gain );
458
if ( balance <= AUDIO_MID_BALANCE )
460
volume.setVolume( Volume::LEFT, gain );
461
volume.setVolume( Volume::RIGHT, gain *
462
( balance - AUDIO_LEFT_BALANCE ) /
463
( AUDIO_MID_BALANCE - AUDIO_LEFT_BALANCE ) );
467
volume.setVolume( Volume::RIGHT, gain );
468
volume.setVolume( Volume::LEFT, gain *
469
( AUDIO_RIGHT_BALANCE - balance ) /
470
( AUDIO_RIGHT_BALANCE - AUDIO_MID_BALANCE ) );