00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "osoundsystem.h"
00031 using namespace Opie::MM;
00032
00033
00034 #include <opie2/odebug.h>
00035 using namespace Opie::Core;
00036
00037
00038 #include <errno.h>
00039 #include <fcntl.h>
00040 #include <string.h>
00041 #include <sys/ioctl.h>
00042 #include <sys/types.h>
00043 #include <sys/soundcard.h>
00044 #include <sys/stat.h>
00045
00046 static const char* device_label[] = SOUND_DEVICE_LABELS;
00047 static int max_device_nr = sizeof device_label / sizeof (const char*);
00048
00049
00050
00051
00052
00053 OSoundSystem* OSoundSystem::_instance = 0;
00054
00055 OSoundSystem::OSoundSystem()
00056 {
00057 odebug << "OSoundSystem::OSoundSystem()" << oendl;
00058 synchronize();
00059 }
00060
00061 void OSoundSystem::synchronize()
00062 {
00063 _interfaces.clear();
00064 _interfaces.insert( "soundcard", new OSoundCard( this, "soundcard" ) );
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 }
00092
00093
00094 int OSoundSystem::count() const
00095 {
00096 return _interfaces.count();
00097 }
00098
00099
00100 OSoundCard* OSoundSystem::card( const QString& iface ) const
00101 {
00102 return _interfaces[iface];
00103 }
00104
00105
00106 OSoundSystem* OSoundSystem::instance()
00107 {
00108 if ( !_instance ) _instance = new OSoundSystem();
00109 return _instance;
00110 }
00111
00112
00113 OSoundSystem::CardIterator OSoundSystem::iterator() const
00114 {
00115 return OSoundSystem::CardIterator( _interfaces );
00116 }
00117
00118
00119
00120
00121
00122
00123 OSoundCard::OSoundCard( QObject* parent, const char* name )
00124 :QObject( parent, name ), _audio( 0 ), _mixer( 0 )
00125 {
00126 odebug << "OSoundCard::OSoundCard()" << oendl;
00127 init();
00128 }
00129
00130
00131 OSoundCard::~OSoundCard()
00132 {
00133 }
00134
00135
00136 void OSoundCard::init()
00137 {
00138 #ifdef QT_QWS_DEVFS
00139 _audio = new OAudioInterface( this, "/dev/sound/dsp" );
00140 _mixer = new OMixerInterface( this, "/dev/sound/mixer" );
00141 #else
00142 _audio = new OAudioInterface( this, "/dev/dsp" );
00143 _mixer = new OMixerInterface( this, "/dev/mixer" );
00144 #endif
00145 }
00146
00147
00148
00149
00150
00151
00152 OAudioInterface::OAudioInterface( QObject* parent, const char* name )
00153 :QObject( parent, name ), _sfd(0)
00154 {
00155 odebug << "OAudioInterface::OAudioInterface()" << oendl;
00156 init();
00157 }
00158
00159
00160 OAudioInterface::~OAudioInterface()
00161 {
00162 }
00163
00164
00165 void OAudioInterface::init()
00166 {
00167
00168
00169 }
00170
00171
00172
00173
00174
00175
00176 OMixerInterface::OMixerInterface( QObject* parent, const char* name )
00177 :QObject( parent, name ), _devmask( 0 ), _recmask( 0 ), _stmask( 0 )
00178 {
00179 odebug << "OMixerInterface::OMixerInterface()" << oendl;
00180 init();
00181 }
00182
00183
00184 OMixerInterface::~OMixerInterface()
00185 {
00186 }
00187
00188
00189 void OMixerInterface::init()
00190 {
00191
00192 _fd = ::open( name(), O_RDWR );
00193 if ( _fd == -1 )
00194 {
00195 owarn << "OMixerInterface::init(): Can't open mixer " << name() << oendl;
00196 return;
00197 }
00198
00199
00200 if ( ioctl( _fd, SOUND_MIXER_READ_CAPS, &_capmask ) != -1 )
00201 {
00202 odebug << "OMixerInterface::init() - capmask = " << _capmask << oendl;
00203 }
00204 if ( ioctl( _fd, SOUND_MIXER_READ_DEVMASK, &_devmask ) != -1 )
00205 {
00206 odebug << "OMixerInterface::init() - devmask = " << _devmask << oendl;
00207 }
00208 if ( ioctl( _fd, SOUND_MIXER_READ_RECMASK, &_recmask ) != -1 )
00209 {
00210 odebug << "OMixerInterface::init() - recmask = " << _recmask << oendl;
00211 }
00212 if ( ioctl( _fd, SOUND_MIXER_READ_STEREODEVS, &_stmask ) != -1 )
00213 {
00214 odebug << "OMixerInterface::init() - stereomask = " << _stmask << oendl;
00215 }
00216 for ( int i = 0; i < max_device_nr; ++i )
00217 {
00218 if ( _devmask & ( 1 << i ) )
00219 {
00220 _channels.insert( QString( device_label[i] ).stripWhiteSpace(), i );
00221 odebug << "OMixerInterface::init() - channel '" << device_label[i] << "'" << oendl;
00222 }
00223 }
00224 }
00225
00226
00227 QStringList OMixerInterface::allChannels() const
00228 {
00229 ChannelIterator it = _channels.begin();
00230 QStringList channels;
00231 while ( it != _channels.end() )
00232 {
00233 channels += it++.key();
00234 }
00235 return channels;
00236 }
00237
00238
00239 QStringList OMixerInterface::recChannels() const
00240 {
00241 ChannelIterator it = _channels.begin();
00242 QStringList channels;
00243 while ( it != _channels.end() )
00244 {
00245 if ( _recmask & ( 1 << _channels[it.key()] ) ) channels += it++.key();
00246 }
00247 return channels;
00248 }
00249
00250
00251 QStringList OMixerInterface::playChannels() const
00252 {
00253 return allChannels();
00254 }
00255
00256
00257 bool OMixerInterface::hasMultipleRecording() const
00258 {
00259 return !( _capmask & SOUND_CAP_EXCL_INPUT );
00260 }
00261
00262
00263 bool OMixerInterface::hasChannel( const QString& channel ) const
00264 {
00265 return _channels.contains( channel );
00266 }
00267
00268
00269 bool OMixerInterface::isStereo( const QString& channel ) const
00270 {
00271 return _channels.contains( channel ) && ( _stmask & ( 1 << _channels[channel] ) );
00272 }
00273
00274
00275 bool OMixerInterface::isRecordable( const QString& channel ) const
00276 {
00277 return _channels.contains( channel ) && ( _recmask & ( 1 << _channels[channel] ) );
00278 }
00279
00280
00281 void OMixerInterface::setVolume( const QString& channel, int left, int right )
00282 {
00283 int volume = left;
00284 volume |= ( right == -1 ) ? left << 8 : right << 8;
00285
00286 if ( _channels.contains( channel ) )
00287 {
00288 int result = ioctl( _fd, MIXER_WRITE( _channels[channel] ), &volume );
00289 if ( result == -1 )
00290 {
00291 owarn << "Can't set volume: " << strerror( errno ) << oendl;
00292 }
00293 else
00294 {
00295 if ( result & 0xff != left )
00296 {
00297 owarn << "Device adjusted volume from " << left << " to " << (result & 0xff) << oendl;
00298 }
00299 }
00300 }
00301 }
00302
00303
00304 int OMixerInterface::volume( const QString& channel ) const
00305 {
00306 int volume;
00307
00308 if ( _channels.contains( channel ) )
00309 {
00310 if ( ioctl( _fd, MIXER_READ( _channels[channel] ), &volume ) == -1 )
00311 {
00312 owarn << "Can't get volume: " << strerror( errno ) << oendl;
00313 }
00314 else return volume;
00315 }
00316 return -1;
00317 }