Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /* 
  2    Copyright (c) 2002 Malte Starostik <malte.starostik@t-online.de>
  3 
  4    This program is free software; you can redistribute it and/or
  5    modify it under the terms of the GNU General Public
  6    License as published by the Free Software Foundation; either
  7    version 2 of the License, or (at your option) any later version.
  8  
  9    This program is distributed in the hope that it will be useful,
 10    but WITHOUT ANY WARRANTY; without even the implied warranty of
 11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12    General Public License for more details.
 13  
 14    You should have received a copy of the GNU General Public License
 15    along with this program; see the file COPYING.  If not, write to
 16    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 17    Boston, MA 02111-1307, USA.
 18 */
 19 
 20 #include <cstring>
 21 #include <iostream>
 22 #include <vector>
 23 
 24 #include <alsa/mixer.h>
 25 
 26 extern "C"
 27 {
 28 # include "grab-ng.h"
 29 }
 30 
 31 class alsa_mixer;
 32 
 33 class attr_proxy : public ng_attribute
 34 {
 35 public:
 36         typedef int ( alsa_mixer::*accessor )();
 37         typedef void ( alsa_mixer::*mutator )( int );
 38         attr_proxy() { std::memset( this, 0, sizeof( ng_attribute ) ); }
 39         attr_proxy( int type, int id, const char* name, alsa_mixer* instance, accessor read, mutator write )
 40         {
 41                 this->id = id;
 42                 this->name = name;
 43                 this->type = type;
 44                 this->read = &read_proxy;
 45                 this->write = &write_proxy;
 46 
 47                 handle_data* d = new handle_data;
 48                 d->instance = instance;
 49                 d->read = read;
 50                 d->write = write;
 51                 this->handle = d;
 52         }
 53         attr_proxy( const attr_proxy& other )
 54         {
 55                 handle = 0;
 56                 *this = other;
 57         }
 58         attr_proxy& operator =( const attr_proxy& rhs )
 59         {
 60                 if ( &rhs != this )
 61                 {
 62                         deref();
 63                         std::memcpy( this, &rhs, sizeof( ng_attribute ) );
 64                         ref();
 65                 }
 66                 return *this;
 67         }
 68         ~attr_proxy() { deref(); }
 69 
 70 private:
 71         struct handle_data
 72         {
 73                 handle_data() : ref_count( 1 ) {}
 74 
 75                 alsa_mixer* instance;
 76                 accessor read;
 77                 mutator write;
 78                 int ref_count;
 79         };
 80 
 81         handle_data* data() const { return reinterpret_cast< handle_data* >( handle ); }
 82         void ref() { if ( data() ) data()->ref_count++; }
 83         void deref()
 84         {
 85                 if ( data() && !--data()->ref_count )
 86                 {
 87                         delete data();
 88                         handle = 0;
 89                 }
 90         }
 91 
 92         static int read_proxy( ng_attribute* attr )
 93         {
 94                 handle_data* d = reinterpret_cast< handle_data* >( attr->handle );
 95                 return ( d->instance->*d->read )();
 96         }
 97         static void write_proxy( ng_attribute* attr, int val )
 98         {
 99                 handle_data* d = reinterpret_cast< handle_data* >( attr->handle );
100                 ( d->instance->*d->write )( val );
101         }
102 };
103 
104 class alsa_mixer
105 {
106 public:
107         alsa_mixer();
108         ~alsa_mixer();
109 
110         bool init( const char* channel );
111 
112         int mute();
113         void mute( int val );
114 
115         int volume();
116         void volume( int val );
117 
118         static void* open( char* );
119         static void close( void* inst );
120 
121         static ng_devinfo* probe();
122         static ng_devinfo* channels( char* device );
123 
124         static ng_attribute* volctl( void* inst, char* channel );
125 
126 private:
127         std::vector< attr_proxy > attrs;
128         snd_mixer_t* handle;
129         snd_mixer_elem_t* elem;
130         bool muted;
131 };
132 
133 alsa_mixer::alsa_mixer()
134         : attrs( 3 )
135 {
136         snd_mixer_open( &handle, 0 );
137         snd_mixer_attach( handle, "default" );
138         snd_mixer_selem_register( handle, 0, 0 );
139         snd_mixer_load( handle );
140 
141         attrs[ 0 ] = attr_proxy( ATTR_TYPE_BOOL, ATTR_ID_MUTE, "mute",
142                                  this, &alsa_mixer::mute, &alsa_mixer::mute );
143         attrs[ 1 ] = attr_proxy( ATTR_TYPE_INTEGER, ATTR_ID_VOLUME, "volume",
144                                  this, &alsa_mixer::volume, &alsa_mixer::volume );
145 }
146 
147 alsa_mixer::~alsa_mixer()
148 {
149         if ( handle ) snd_mixer_close( handle );
150 }
151 
152 bool alsa_mixer::init( const char* channel )
153 {
154         for ( elem = snd_mixer_first_elem( handle ); elem; elem = snd_mixer_elem_next( elem ) )
155                 if ( strcasecmp( channel, snd_mixer_selem_get_name( elem ) ) == 0 )
156                 {
157                         long min, max;
158                         snd_mixer_selem_get_playback_volume_range( elem, &min, &max );
159                         attrs[ 1 ].min = min;
160                         attrs[ 1 ].max = max;
161                         return true;
162                 }
163         return false;
164 }
165 
166 int alsa_mixer::mute()
167 {
168         int left, right;
169         snd_mixer_selem_get_playback_switch( elem, SND_MIXER_SCHN_FRONT_LEFT, &left );
170         snd_mixer_selem_get_playback_switch( elem, SND_MIXER_SCHN_FRONT_RIGHT, &right );
171         return !left && !right;
172 }
173 
174 void alsa_mixer::mute( int val )
175 {
176         snd_mixer_selem_set_playback_switch( elem, SND_MIXER_SCHN_FRONT_LEFT, !val );
177         snd_mixer_selem_set_playback_switch( elem, SND_MIXER_SCHN_FRONT_RIGHT, !val );
178 }
179 
180 int alsa_mixer::volume()
181 {
182         long left, right;
183         snd_mixer_selem_get_playback_volume( elem, SND_MIXER_SCHN_FRONT_LEFT, &left );
184         snd_mixer_selem_get_playback_volume( elem, SND_MIXER_SCHN_FRONT_RIGHT, &right );
185         return ( left + right ) / 2;
186 }
187 
188 void alsa_mixer::volume( int val )
189 {
190         snd_mixer_selem_set_playback_volume( elem, SND_MIXER_SCHN_FRONT_LEFT, val );
191         snd_mixer_selem_set_playback_volume( elem, SND_MIXER_SCHN_FRONT_RIGHT, val );
192 }
193 
194 void* alsa_mixer::open( char* )
195 {
196         return new alsa_mixer();
197 }
198 
199 void alsa_mixer::close( void* inst )
200 {
201         delete reinterpret_cast< alsa_mixer* >( inst );
202 }
203 
204 ng_devinfo* alsa_mixer::probe()
205 {
206         std::cerr << "alsa_mixer::probe not implemented" << std::endl;
207         return 0;
208 }
209 
210 ng_devinfo* alsa_mixer::channels( char* device )
211 {
212         std::cerr << "alsa_mixer::channels not implemented" << std::endl;
213         return 0;
214 }
215 
216 ng_attribute* alsa_mixer::volctl( void* instance, char* channel )
217 {
218         alsa_mixer* mixer = reinterpret_cast< alsa_mixer* >( instance );
219         return mixer->init( channel ) ? &mixer->attrs[ 0 ] : 0;
220 }
221 
222 extern "C" void ng_plugin_init( void )
223 {
224         static struct ng_mix_driver mixer_info =
225         {
226             /* name */      "alsa",
227             /* probe */     alsa_mixer::probe,
228             /* channels */  alsa_mixer::channels,
229             /* open */      alsa_mixer::open,
230             /* volctl */    alsa_mixer::volctl,
231             /* close */     alsa_mixer::close,
232         };
233 
234         ng_mix_driver_register( NG_PLUGIN_MAGIC, __FILE__, &mixer_info );
235 }
236 
237 // vim: ts=4 sw=4 noet
238 
  This page was automatically generated by the LXR engine.