On Wed, 2009-04-08 at 08:42 -0700, bburde...@comcast.net wrote: > Hi all; > > With SHR-testing the phone seems to be fairly usable. Battery life is > even pretty decent. However, one thing that is a dealbreaker for me as > far as using my freerunner as my main phone is the call volume. I can > make calls just fine from my living room, but in a noisy cafe or inside > a car I can't hear very well at all. I've adjusted the volume before > from text config files, but you walk the line between usable call volume > and bad echo problems for whoever you're talking to. > > Has anyone been able to address this for themselves? This is maybe the > last major issue that keeps the FR from being my main phone. But unless > this is addressed I can't really recommend the phone to anyone but > hobbyists. > > Ben >
I wrote an application do control this. It requires python-pyalasaaudio, FSO and elementary, so should work on SHR or OM distro's. Put the elmixer.py into /usr/bin and then put volume.desktop into /usr/share/applications. The CLVL volume that Mickey talks about in his mail can be adjusted by using the Modem mixer control. The mixer tracks scenario changes so the call volume controls don't become active until a call has started. If you want to change call volumes it is best to start the application before the call starts as it takes quite a few seconds to start. Angus
volume.desktop
Description: application/desktop
#!/usr/bin/python # # copyright 2008 Angus Ainslie <angus.ains...@gmail.com> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # import alsaaudio import sys import elementary import os import dbus import e_dbus #from dbus.mainloop.glib import DBusGMainLoop class Mixers: def __init__( self ): return def GetMixers( self ) : self.mixers = [] for m in alsaaudio.mixers(): mixer = alsaaudio.Mixer( m ) self.mixers.append( mixer ) class Main: def delete_event(self, widget, event, data=None): print "delete event occurred" return False def destroy(self, widget, data=None, more=None ) : elementary.exit() def __init__(self): #DBusGMainLoop(set_as_default=True) #e_dbus.DBusEcoreMainLoop() self.bus = dbus.SystemBus( mainloop=e_dbus.DBusEcoreMainLoop() ) #usage_obj = self.bus.get_object('org.freesmartphone.ousaged', '/org/freesmartphone/Usage') #usage_iface = dbus.Interface(usage_obj, 'org.freesmartphone.Usage') gsm_obj = self.bus.get_object('org.freesmartphone.ogsmd', '/org/freesmartphone/GSM/Device') self.gsm_iface = dbus.Interface(gsm_obj, 'org.freesmartphone.GSM.Device') #device_obj = self.bus.get_object('org.freesmartphone.odeviced', '/org/freesmartphone/Device') #device_iface = dbus.Interface(device_obj, 'org.freesmartphone.Device') audio_obj = self.bus.get_object('org.freesmartphone.odeviced', '/org/freesmartphone/Device/Audio') self.audio_iface = dbus.Interface(audio_obj, 'org.freesmartphone.Device.Audio') self.audio_iface.connect_to_signal( "Scenario", self.on_scenario_status) input_obj = self.bus.get_object('org.freesmartphone.odeviced', '/org/freesmartphone/Device/Input') self.input_iface = dbus.Interface(input_obj, 'org.freesmartphone.Device.Input') self.input_iface.connect_to_signal( "Event", self.on_input_event ) info = self.audio_iface.GetInfo() print "Info", info scenario = self.audio_iface.GetScenario() print "Current Scenario", scenario elementary.init() self.window = elementary.Window("mixer", elementary.ELM_WIN_BASIC) self.window.title_set("Mixer") self.window.destroy = self.destroy self.mixers = Mixers() self.mixers.GetMixers() bg = elementary.Background(self.window) self.window.resize_object_add(bg) bg.size_hint_weight_set(1.0, 1.0) bg.show() self.main_box = elementary.Box( self.window ) self.main_box.size_hint_weight_set(1.0, 1.0) self.main_box.show() self.on_scenario_status( scenario, "startup" ) self.window.resize_object_add( self.main_box ) self.window.resize(480, 640) self.window.show() def on_input_event( self, name, action, seconds ) : print "Input event", name print "Action", action print "time", seconds # scenario = self.audio_iface.GetScenario() scenario = 'handset' if name == 'HEADSET' : if action == 'pressed' : self.on_scenario_status( scenario, 'plugged' ) elif action == 'released' : self.on_scenario_status( scenario, 'unplugged' ) def on_scenario_status( self, scenario, reason ) : #print "Scenario status change", scenario #print "reason", reason if reason != 'startup' : self.main_label.delete() self.screen_mixers.delete() self.main_label = elementary.Label(self.window) if scenario == 'gsmhandset' : print "Handset" self.screen_mixers = self.CreateHandsetControls( self.mixers.mixers ) self.main_label.label_set( '<b>Handset</b>' ) elif scenario == 'headset' : print "Headset" self.screen_mixers = self.CreateWiredHeadsetControls( self.mixers.mixers ) self.main_label.label_set( '<b>Headset</b>' ) elif scenario == 'stereoout' : print "StereoOut" self.screen_mixers = self.CreateSpeakeroutControls( self.mixers.mixers ) self.main_label.label_set( '<b>StereoOut</b>' ) elif scenario == 'btheadset' : print "BT Headset" self.screen_mixers = self.CreateBtHeadsetControls( self.mixers.mixers ) self.main_label.label_set( '<b>BT Headset<\b>' ) self.main_box.pack_start( self.main_label ) self.main_box.pack_end( self.screen_mixers ) self.main_label.show() self.main_box.show() self.window.resize_object_add( self.screen_mixers ) self.screen_mixers.show() def get_mixer_name( self, mixer_name_idx ) : parts = mixer_name_idx.partition( "-" ) return( parts[0] ) def get_mixer_idx( self, mixer_name_idx ) : parts = mixer_name_idx.partition( "-" ) if parts[2] == "" : mixer_idx = 0 else : mixer_idx = int( parts[2] ) return( mixer_idx ) def get_mixer( self, mixer_name_idx ) : mixer_name = self.get_mixer_name( mixer_name_idx ) for m in self.mixers.mixers: if mixer_name == m.mixer() : #print "Mixer ", mixer_name ,": ", m.mixer() return( m ) return( None ) def cb_volume( self, slider, event ) : # print "Volume callback", slider, event # print "Slider %s Value : %d" % ( slider.name_get(), slider.value ) if slider.name_get() == 'Modem' : self.gsm_iface.SetSpeakerVolume( int( slider.value )) else : mixer = self.get_mixer( slider.name_get() ) mixer_idx = self.get_mixer_idx( slider.name_get() ) actual_volume = self.set_volume( int( slider.value ), mixer, mixer_idx, 'Single' ) slider.value = actual_volume def set_volume( self, volume, m, idx, style = 'All' ) : # print "value changed :", volume, m.mixer(), idx volumes = m.getvolume() if( style == 'Single' ) : for i in range(len(volumes)) : m.setvolume(volume,i) else : m.setvolume(volume,idx) volumes = m.getvolume() return( volumes[idx] ) def cb_mute( self, button, m, i ) : print "event" if button.get_active() == False : muted = "on" m.setmute( 1 ) # button.set_active( False ) else : muted = "off" m.setmute( 0 ) # button.set_active( True ) print m.mixer(), "mute", muted def cb_record( self, button, m, i ) : print "event" if button.get_active() == False : rec = "on" m.setrec( 1 ) # button.set_active( False ) else : rec = "off" m.setrec( 0 ) # button.set_active( True ) print m.mixer(), "record", rec def CreateModemSlider( self ) : box0 = elementary.Box(self.window) box0.horizontal_set( True ) box0.size_hint_min_set( 200, 50 ) label = elementary.Label(self.window) label.label_set('Modem') label.size_hint_align_set(-1.0, 0) label.size_hint_weight_set(0, 1) label.scale_set(1) box0.pack_end(label) label.show() box1 = elementary.Box(self.window) box1.horizontal_set( True ) box1.pack_start( box0 ) volume = self.gsm_iface.GetSpeakerVolume() slider = elementary.Slider(self.window) slider.label_set( '' ) slider.name_set( 'Modem' ) slider.span_size_set(100) slider.size_hint_align_set(0, 0.5) slider.size_hint_weight_set(0, 1) slider.unit_format_set(" %3.0f" + ' / %d' % 100 ) slider.indicator_format_set("%3.0f") slider.min_max_set( 0, 100 ) slider.value = float( volume ) slider.scale_set(0.8) slider.on_mouse_up_add(self.cb_volume) box1.pack_end(slider) slider.show() box0.show() return box1 def CreateMixerSliders( self, m, style = 'All' ) : box0 = elementary.Box(self.window) box0.horizontal_set( True ) box0.size_hint_min_set( 200, 50 ) label = elementary.Label(self.window) label.label_set('%s' % m.mixer() ) label.size_hint_align_set(-1.0, 0) label.size_hint_weight_set(0, 1) label.scale_set(1) box0.pack_end(label) label.show() box1 = elementary.Box(self.window) box1.horizontal_set( True ) box1.pack_start( box0 ) # print "Mixer name: '%s' '%d" %( m.mixer(),m.mixerid() ) volcap = m.volumecap() switchcap = m.switchcap() # print "Capabilities", volcap + switchcap volumes = m.getvolume() if volcap and volumes : if( style == 'Single' ) : slides = 1 if( style == 'All' ) : slides = len(volumes) for i in range( slides ): # print "Channel %i volume: %i%%"%(i,volumes[i]) slider = elementary.Slider(self.window) # slider.label_set('%s' % m.mixer() ) slider.label_set( '' ) slider.name_set( m.mixer() + "-" + str( i )) slider.span_size_set(100) slider.size_hint_align_set(0, 0.5) slider.size_hint_weight_set(0, 1) slider.unit_format_set(" %3.0f" + ' / %d' % 100 ) slider.indicator_format_set("%3.0f") slider.min_max_set( 0, 100 ) slider.value = float( volumes[i] ) slider.scale_set(0.8) slider.on_mouse_up_add(self.cb_volume) box1.pack_end(slider) slider.show() else : return None box0.show() return box1 def SaveState( self, arg, stateFile ) : oldFile = '/usr/share/openmoko/scenarios/' + stateFile + '.backup' newFile = '/usr/share/openmoko/scenarios/' + stateFile try : os.rename( newFile, oldFile ) except : print 'No old file to backup' os.system( 'alsactl store 0 -f ' + newFile ) def SetState( self, arg, stateFile ) : path = '/usr/share/openmoko/scenarios/' + stateFile os.system( 'alsactl restore 0 -f ' + path ) def CreateHandsetControls( self , mixers ) : inputs = [ 'Mic2', 'Mono Sidetone', 'Mono' ] outputs = [ 'Bypass', 'Speaker', 'Modem' ] return( self.CreateMixerControls( mixers, inputs, outputs )) def CreateWiredHeadsetControls( self , mixers ) : inputs = [ 'Mic1', 'Mono Sidetone', 'Mono' ] outputs = [ 'Bypass', 'Headphone', 'Modem' ] return( self.CreateMixerControls( mixers, inputs, outputs )) def CreateSpeakeroutControls( self , mixers ) : inputs = [ 'Mic2', 'Mono Sidetone', 'Mono' ] outputs = [ 'Bypass', 'Headphone' ] return( self.CreateMixerControls( mixers, inputs, outputs )) def CreateBtHeadsetControls( self , mixers ) : inputs = [ 'Mono Voice Playback Volume', 'Mono' ] outputs = [ 'ADC', 'Modem' ] return( self.CreateMixerControls( mixers, inputs, outputs )) def CreateMixerControls( self , mixers, inputs, outputs ) : mixerBox = elementary.Box( self.window ) mixerBox.size_hint_weight_set(1.0, 1.0) mixerBox.size_hint_align_set(-1.0, -1.0) label = elementary.Label( self.window ) label.label_set('<b>Input</b>') label.size_hint_align_set(0.1, 0.5) label.scale_set(1) mixerBox.pack_start(label) label.show() for m in mixers: mixer = False id = m.mixerid() # print "Mixer ", id ,": ", m.mixer() if m.mixer() in inputs : mixerControls = self.CreateMixerSliders( m, 'Single' ) if mixerControls != None : mixerBox.pack_end( mixerControls ) mixerControls.show() label = elementary.Label( self.window ) label.label_set('<b>Output</b>') label.size_hint_align_set(0.1, 0.5) label.scale_set(1) mixerBox.pack_end(label) label.show() for m in mixers: if m.mixer() in outputs : mixerControls = self.CreateMixerSliders( m, 'Single' ) if mixerControls != None : mixerBox.pack_end( mixerControls ) mixerControls.show() if 'Modem' in outputs : mixerControls = self.CreateModemSlider() if mixerControls != None : mixerBox.pack_end( mixerControls ) mixerControls.show() #buttonBox = elementary.Box( self.window ) #buttonBox.horizontal_set( True ) #buttonBox.size_hint_weight_set(1.0, 1.0) #buttonBox.size_hint_align_set(-1.0, -1.0) #self.window.resize_object_add( buttonBox ) #button = elementary.Button( self.window ) #button.label_set('Save') #button.show() #button.clicked = self.SaveState #buttonBox.pack_start( button ) #button = elementary.Button( self.window ) #button.label_set('Restore') #button.show() #button.clicked = self.SetState #buttonBox.pack_end( button ) #buttonBox.show() #mixerBox.pack_end( buttonBox ) return( mixerBox ) def main(self): elementary.run() elementary.shutdown() run = Main() run.main()
_______________________________________________ support mailing list support@lists.openmoko.org https://lists.openmoko.org/mailman/listinfo/support