From 24d20c74b8e02ad7b7575ab8f577880f98e43655 Mon Sep 17 00:00:00 2001 From: mickeyl Date: Sun, 15 Jun 2003 12:47:05 +0000 Subject: just a check-in before i lose that because of my fscking harddrive... this is work-in-progress... --- (limited to 'libopie2/opiemm') diff --git a/libopie2/opiemm/.cvsignore b/libopie2/opiemm/.cvsignore new file mode 100644 index 0000000..8f7300c --- a/dev/null +++ b/libopie2/opiemm/.cvsignore @@ -0,0 +1,6 @@ +Makefile* +moc* +*moc +*.o +~* + diff --git a/libopie2/opiemm/config.in b/libopie2/opiemm/config.in new file mode 100644 index 0000000..c95d14b --- a/dev/null +++ b/libopie2/opiemm/config.in @@ -0,0 +1,7 @@ + config LIBOPIE2MM + boolean "libopie2mm (audio and video related classes)" + default "n" + depends ( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE + comment "libopie2mm needs a libqpe and libopie2core" + depends !(( LIBQPE || LIBQPE-X11 ) && LIBOPIE2CORE) + diff --git a/libopie2/opiemm/opiemm.pro b/libopie2/opiemm/opiemm.pro new file mode 100644 index 0000000..8e5eeb4 --- a/dev/null +++ b/libopie2/opiemm/opiemm.pro @@ -0,0 +1,16 @@ +TEMPLATE = lib +CONFIG += qt warn_on debug +DESTDIR = $(OPIEDIR)/lib +HEADERS = osoundsystem.h +SOURCES = osoundsystem.cpp +INTERFACES = +TARGET = opiemm2 +VERSION = 1.8.1 +INCLUDEPATH += $(OPIEDIR)/include +DEPENDPATH += $(OPIEDIR)/include +LIBS += +MOC_DIR = moc +OBJECTS_DIR = obj + +include ( $(OPIEDIR)/include.pro ) + diff --git a/libopie2/opiemm/osoundsystem.cpp b/libopie2/opiemm/osoundsystem.cpp new file mode 100644 index 0000000..fd23bea --- a/dev/null +++ b/libopie2/opiemm/osoundsystem.cpp @@ -0,0 +1,315 @@ +/* +                 This file is part of the Opie Project + +              (C) 2003 Michael 'Mickey' Lauer + =. + .=l. +           .>+-= + _;:,     .>    :=|. This program is free software; you can +.> <`_,   >  .   <= redistribute it and/or modify it under +:`=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; either version 2 of the License, +     ._= =}       : or (at your option) any later version. +    .%`+i>       _;_. +    .i_,=:_.      -`: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .`     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +    --        :-=` this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#include + +#include +#include +#include +#include +#include +#include +#include + + +/*====================================================================================== + * OSoundSystem + *======================================================================================*/ + +OSoundSystem* OSoundSystem::_instance = 0; + +OSoundSystem::OSoundSystem() +{ + qDebug( "OSoundSystem::OSoundSystem()" ); + synchronize(); +} + +void OSoundSystem::synchronize() +{ + // gather available interfaces by inspecting /dev + //FIXME: we could use SIOCGIFCONF here, but we aren't interested in virtual (e.g. eth0:0) devices + //FIXME: Use SIOCGIFCONF anway, because we can disable listing of aliased devices + + _interfaces.clear(); + _interfaces.insert( "soundcard", new OSoundCard( this, "soundcard" ) ); + + + /* + + + + + QString str; + QFile f( "/dev/sound" ); + bool hasFile = f.open( IO_ReadOnly ); + if ( !hasFile ) + { + qDebug( "OSoundSystem: /dev/sound not existing. No sound devices available" ); + return; + } + QTextStream s( &f ); + s.readLine(); + s.readLine(); + while ( !s.atEnd() ) + { + s >> str; + str.truncate( str.find( ':' ) ); + qDebug( "OSoundSystem: found interface '%s'", (const char*) str ); + OAudioInterface* iface; + iface = new OAudioInterface( this, (const char*) str ); + + _interfaces.insert( str, iface ); + s.readLine(); + } +*/ +} + + +int OSoundSystem::count() const +{ + return _interfaces.count(); +} + + +OSoundCard* OSoundSystem::card( const QString& iface ) const +{ + return _interfaces[iface]; +} + + +OSoundSystem* OSoundSystem::instance() +{ + if ( !_instance ) _instance = new OSoundSystem(); + return _instance; +} + + +OSoundSystem::CardIterator OSoundSystem::iterator() const +{ + return OSoundSystem::CardIterator( _interfaces ); +} + + +/*====================================================================================== + * OSoundCard + *======================================================================================*/ + +OSoundCard::OSoundCard( QObject* parent, const char* name ) + :QObject( parent, name ), _audio( 0 ), _mixer( 0 ) +{ + qDebug( "OSoundCard::OSoundCard()" ); + init(); +} + + +OSoundCard::~OSoundCard() +{ +} + + +void OSoundCard::init() +{ + _audio = new OAudioInterface( this, "/dev/dsp" ); + _mixer = new OMixerInterface( this, "/dev/mixer" ); +} + + +/*====================================================================================== + * OAudioInterface + *======================================================================================*/ + +OAudioInterface::OAudioInterface( QObject* parent, const char* name ) + :QObject( parent, name ) +{ + qDebug( "OAudioInterface::OAudioInterface()" ); + init(); +} + + +OAudioInterface::~OAudioInterface() +{ +} + + +void OAudioInterface::init() +{ + + +} + + +/*====================================================================================== + * OMixerInterface + *======================================================================================*/ + +OMixerInterface::OMixerInterface( QObject* parent, const char* name ) + :QObject( parent, name ) +{ + qDebug( "OMixerInterface::OMixerInterface()" ); + init(); +} + + +OMixerInterface::~OMixerInterface() +{ +} + + +void OMixerInterface::init() +{ + // open the device + _fd = ::open( name(), O_RDWR ); + if ( _fd == -1 ) + { + qWarning( "can't open mixer." ); + return; + } + + // construct the device capabilities + int devmask = 0; + if ( ioctl( _fd, SOUND_MIXER_READ_DEVMASK, &devmask ) != -1 ) + { + if ( devmask & ( 1 << SOUND_MIXER_VOLUME ) ) _channels.insert( "PlayVolume", SOUND_MIXER_VOLUME ); + if ( devmask & ( 1 << SOUND_MIXER_BASS ) ) _channels.insert( "PlayBass", SOUND_MIXER_BASS ); + if ( devmask & ( 1 << SOUND_MIXER_TREBLE ) ) _channels.insert( "PlayTreble", SOUND_MIXER_TREBLE ); + if ( devmask & ( 1 << SOUND_MIXER_SYNTH ) ) _channels.insert( "PlaySynth", SOUND_MIXER_SYNTH ); + if ( devmask & ( 1 << SOUND_MIXER_PCM ) ) _channels.insert( "PlayPCM", SOUND_MIXER_PCM ); + if ( devmask & ( 1 << SOUND_MIXER_SPEAKER ) ) _channels.insert( "PlaySpeaker", SOUND_MIXER_SPEAKER ); + if ( devmask & ( 1 << SOUND_MIXER_LINE ) ) _channels.insert( "PlayLine", SOUND_MIXER_LINE ); + if ( devmask & ( 1 << SOUND_MIXER_MIC ) ) _channels.insert( "PlayMic", SOUND_MIXER_MIC ); + if ( devmask & ( 1 << SOUND_MIXER_CD ) ) _channels.insert( "PlayCD", SOUND_MIXER_CD ); + if ( devmask & ( 1 << SOUND_MIXER_IMIX ) ) _channels.insert( "PlayInputMix", SOUND_MIXER_IMIX ); + if ( devmask & ( 1 << SOUND_MIXER_ALTPCM ) ) _channels.insert( "PlayAltPCM", SOUND_MIXER_ALTPCM ); + if ( devmask & ( 1 << SOUND_MIXER_RECLEV ) ) _channels.insert( "PlayRecord", SOUND_MIXER_RECLEV ); + if ( devmask & ( 1 << SOUND_MIXER_IGAIN ) ) _channels.insert( "PlayInputGain", SOUND_MIXER_IGAIN ); + if ( devmask & ( 1 << SOUND_MIXER_OGAIN ) ) _channels.insert( "PlayOutputGain", SOUND_MIXER_OGAIN ); + //qDebug( "devmask available and constructed." ); + } + + devmask = 0; + if ( ioctl( _fd, SOUND_MIXER_READ_RECMASK, &devmask ) != -1 ) + { + if ( devmask & ( 1 << SOUND_MIXER_VOLUME ) ) _channels.insert( "RecVolume", SOUND_MIXER_VOLUME ); + if ( devmask & ( 1 << SOUND_MIXER_BASS ) ) _channels.insert( "RecBass", SOUND_MIXER_BASS ); + if ( devmask & ( 1 << SOUND_MIXER_TREBLE ) ) _channels.insert( "RecTreble", SOUND_MIXER_TREBLE ); + if ( devmask & ( 1 << SOUND_MIXER_SYNTH ) ) _channels.insert( "RecSynth", SOUND_MIXER_SYNTH ); + if ( devmask & ( 1 << SOUND_MIXER_PCM ) ) _channels.insert( "RecPCM", SOUND_MIXER_PCM ); + if ( devmask & ( 1 << SOUND_MIXER_SPEAKER ) ) _channels.insert( "RecSpeaker", SOUND_MIXER_SPEAKER ); + if ( devmask & ( 1 << SOUND_MIXER_LINE ) ) _channels.insert( "RecLine", SOUND_MIXER_LINE ); + if ( devmask & ( 1 << SOUND_MIXER_MIC ) ) _channels.insert( "RecMic", SOUND_MIXER_MIC ); + if ( devmask & ( 1 << SOUND_MIXER_CD ) ) _channels.insert( "RecCD", SOUND_MIXER_CD ); + if ( devmask & ( 1 << SOUND_MIXER_IMIX ) ) _channels.insert( "RecInputMix", SOUND_MIXER_IMIX ); + if ( devmask & ( 1 << SOUND_MIXER_ALTPCM ) ) _channels.insert( "RecAltPCM", SOUND_MIXER_ALTPCM ); + if ( devmask & ( 1 << SOUND_MIXER_RECLEV ) ) _channels.insert( "RecRecord", SOUND_MIXER_RECLEV ); + if ( devmask & ( 1 << SOUND_MIXER_IGAIN ) ) _channels.insert( "RecInputGain", SOUND_MIXER_IGAIN ); + if ( devmask & ( 1 << SOUND_MIXER_OGAIN ) ) _channels.insert( "RecOutputGain", SOUND_MIXER_OGAIN ); + //qDebug( "recmask available and constructed." ); + } + +/* ChannelIterator it; + for ( it = _channels.begin(); it != _channels.end(); ++it ) + { + qDebug( "Channel %s available (bit %d)", (const char*) it.key(), it.data() ); + qDebug( " +--- Volume: %02d | %02d", volume( it.key() ) & 0xff, volume( it.key() ) >> 8 ); + } +*/ +} + +QStringList OMixerInterface::allChannels() const +{ + ChannelIterator it = _channels.begin(); + QStringList channels; + while ( it != _channels.end() ) + { + channels += it.key(); + it++; + } + return channels; +} + + +QStringList OMixerInterface::recChannels() const +{ + qWarning( "NYI" ); +} + + +QStringList OMixerInterface::playChannels() const +{ + qWarning( "NYI" ); +} + + +bool OMixerInterface::hasChannel( const QString& channel ) +{ + return _channels.contains( channel ); +} + + +void OMixerInterface::setVolume( const QString& channel, int left, int right ) +{ + int volume = left; + volume |= ( right == -1 ) ? left << 8 : right << 8; + + if ( _channels.contains( channel ) ) + { + int result = ioctl( _fd, MIXER_WRITE( _channels[channel] ), &volume ); + if ( result == -1 ) + { + qWarning( "Can't set volume: %s", strerror( errno ) ); + } + else + { + if ( result & 0xff != left ) + { + qWarning( "Device adjusted volume from %d to %d", left, result & 0xff ); + } + } + } +} + + +int OMixerInterface::volume( const QString& channel ) const +{ + int volume; + + if ( _channels.contains( channel ) ) + { + if ( ioctl( _fd, MIXER_READ( _channels[channel] ), &volume ) == -1 ) + { + qWarning( "Can't get volume: %s", strerror( errno ) ); + } + else return volume; + } + return -1; +} + + diff --git a/libopie2/opiemm/osoundsystem.h b/libopie2/opiemm/osoundsystem.h new file mode 100644 index 0000000..096d397 --- a/dev/null +++ b/libopie2/opiemm/osoundsystem.h @@ -0,0 +1,216 @@ +/* +                 This file is part of the Opie Project + +              (C) 2003 Michael 'Mickey' Lauer + =. + .=l. +           .>+-= + _;:,     .>    :=|. This program is free software; you can +.> <`_,   >  .   <= redistribute it and/or modify it under +:`=1 )Y*s>-.--   : the terms of the GNU Library General Public +.="- .-=="i,     .._ License as published by the Free Software + - .   .-<_>     .<> Foundation; either version 2 of the License, +     ._= =}       : or (at your option) any later version. +    .%`+i>       _;_. +    .i_,=:_.      -`: PARTICULAR PURPOSE. See the GNU +..}^=.=       =       ; Library General Public License for more +++=   -.     .`     .: details. + :     =  ...= . :.=- + -.   .:....=;==+<; You should have received a copy of the GNU +  -_. . .   )=.  = Library General Public License along with +    --        :-=` this library; see the file COPYING.LIB. + If not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + +*/ + +#ifndef OSOUNDSYSTEM_H +#define OSOUNDSYSTEM_H + +#include +#include +#include + +class OAudioInterface; +class OMixerInterface; +class OSoundCard; + +/*====================================================================================== + * OSoundSystem + *======================================================================================*/ + +/** + * @brief A container class for all audio interfaces + * + * This class provides access to all available audio/midi/sequencer interfaces of your computer. + * + * @author Michael 'Mickey' Lauer + */ +class OSoundSystem : public QObject +{ + Q_OBJECT + + public: + typedef QDict CardMap; + typedef QDictIterator CardIterator; + + public: + /** + * @returns the number of available interfaces + */ + int count() const; + /** + * @returns a pointer to the (one and only) @ref ONetwork instance. + */ + static OSoundSystem* instance(); + /** + * @returns an iterator usable for iterating through all network interfaces. + */ + CardIterator iterator() const; + /** + * @returns a pointer to the @ref OAudioInterface object for the specified @a interface or 0, if not found + * @see OAudioInterface + */ + OSoundCard* card( const QString& interface ) const; + /** + * @internal Rebuild the internal interface database + * @note Sometimes it might be useful to call this from client code, + * e.g. after issuing a cardctl insert + */ + void synchronize(); + + protected: + OSoundSystem(); + + private: + static OSoundSystem* _instance; + CardMap _interfaces; +}; + + +/*====================================================================================== + * OSoundCard + *======================================================================================*/ + +class OSoundCard : public QObject +{ + Q_OBJECT + + public: + /** + * Constructor. Normally you don't create @ref OSoundCard objects yourself, + * but access them via @ref OSoundSystem::card(). + */ + OSoundCard( QObject* parent, const char* name ); + /** + * Destructor. + */ + virtual ~OSoundCard(); + + bool hasMixer() const { return _audio; }; + bool hasAudio() const { return _mixer; }; + + OAudioInterface* audio() const { return _audio; }; + OMixerInterface* mixer() const { return _mixer; }; + + protected: + OAudioInterface* _audio; + OMixerInterface* _mixer; + + private: + void init(); +}; + +/*====================================================================================== + * OAudioInterface + *======================================================================================*/ + +class OAudioInterface : public QObject +{ + Q_OBJECT + + public: + /** + * Constructor. Normally you don't create @ref OAudioInterface objects yourself, + * but access them via the @ref OSoundCard interface. + */ + OAudioInterface( QObject* parent, const char* name ); + /** + * Destructor. + */ + virtual ~OAudioInterface(); + + protected: + const int _sfd; + + private: + void init(); +}; + + +/*====================================================================================== + * OMixerInterface + *======================================================================================*/ + +class OMixerInterface : public QObject +{ + Q_OBJECT + + public: + + typedef QMap::ConstIterator ChannelIterator; + + /** + * Constructor. Normally you don't create @ref OMixerInterface objects yourself, + * but access them via the @ref OSoundCard interface. + */ + OMixerInterface( QObject* parent, const char* name ); + /** + * Destructor. + */ + virtual ~OMixerInterface(); + + /** + * @returns all available channels. + */ + QStringList allChannels() const; + /** + * @returns recordable channels. + */ + QStringList recChannels() const; + /** + * @returns playable channels. + */ + QStringList playChannels() const; + + /** + * @returns true, if @a channel exists. + */ + bool hasChannel( const QString& channel ); + + /** + * Set the @a left and @a right volumes for @a channel. + * If no value for right is given, the value for left is taken for that. + */ + void setVolume( const QString& channel, int left, int right = -1 ); + /** + * @returns the volume of @a channel or -1, if the channel doesn't exist. + * @note You might want to use @ref hasChannel() to check if a channel exists. + */ + int volume( const QString& channel ) const; + + protected: + int _fd; + QMap _channels; + + private: + void init(); +}; + +#endif // OSOUNDSYSTEM_H + -- cgit v0.9.0.2