Bug 70802

Summary: artsd fails at using a modern alsa setup: pcm.default not used
Product: [Unmaintained] arts Reporter: Moritz Moeller-Herrmann <moritz-kdebugs>
Component: artsdAssignee: Stefan Westerfeld <stefan>
Status: RESOLVED FIXED    
Severity: grave CC: bitblt, jarkko.haapalainen, kde-multimedia, rdieter, sami.nieminen
Priority: NOR    
Version: 1.2   
Target Milestone: ---   
Platform: Debian testing   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Moritz Moeller-Herrmann 2003-12-19 03:48:01 UTC
Version:           KDE-3.1.93 (using KDE KDE 3.1.93)
Installed from:    Debian testing/unstable Packages
Compiler:          gcc-3.3 
OS:          Linux

artsd is at the moment unable to support alsa as provided in kernel-2.6.0 in a decent way.  
(I am using KDE-3.2b1 on linux-2.6.0-test9 with alsa-0.9.8, using an SB PCI 128 with alsa ens1371 driver)

Background: artsd is a software mixer. alsa  -- with dmix  -- now provides hardware mixing at the kernel level. It works perfectly using xmms, mplayer and alsaplayer at the same time usign alsa output in each. 


BUG EFFECT:If I use artsd with my dmixed alsa, sounds in KDE do NOT work. BTW, an error will arise if you use artsd full duplex, because the dmix plugin can of course not be read!!!!

I have now started artsd with 
#artsd -l 0 -a alsa

artsd version is 1.2.0
gsl: using Unix98 pthreads directly for mutexes and conditions
[artsd: 10008] SoundServerStartup --> got lock
ALSA driver: default
buffering: 8 fragments with 1024 bytes (audio latency is 46.4 ms)
virtualize StereoVolumeControl
ALSA driver: default
buffering: 8 fragments with 1024 bytes (audio latency is 46.4 ms)
audio format is 44100 Hz, 16 bits, 2 channels
addDirectory(/usr/lib/mcop,)
addDirectory(/usr/lib/mcop/Arts,Arts)
addDirectory(/usr/lib/mcop/Arts/Environment,Arts::Environment)
addDirectory(/usr/lib/mcop/Noatun,Noatun)
addDirectory(/home/moritz/.mcop/trader-cache,)
Arts::MidiManager registered successfully.
[artsd: 10008] SoundServerStartup <-- released lock

Now I try to artsplay something using artsplay some.mp3

UnixManager: got notifyIO
socketconnection created, fd = 10
search playobject, extension = mp3
creating MP3PlayObject to play file
outputStream created
MP3PlayObject_impl
loadMedia
MP3PlayObject_impl::getPlugin
DecoderBaseObject_impl::streamStart
play: 1

RESULT: NO SOUND!!! 

At the same time, mplayer, xmms-arts, alsaplay work perfectly and are mixed by dmix!!
Note that the default alsa device seems to be recognized, but not used for some reason
Just as a contrast the results of mplayer -ao alsa9:pcm.default some.mp3


Opening audio decoder: [mp3lib] MPEG layer-2, layer-3
MP3lib: init layer2&3 finished, tables done
AUDIO: 44100 Hz, 2 ch, 16 bit (0x10), ratio: 12000->176400 (96,0 kbit)
Selected audio codec: [mp3] afm:mp3lib (mp3lib MPEG layer-2, layer-3)
==========================================================================
Checking audio filter chain for 44100Hz/2ch/16bit -> 44100Hz/2ch/16bit...
AF_pre: af format: 2 bps, 2 ch, 44100 hz, little endian signed int 
AF_pre: 44100Hz 2ch Signed 16-bit (Little-Endian)
alsa-init: requested format: 44100 Hz, 2 channels, Signed 16-bit (Little-Endian)
alsa-init: soundcard set to pcm.default
alsa9: 44100 Hz/2 channels/4 bpf/32768 bytes buffer/Signed 16 bit Little Endian
AO: [alsa9] 44100Hz 2ch Signed 16-bit (Little-Endian) (2 bps)
Building audio filter chain for 44100Hz/2ch/16bit -> 44100Hz/2ch/16bit...
Video: no video
Starting playback...
alsa-uninit: pcm closed% 



I am using the following alsa settings in my ~/.asoundrc:
"""
pcm.ossmix {
    type dmix
    ipc_key 1024          # must be unique!
    slave {
        pcm "hw:0,0"      # you cannot use a "plug" device here, darn.
        period_time 0
        period_size 1024  # must be power of 2
        buffer_size 8192  # dito. It
        #format "S32_LE"
        #periods 128      # dito.
        #rate 8000        # with rate 8000 you *will* hear,
                          # if ossmix is used :)
    }

# bindings are cool. This says, that only the first
# two channels are to be used by dmix, which is enough for
# (most) oss apps and also lets multichannel chios work
# much faster:

    bindings {
        0 0   # from 0 => to 0
        1 1   # from 1 => to 1
    }
}

pcm.dsp0 {
    type plug
    slave.pcm "ossmix"     # use our new PCM here
}
# mixer0 like above
ctl.mixer0 {
    type hw
    card 0
}
# Everything shall be dmixed, so redefine "default":
pcm.!default {
    type plug
        slave.pcm "ossmix"
}
"""


PROPOSAL:

a) Either fix Alsa output to use the designated alsa default output device or
b) at least give a way to specify which device to use manualle (like "mplayer -ao alsa9:pcm.default")

I think this bug should really be fixed before KDE-3.2, it would look idiotic, if artsd could not use the features of linux-2.6.0.
Comment 1 Ilya Konstantinov 2003-12-26 15:04:58 UTC
I second this bug report. Apparently, aRts can use only real ALSA devices (such as hw:0,0) but not devices which work via user-space plugins (such as "dmix"). When using aRts via a dmix device (with artsd' -d argument), it's simply silent, not playing anything (but not emiting errors either).

BACKGROUND
==========

You may ask: If aRts does user-space software mixing already, why do you use "dmix" at all?
Answer: Because:
1. Pure ALSA applications can be easily made to use dmix.
2. Sometimes I prefer dmix over aRts for sake of lower latencies.
3. When a single machine runs multiple KDE desktops on different VTs, the multiple aRts servers, belonging to differnet users, will compete over the sound device. dmix allows them to share it.

P.S. Unlike what's said in the previous comment, dmix is pure user-space software mixing.
Comment 2 Sami Nieminen 2004-01-24 09:50:00 UTC
I was going to report this but fortunately found this bug report. I too would like to see artsd having support for dmix feature of ALSA. Would it be possible to have some simple passthrough feature for artsd that would pass the audio to dmix if enabled. Also a way to specify the device would be nice (you can specify it in e.g. mplayer and xmms).
Comment 3 Jeroen Versteeg 2004-01-24 12:51:02 UTC
Indeed, since it should be possible to use one linux box as a multi-user desktop system, reason (3) of comment #1 should be enough reason to fix aRts straight away.

Having a way to mix (dmix) should be used to enable multi-user mixing for as many alsa clients as possible, including artsd.
Comment 4 Stephan Kulow 2004-02-05 12:07:02 UTC
Does anyone care for arts?!
Comment 5 Stefan Gehn 2004-02-05 12:13:52 UTC
If alsa wouldn't be so crappy I guess somebody would want to fix it.
Comment 6 Allan Sandfeld 2004-02-13 17:09:32 UTC
Someone has writen a way to workaround the problem. Look at bottom of
<http://alsa.opensrc.org/index.php?page=DmixPlugin>
Comment 7 Jaroslav Kysela 2004-02-29 16:35:24 UTC
I added a new bug-report (it's my mistake of course) with a hint, how can be the current code fixed.

See http://bugs.kde.org/show_bug.cgi?id=76413

Unfortunately, it seems that arts development is somehow stopped or very slow,
so I guess we have to solve this bug ourselves, altough our capacity (ALSA team) is limited.
Comment 8 Allan Sandfeld 2004-03-19 16:05:27 UTC
CVS commit by carewolf: 

After venting my fury I calmed down and looked at the dmix-code. It seems 
it is really more borken than broken, and nothing we can't work around.

- Make aRts work with dmix. Two important changes:
  1. Dmix uses read-events to signify write-events, so we need to autodetect 
     what kind of crack ALSA is smoking today.
  2. Dmix needs to be started like a recorder even if this is contrary
     to the ALSA API documentation.

If everything works like expected I will backport and close bugs 76413 and 70802.

CCMAIL: 76413@bugs.kde.org
CCMAIL: 70802@bugs.kde.org


  M +110 -48   audioioalsa9.cc   1.6



Comment 9 Matthieu Robin 2004-03-19 18:44:42 UTC
Works for me. Thanks a lot.

However, artsd is using about 80 % of the CPU (1 GHz).
Comment 10 Allan Sandfeld 2004-03-19 18:53:31 UTC
Yes, there seems to be too many IO-events now. I am working on filtering them a bit.
Comment 11 Sami Nieminen 2004-03-20 14:49:00 UTC
I tried with the patch, but I am getting "Sound server fatal error: cpu overload, aborting" errors, and my laptop hangs for about 10 secs every time I try to play a sound.

Hardware:
P4-2800
SI7012 (intel8x0)

Software:
linux-2.6.3 (with alsa-driver 1.0.2c)
arts-1.2.1 with the patch applied
Comment 12 Allan Sandfeld 2004-03-31 23:28:28 UTC
CVS commit by carewolf: 

Avoid infinite loops when playing through DMix.

CCMAIL: 70802@bugs.kde.org


  M +45 -25    audioioalsa9.cc   1.7


--- arts/flow/audioioalsa9.cc  #1.6:1.7
@@ -72,5 +72,7 @@ protected:
         int m_period_size, m_periods;
         bool inProgress;
+        bool restartIOHandling;
 
+        void startIO();
         int poll2iomanager(int pollTypes);
         int setPcmParams(snd_pcm_t *pcm);
@@ -118,4 +120,6 @@ AudioIOALSA::AudioIOALSA()
         m_pcm_capture = NULL;
         inProgress = false;
+        restartIOHandling = false;
+        audio_read_fd = audio_write_fd = -1;
 }
 
@@ -196,14 +200,6 @@ bool AudioIOALSA::open()
                   (float)(2.0 * _samplingRate * _channels)*1000.0);
 
-        /* watch PCM file descriptor(s) */
-        Dispatcher::the()->ioManager()->remove(this, IOType::all);
-        audio_read_fd = audio_write_fd = -1;
-        if (_direction & directionWrite) {
-                audio_write_fd = watchDescriptor(m_pcm_playback);
-        }
-        if (_direction & directionRead) {
-                audio_read_fd = watchDescriptor(m_pcm_capture);
-        }
 
+        startIO();
         /* restore the format value */
         switch (m_format) {
@@ -311,4 +307,16 @@ int AudioIOALSA::getParam(AudioParam p)
 }
 
+void AudioIOALSA::startIO()
+{
+        /* watch PCM file descriptor(s) */
+        if (m_pcm_playback) {
+                audio_write_fd = watchDescriptor(m_pcm_playback);
+        }
+        if (m_pcm_capture) {
+                audio_read_fd = watchDescriptor(m_pcm_capture);
+        }
+
+}
+
 int AudioIOALSA::poll2iomanager(int pollTypes)
 {
@@ -352,5 +360,4 @@ int AudioIOALSA::xrun(snd_pcm_t *pcm)
         if ((err = snd_pcm_prepare(pcm)) < 0)
                 return err;
-        if (pcm == m_pcm_capture)
                 snd_pcm_start(pcm); // ignore error here..
         return 0;
@@ -367,5 +374,4 @@ int AudioIOALSA::resume(snd_pcm_t *pcm)
                 if ((err = snd_pcm_prepare(pcm)) < 0)
                         return err;
-                if (pcm == m_pcm_capture)
                         snd_pcm_start(pcm); // ignore error here..
         }
@@ -395,4 +401,8 @@ int AudioIOALSA::read(void *buffer, int 
 int AudioIOALSA::write(void *buffer, int size)
 {
+        // DMix has an annoying habit of returning instantantly on the returned
+        // poll-descriptor. So we block here to avoid an infinity loop.
+        while(snd_pcm_wait(m_pcm_playback, 1) == 0);
+
         int frames = snd_pcm_bytes_to_frames(m_pcm_playback, size);
         int length;
@@ -416,5 +426,13 @@ void AudioIOALSA::notifyIO(int fd, int t
     int todo = 0;
 
-    if (inProgress) return;
+        if(inProgress)
+        {
+                if(!restartIOHandling)
+                {
+                        Dispatcher::the()->ioManager()->remove(this,IOType::all);
+                        restartIOHandling = true;
+                }
+                return;
+        }
 
     // We can't trust the type as ALSA might have read-type events,
@@ -425,8 +443,10 @@ void AudioIOALSA::notifyIO(int fd, int t
     if (type & IOType::except) todo |= AudioSubSystem::ioExcept;
 
+        restartIOHandling = false;
     inProgress = true;
     AudioSubSystem::the()->handleIO(todo);
     inProgress = false;
 
+        if (restartIOHandling) startIO();
 }
 


Comment 13 Allan Sandfeld 2004-04-02 12:43:02 UTC
CVS commit by carewolf: 

Dmix seems to work this time with no adverse effects.

CCMAIL:70802-done@bugs.kde.org


  M +141 -56   audioioalsa9.cc   1.4.2.2