gen2brain / volti

Volti is GTK+ application for controlling audio volume from system tray/notification area
GNU General Public License v3.0
28 stars 8 forks source link

Volti freezes on usb e-mu tracker pre card switch #22

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. start volti in gnome-terminal
2. open preferences
3. select adio card: USB
4. volti freezes with no messages in terminal

If i kill volti and start it again, i see infinite running messages:
volti.alsactrl.__init__: can't open Master control for card USB
error: Unable to find mixer control 'Master',0

E-MU tracker pre card has no hardware mixer and DSP

In the alsamixer is only present following outputs/inputs: pcm, pcm in, clock 
rate selector

OS: Ubuntu maverick 10.10
volti 0.2.3.68 from my ppa: https://launchpad.net/~zerkalica/+archive/main

Original issue reported on code.google.com by zerkalica@gmail.com on 20 Oct 2010 at 9:57

GoogleCodeExporter commented 9 years ago
I wrote some patches:

default-mixer-tab-channels-locked.patch - now by default all stereo subchannels 
are locked,
default mixer tab now corresponds to default card_index, stored in preferences.

mixer-channel-fix.patch - bugfix, approved above, trying to select first 
available mixer channel if alsa.Mixer fails

preferences.patch - set xlib by default (hal now is deprecated), 
scale_increment: 5% (1% value is buggy, sometime while volume are changed, 
volume slider is hiding)
toggle - set to mixer (mute does not works on my card)

man-pages-lintian-fix.patch - debian/lintian fix for volume-mixer.1 man page

Original comment by zerkalica@gmail.com on 22 Oct 2010 at 4:08

Attachments:

GoogleCodeExporter commented 9 years ago
Hi, thanks for patches, I didn't have much time lately but these days I will 
take a look at your patches and some that I received earlier and merge em. 

Original comment by gen2br...@gmail.com on 23 Oct 2010 at 11:06

GoogleCodeExporter commented 9 years ago
I found one more bug with my usb card.
While entering main program loop in main.py, update method called many times 
with the same volume value.
See modifyed main.py and error log
I try to solve this bug.

/proc/asound/cards:
0 [SB             ]: HDA-Intel - HDA ATI SB
                      HDA ATI SB at 0xfe7f0000 irq 16
1 [USB            ]: USB-Audio - E-MU Tracker Pre | USB
                      E-MU Systems, Inc. E-MU Tracker Pre | USB at usb-0000:00:12.0-1, full speed

/proc/asound/devices:
 2:        : timer
  3:        : sequencer
  4: [ 1- 0]: digital audio playback
  5: [ 1- 0]: digital audio capture
  6: [ 1]   : control
  7: [ 0- 2]: digital audio capture
  8: [ 0- 1]: digital audio playback
  9: [ 0- 0]: digital audio playback
 10: [ 0- 0]: digital audio capture
 11: [ 0- 0]: hardware dependent
 12: [ 0]   : control

~/.config/volti/config:

[card-0]
control = PCM

[card-1]
control = PCM

main.py:
    def set_volume(self, volume):
        """ Set volume """
        oldvolume = int(self.scale.slider.get_value())
        sys.stderr.write("set from %s to %s\n" % (oldvolume, volume))
        traceback.print_stack()
        if volume != oldvolume:
            self.scale.slider.set_value(volume)
        else:
            sys.stderr.write("emit value_changed\n")
            self.scale.slider.emit("value_changed")

sets in config card_index = 1

$volti
set from 0 to 70
  File "/usr/bin/volti", line 52, in <module>
    volti = main.VolumeTray()
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 117, in __init__
    self.update()
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 339, in update
    self.set_volume(volume)
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 288, in set_volume
    traceback.print_stack()
set from 70 to 70
  File "/usr/bin/volti", line 53, in <module>
    volti.main()
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 402, in main
    gtk.main()
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 339, in update
    self.set_volume(volume)
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 288, in set_volume
    traceback.print_stack()
emit value_changed

set from 70 to 70
  File "/usr/bin/volti", line 53, in <module>
    volti.main()
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 402, in main
    gtk.main()
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 339, in update
    self.set_volume(volume)
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 288, in set_volume
    traceback.print_stack()
emit value_changed

..... infinite

card_index = 0
$volti
set from 0 to 75
  File "/usr/bin/volti", line 52, in <module>
    volti = main.VolumeTray()
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 117, in __init__
    self.update()
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 339, in update
    self.set_volume(volume)
  File "/usr/lib/pymodules/python2.6/volti/main.py", line 288, in set_volume
    traceback.print_stack()

Original comment by zerkalica@gmail.com on 25 Oct 2010 at 10:49

GoogleCodeExporter commented 9 years ago
What for using self.scale.slider.emit("value_changed") ?
May be better use something like that:

def set_volume(self, volume, from_slider)
...
else:
    if not from_slider
       self.scale.slider.emit("value_changed")

Original comment by zerkalica@gmail.com on 25 Oct 2010 at 10:59

GoogleCodeExporter commented 9 years ago
I found, that fd in get_descriptors in alsactrl.py changes frequently without 
volume changes for usb card

Original comment by zerkalica@gmail.com on 25 Oct 2010 at 11:48

GoogleCodeExporter commented 9 years ago
scale value_changed signal is used always, there is no need to add from_slider, 
signal is emited when volume changes, if volume is the same that means for 
example that sound in alsamixer is muted (that doesn't trigger value_changed).

Original comment by gen2br...@gmail.com on 26 Oct 2010 at 10:38

GoogleCodeExporter commented 9 years ago
I found, that fd in get_descriptors in alsactrl.py changes frequently without 
volume changes for usb card

Hmm, what do you mean by that? That could be the reason why you see so many 
update()

Original comment by gen2br...@gmail.com on 26 Oct 2010 at 10:39

GoogleCodeExporter commented 9 years ago
About your previous patches, I will commit it today, I am on work right now, 
only preferences.patch I don't like, those are your prefs, only valid change I 
see is xlib by default instead of hal, which I anyway would change some time 
but lot of distros still come with hal by default and don't have 
python-xlib-0.15rc1

Original comment by gen2br...@gmail.com on 26 Oct 2010 at 10:42

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
About frequently events changing. It's only for usb card and hard to reproduce. 
May be it's bug in alsa subsystem or pyalsa.
But alsamixer or gnome-volume is not affected by this bug.

Steps to reproduce:
1. delete ~/.config/volti/config
2. run volti and set second card in settings
3. exit from volti and run again
4. chaotically drag the volume slider many times
5. volti freezes, only kill helps
6. restart volti - freeze, bug is not dissapeared

I placed in alsactrl.py:
    def get_descriptors(self):
        """ Returns file descriptors """
        try:

            desc = self.mixer.polldescriptors()[0]

            sys.stderr.write("descriptor = %s\n\n" % str(desc))

            return desc
        except Exception, err:
            sys.stderr.write("%s.%s: %s\n" % (
                __name__, sys._getframe().f_code.co_name, str(err)))
            return None

After reproducing, I see in terminal:
$volti
set from 0 to 30
descriptor = (9, 41)

descriptor = (9, 41)
....
- this message repeats 20 times per second
....
set from 30 to 30
emit value_changed
set from 30 to 30
emit value_changed
descriptor = (9, 41)

descriptor = (9, 41)
....
- message repeats again 20 times per second
....
etc

Workaround: 
in main.py / set_volume remove self.scale.slider.emit("value_changed")
Messages flood with descriptor = (xx, xx) is not dissapeared, but volti not 
freezes and volume slider works.

Strange behaviour with events dissapears, if unload the volti and wait 10-15 
minutes or reboot

About xlib. For example, sonata mpd frontend uses own simple library for 
accessing multimedia keys, called python-mmkeys (based on xlib).
May be better use this library, it comes with many distros and old versions 
works fine.
svn://svn.berlios.de/sonata/trunk

Original comment by zerkalica@gmail.com on 26 Oct 2010 at 12:13

GoogleCodeExporter commented 9 years ago
I committed some of your patches, I didn't add mixer-channel-fix.patch because 
update() is really a bad place to write file, I don't think there is a need to 
write it there. Master is default assumption, if not, first available is 
chosen, until you open/close preferences file is not saved and you still use 
default settings. 

About fd events changing, I can't reproduce this, workaround for you is indeed 
if you don't emit value_changed but update should not be called so many times 
in the first place, when I was adding polling I did look C code for 
gnome-alsamixer and pyalsaaudio, nothing strange I saw there (but I don't code 
in C, I was just reading).

Do you by any chance still have pulseaudio in process list? When I tried 
pulseaudio I saw that it writes everwhere, /home, /tmp, /var, I wouldn't be 
surprised if it has something to do with it.
I also had problems when I wanted to add polling to mixer app, so I delayed 
this, but it is not all clear to me what happens so any help with it is 
welcomed.

About mmkeys. I know about mmkeys, but package is not available for at least 
gentoo and arch, it is rarer then python-xlib, and often comes bundled with 
software. I would not want to include code which I can't maintain. Another 
option I think is xpyb, xcb based python bindings for X, hope similar can be 
done with this library but I didn't have time to look yet.

Original comment by gen2br...@gmail.com on 26 Oct 2010 at 5:11

GoogleCodeExporter commented 9 years ago
>> Do you by any chance still have pulseaudio 
No, pulse audio removed from my system.

>>I also had problems when I wanted to add polling to mixer app

get_descriptors + gobject.io_add_watch is a bad choice for detecting side alsa 
events. The best way is use snd_mixer_set_callback (used in alsamixer, 
alsamixer-gui), but it's not implemented in pyalsa. I think, there is no clear 
solution for it in python.
gnome-alsamixer is a very old application and algorithm that it uses is not a 
good model.

On my system events this simple example start repeats infinitely after first 
event and eats cpu:
fd, eventmask = self.alsactrl.get_descriptors()
self.watchid = gobject.io_add_watch(fd, eventmask, self.update)

def self.update(self):
   sys.stderr.write("handler called\n")
   return True

If i change volume in any system mixer, io_add_watch going crazy and i see 
message flood in console. gobject.source_remove / gobject.io_add_watch and 
locks in update does not help.

I was looking your code, some moments: locks, timeouts, status updates in 
different places (menu.py:on_toggle_mute), constructors in update 
(self.alsactrl = AlsaControl) looks are not clear and needs some refactoring.

So why not to check changing alsa status in the timer, it's simple ? 
Make one timer function: update
Check changing alsa volume and mute.
if status changes:
    set lock for disabling feedback events from slider and menu controls
    set slider position and mute item.
    unset lock
    update tips and notify control
    save volume and mute state
else: renew alsa mixer handle (replace self.alsactrl = AlsaControl to 
self.alsactrl.renew_mixer_handle() )

So, this is the patch for volti-0.2.3~svn72, where i realize this algorithm and 
slightly refactor some code. It's not the final version, I still think about it.

Original comment by zerkalica@gmail.com on 28 Oct 2010 at 9:47

Attachments:

GoogleCodeExporter commented 9 years ago
Hi, sorry, didn't have much time lately, I tried patch although for now nothing 
works... I agree it needs some refactoring but wouldn't want such drastic 
changes :) (although if it works better offcourse!)

Before pyalsaaudio wrapper had poll descriptors I also used timer function, 
polling is much nicer than timer, it reacts better and instantly on changes, 
not after some seconds...

I also had this working before I released first public version with official 
alsa bindings, pyalsa from alsa-project.org, snd_mixer_set_callback is 
implemented there, but it needed new thread because of poll, as soon as 
pyalsaaudio got this function I switched (at least for pyalsaaudio you have 
some docs ;) ). 

The best would be if we can fix it for real, don't know for now what is the 
problem, is it pyalsaaudio wrapper or something else... Thanks!

Original comment by gen2br...@gmail.com on 10 Nov 2010 at 8:31

GoogleCodeExporter commented 9 years ago
I complete rewrote all code, remove multimedia keys support and control volti 
from command line (remote).
For controlling volume can be used wm multimedia keys support and amix command 
line utility from alsa-utils
In that case volti used only to indicate volume changes by side programs.

I started the separate project, volti-lite:
https://github.com/zerkalica/volti-lite

Original comment by zerkalica@gmail.com on 14 Dec 2010 at 7:30

GoogleCodeExporter commented 9 years ago
Hey, good luck with project. I am looking at changes right now, there are 
interesting stuff. A lot of users were asking for those mm keys but hey, you 
are free to do what you want. Sorry we couldn't agree, but I really don't like 
how app behave with timer... 
I sent patch to alsa-project to include poll_fds property to alsa-python so it 
can be used with gobject.io_add_watch, if they include it I plan to switch 
volti to official alsa bindings, in the beginning volti will support both 
pyalsaaudio and pyalsa but it will prefer pyalsa if installed. 

All best, 
Milan

Original comment by gen2br...@gmail.com on 20 Dec 2010 at 9:12