~ubuntu-branches/ubuntu/hoary/kdemultimedia/hoary

« back to all changes in this revision

Viewing changes to kmix/mixer_oss.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Martin Schulze
  • Date: 2003-01-22 15:00:51 UTC
  • Revision ID: james.westby@ubuntu.com-20030122150051-uihwkdoxf15mi1tn
Tags: upstream-2.2.2
ImportĀ upstreamĀ versionĀ 2.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *              KMix -- KDE's full featured mini mixer
 
3
 *
 
4
 *
 
5
 *              Copyright (C) 1996-2000 Christian Esken
 
6
 *                        esken@kde.org
 
7
 *
 
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.
 
12
 *
 
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.
 
17
 *
 
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.
 
21
 */
 
22
 
 
23
#include <fcntl.h>
 
24
#include <errno.h>
 
25
#include <unistd.h>
 
26
#include <sys/ioctl.h>
 
27
#include <sys/types.h>
 
28
#include <sys/stat.h>
 
29
 
 
30
// Linux section, by Christian Esken
 
31
#if defined(__linux__)
 
32
#include <sys/soundcard.h>
 
33
// FreeBSD section, according to Sebestyen Zoltan
 
34
#elif defined(__FreeBSD__)
 
35
#include "machine/soundcard.h"
 
36
// NetBSD section, according to  Lennart Augustsson <augustss@cs.chalmers.se>
 
37
#elif defined(__NetBSD__)
 
38
#include <soundcard.h>
 
39
// BSDI section, according to <tom@foo.toetag.com>
 
40
#elif defined(__bsdi__)
 
41
#include <sys/soundcard.h>
 
42
// UnixWare includes
 
43
#elif defined(_UNIXWARE)
 
44
#include <sys/soundcard.h>
 
45
#endif
 
46
 
 
47
#include "mixer_oss.h"
 
48
#include <klocale.h>
 
49
 
 
50
 
 
51
const char* MixerDevNames[32]={
 
52
    I18N_NOOP("Volume"), I18N_NOOP("Bass"), I18N_NOOP("Treble"),
 
53
    I18N_NOOP("Synth"), I18N_NOOP("Pcm"), I18N_NOOP("Speaker"),
 
54
    I18N_NOOP("Line"), I18N_NOOP("Microphone"), I18N_NOOP("CD"),
 
55
    I18N_NOOP("Mix"), I18N_NOOP("Pcm2"), I18N_NOOP("RecMon"),
 
56
    I18N_NOOP("IGain"), I18N_NOOP("OGain"), I18N_NOOP("Line1"),
 
57
    I18N_NOOP("Line2"), I18N_NOOP("Line3"), I18N_NOOP("Digital1"),
 
58
    I18N_NOOP("Digital2"), I18N_NOOP("Digital3"), I18N_NOOP("PhoneIn"),
 
59
    I18N_NOOP("PhoneOut"), I18N_NOOP("Video"), I18N_NOOP("Radio"),
 
60
    I18N_NOOP("Monitor"), I18N_NOOP("3D-depth"), I18N_NOOP("3D-center"),
 
61
    I18N_NOOP("unknown"), I18N_NOOP("unknown"), I18N_NOOP("unknown"),
 
62
    I18N_NOOP("unknown") , I18N_NOOP("unused") };
 
63
 
 
64
const MixDevice::ChannelType MixerChannelTypes[32] = {
 
65
  MixDevice::VOLUME,   MixDevice::BASS,       MixDevice::TREBLE,   MixDevice::MIDI,
 
66
  MixDevice::AUDIO,    MixDevice::EXTERNAL,   MixDevice::EXTERNAL, MixDevice::MICROPHONE,
 
67
  MixDevice::CD,       MixDevice::VOLUME,     MixDevice::AUDIO,    MixDevice::RECMONITOR,
 
68
  MixDevice::VOLUME,   MixDevice::RECMONITOR, MixDevice::EXTERNAL, MixDevice::EXTERNAL,
 
69
  MixDevice::EXTERNAL, MixDevice::AUDIO,      MixDevice::AUDIO,    MixDevice::AUDIO,
 
70
  MixDevice::EXTERNAL, MixDevice::EXTERNAL,   MixDevice::EXTERNAL, MixDevice::EXTERNAL,
 
71
  MixDevice::EXTERNAL, MixDevice::VOLUME,     MixDevice::VOLUME,   MixDevice::UNKNOWN,
 
72
  MixDevice::UNKNOWN,  MixDevice::UNKNOWN,    MixDevice::UNKNOWN,  MixDevice::UNKNOWN };
 
73
 
 
74
Mixer* OSS_getMixer( int device, int card )
 
75
{
 
76
  Mixer *l_mixer;
 
77
  l_mixer = new Mixer_OSS( device, card );
 
78
  l_mixer->setupMixer();
 
79
  return l_mixer;
 
80
}
 
81
 
 
82
Mixer* OSS_getMixerSet( MixSet set, int device, int card )
 
83
{
 
84
  Mixer *l_mixer;
 
85
  l_mixer = new Mixer_OSS( device, card );
 
86
  l_mixer->setupMixer( set );
 
87
  return l_mixer;
 
88
}
 
89
 
 
90
 
 
91
Mixer_OSS::Mixer_OSS(int device, int card) : Mixer(device, card)
 
92
{
 
93
  if( device == -1 ) m_devnum = 0;
 
94
  if( card   == -1 ) m_cardnum = 0;
 
95
}
 
96
 
 
97
int Mixer_OSS::openMixer()
 
98
{
 
99
    if ( m_cardnum!=0 ) return Mixer::ERR_OPEN; // OSS doesn't support different card numbers
 
100
  release();            // To be sure, release mixer before (re-)opening
 
101
 
 
102
  if ((m_fd= ::open( deviceName( m_devnum ).latin1(), O_RDWR)) < 0)
 
103
    {
 
104
      if ( errno == EACCES )
 
105
        return Mixer::ERR_PERM;
 
106
      else
 
107
        return Mixer::ERR_OPEN;
 
108
    }
 
109
  else
 
110
    {
 
111
      int devmask, recmask, i_recsrc, stereodevs;
 
112
      // Mixer is open. Now define properties
 
113
      if (ioctl(m_fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
 
114
        return Mixer::ERR_READ;
 
115
      if (ioctl(m_fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
 
116
        return Mixer::ERR_READ;
 
117
      if (ioctl(m_fd, SOUND_MIXER_READ_RECSRC, &i_recsrc) == -1)
 
118
        return Mixer::ERR_READ;
 
119
      if (ioctl(m_fd, SOUND_MIXER_READ_STEREODEVS, &stereodevs) == -1)
 
120
        return Mixer::ERR_READ;
 
121
      if (!devmask)
 
122
        return Mixer::ERR_NODEV;
 
123
      int maxVolume =100;
 
124
 
 
125
      if( m_mixDevices.isEmpty() )
 
126
        {
 
127
          int idx = 0;
 
128
          while( devmask && idx < MAX_MIXDEVS )
 
129
            {
 
130
              if( devmask & ( 1 << idx ) ) // device active?
 
131
                {
 
132
                  Volume vol( stereodevs & ( 1 << idx ) ? 2 : 1, maxVolume);
 
133
                  readVolumeFromHW( idx, vol );
 
134
                  MixDevice* md =
 
135
                    new MixDevice( idx, vol, recmask & ( 1 << idx ),
 
136
                                   QString(MixerDevNames[idx]),
 
137
                                   MixerChannelTypes[idx]);
 
138
                  md->setRecsrc( isRecsrcHW( idx ) );
 
139
                  m_mixDevices.append( md );
 
140
                }
 
141
              idx++;
 
142
            }
 
143
        }
 
144
      else
 
145
        for( unsigned int idx = 0; idx < m_mixDevices.count(); idx++ )
 
146
          {
 
147
            MixDevice* md = m_mixDevices.at( idx );
 
148
            if( !md )
 
149
              return ERR_INCOMPATIBLESET;
 
150
            writeVolumeToHW( idx, md->getVolume() );
 
151
          }
 
152
 
 
153
#if !defined(__FreeBSD__)
 
154
      struct mixer_info l_mix_info;
 
155
      if (ioctl(m_fd, SOUND_MIXER_INFO, &l_mix_info) != -1)
 
156
        {
 
157
          m_mixerName = l_mix_info.name;
 
158
        }
 
159
      else
 
160
#endif
 
161
 
 
162
        m_mixerName = "OSS Audio Mixer";
 
163
 
 
164
      m_isOpen = true;
 
165
      return 0;
 
166
    }
 
167
}
 
168
 
 
169
int Mixer_OSS::releaseMixer()
 
170
{
 
171
  int l_i_ret = ::close(m_fd);
 
172
  return l_i_ret;
 
173
}
 
174
 
 
175
 
 
176
QString Mixer_OSS::deviceName(int devnum)
 
177
{
 
178
  switch (devnum) {
 
179
  case 0:
 
180
    return QString("/dev/mixer");
 
181
    break;
 
182
 
 
183
  default:
 
184
    QString devname("/dev/mixer");
 
185
    devname += ('0'+devnum);
 
186
    return devname;
 
187
  }
 
188
}
 
189
 
 
190
QString Mixer_OSS::errorText(int mixer_error)
 
191
{
 
192
  QString l_s_errmsg;
 
193
  switch (mixer_error)
 
194
    {
 
195
    case ERR_PERM:
 
196
      l_s_errmsg = i18n("kmix: You do not have permission to access the mixer device.\n" \
 
197
                        "Login as root and do a 'chmod a+rw /dev/mixer*' to allow the access.");
 
198
      break;
 
199
    case ERR_OPEN:
 
200
      l_s_errmsg = i18n("kmix: Mixer cannot be found.\n" \
 
201
                        "Please check that the soundcard is installed and the\n" \
 
202
                        "soundcard driver is loaded.\n" \
 
203
                        "On Linux you might need to use 'insmod' to load the driver.\n" \
 
204
                        "Use 'soundon' when using commercial OSS.");
 
205
      break;
 
206
    default:
 
207
      l_s_errmsg = Mixer::errorText(mixer_error);
 
208
    }
 
209
  return l_s_errmsg;
 
210
}
 
211
 
 
212
 
 
213
bool Mixer_OSS::setRecsrcHW( int devnum, bool on )
 
214
{
 
215
  int i_recsrc, oldrecsrc;
 
216
  if (ioctl(m_fd, SOUND_MIXER_READ_RECSRC, &i_recsrc) == -1)
 
217
    errormsg(Mixer::ERR_READ);
 
218
 
 
219
  oldrecsrc = i_recsrc = on ?
 
220
             (i_recsrc | (1 << devnum )) :
 
221
             (i_recsrc & ~(1 << devnum ));
 
222
 
 
223
  // Change status of record source(s)
 
224
  if (ioctl(m_fd, SOUND_MIXER_WRITE_RECSRC, &i_recsrc) == -1)
 
225
    errormsg (Mixer::ERR_WRITE);
 
226
  // Re-read status of record source(s). Just in case, OSS does not like
 
227
  // my settings. And with this line mix->recsrc gets its new value. :-)
 
228
  if (ioctl(m_fd, SOUND_MIXER_READ_RECSRC, &i_recsrc) == -1)
 
229
    errormsg(Mixer::ERR_READ);
 
230
 
 
231
  // PORTING: Hint: Do not forget to set i_recsrc to the new valid
 
232
  //                record source mask.
 
233
 
 
234
  return i_recsrc == oldrecsrc;
 
235
}
 
236
 
 
237
bool Mixer_OSS::isRecsrcHW( int devnum )
 
238
{
 
239
  int i_recsrc;
 
240
  if (ioctl(m_fd, SOUND_MIXER_READ_RECSRC, &i_recsrc) == -1)
 
241
    errormsg(Mixer::ERR_READ);
 
242
 
 
243
  return i_recsrc & (1 << devnum );
 
244
}
 
245
 
 
246
 
 
247
int Mixer_OSS::readVolumeFromHW( int devnum, Volume &vol )
 
248
{
 
249
  if( vol.isMuted() ) return 0; // Don't alter volume when muted
 
250
 
 
251
  int volume;
 
252
  if (ioctl(m_fd, MIXER_READ( devnum ), &volume) == -1)
 
253
    {
 
254
      /* Oops, can't read mixer */
 
255
      return(Mixer::ERR_READ);
 
256
    }
 
257
  else
 
258
    {
 
259
      vol.setVolume( Volume::LEFT, (volume & 0x7f));
 
260
      if( vol.channels() > 1 )
 
261
        vol.setVolume( Volume::RIGHT, ((volume>>8) & 0x7f));
 
262
      return 0;
 
263
    }
 
264
}
 
265
 
 
266
 
 
267
 
 
268
int Mixer_OSS::writeVolumeToHW( int devnum, Volume vol )
 
269
{
 
270
  int volume;
 
271
  if( vol.isMuted() ) volume = 0;
 
272
  else
 
273
    if ( vol.channels() > 1 )
 
274
      volume = vol[ Volume::LEFT ] + ((vol[ Volume::RIGHT ])<<8);
 
275
    else
 
276
      volume = vol[ Volume::LEFT ];
 
277
 
 
278
  if (ioctl(m_fd, MIXER_WRITE( devnum ), &volume) == -1)
 
279
    return Mixer::ERR_WRITE;
 
280
 
 
281
  return 0;
 
282
}