[Debian GNUstep maintainers] RFH: ALSA output bundle for cynthiune.app

Yavor Doganov yavor at gnu.org
Tue Feb 9 16:19:53 UTC 2010


[ CCing my local GUG, someone might have an idea what's going on. ]

Modern (Debian) kernels disable OSS support by default; this was done
in other distros long time ago.  I noticed a release goal [1] for
getting rid of apps that use /dev/dsp by default; Cynthiune is among
them.

[1] http://wiki.debian.org/ReleaseGoals/NoLinuxDevDsp

Furthermore, it is not entirely clear to me that the current
dependencies are right; I asked on mentors a few days ago [2] about
this but got no reply.

[2] http://article.gmane.org/gmane.linux.debian.devel.mentors/41523

Regardless of the current (potential and likely) dependency problem,
it is clear that an ALSA bundle is needed on the long term, to be the
default on all GNU/Linux archs.  I wrote one fairly quickly, but I
experience severe memory clobbering problems, especially at work,
where my workstation is a a dual-core Pentium IV.  It is very hard to
reproduce the crashes on an old scruffy machine such as my main
workstation at home (running gNewSense, but it shouldn't matter much;
it's hard to reproduce on my single-core Debian sid machine as well).

Initially I thought there's a severe bug in the way I use the
libasound API, but the aRts output bundle (the only one which is
threaded; OSS and Esound are not) has exactly the same problem.  I
spent more than a week in trying various approaches (using
NSLock/NSRecursiveLock in critical places, dynamic memory allocation,
copying the buffer before passing it to parentPlayer's
[readNextChunk:withSize:] (which calls the corresponding method in the
relevant format bundle), etc.  No success.

I feel there's something very fishy here, possibly fairly trivial and
fundamental, but I already feel helpless :-(

What am I doing wrong?

The patch is attached, just apply it against the patched source
cynthiune.app 0.9.5-9 source.  As the pkg-gnustep list strips
attachments, I uploaded it here [3].  For your convenience, a binary
package built with noopt and nostrip for squeeze (so that it's almost
guaranteed to work on sid) is available there [4] as well.

[3] http://www.fsa-bg.org/~yavorescu/alsa.patch
[4] http://www.fsa-bg.org/~yavorescu/cynthiune.app_0.9.5-9_i386.deb
    sha1sum: 1578db1f37f2f1fa360b6a4cb3df8f8555d12f47

-------------- next part --------------
--- cynthiune.app-0.9.5.orig/Bundles/ALSA/ALSA.h
+++ cynthiune.app-0.9.5/Bundles/ALSA/ALSA.h
@@ -0,0 +1,41 @@
+/* ALSA.h - this file is part of Cynthiune                       -*-objc-*-
+ *
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * Author: Yavor Doganov <yavor at gnu.org>
+ *
+ * Cynthiune 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 2, or (at your option)
+ * any later version.
+ *
+ * Cynthiune 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef ALSA_H
+#define ALSA_H
+
+ at interface ALSA : NSObject <CynthiuneBundle, Output>
+{
+  id parentPlayer;
+  snd_pcm_t *pcm_handle;
+
+  BOOL stopRequested;
+  
+  unsigned int channels;
+  unsigned long rate;
+
+  unsigned char buffer[DEFAULT_BUFFER_SIZE];
+}
+
+ at end
+
+#endif /* ALSA_H */
--- cynthiune.app-0.9.5.orig/Bundles/ALSA/ALSA.m
+++ cynthiune.app-0.9.5/Bundles/ALSA/ALSA.m
@@ -0,0 +1,183 @@
+/* ALSA.m - this file is part of Cynthiune
+ *
+ * Copyright (C) 2010 Free Software Foundation, Inc.
+ *
+ * Author: Yavor Doganov <yavor at gnu.org>
+ *
+ * Cynthiune 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 2, or (at your option)
+ * any later version.
+ *
+ * Cynthiune 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; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _REENTRANT
+#define _REENTRANT 1
+#endif
+
+#import <AppKit/AppKit.h>
+
+#import <Cynthiune/CynthiuneBundle.h>
+#import <Cynthiune/Output.h>
+#import <Cynthiune/utils.h>
+
+#include <alsa/asoundlib.h>
+
+#import "ALSA.h"
+
+#define LOCALIZED(X) _b ([ALSA class], X)
+
+static char *device = "default";
+
+
+ at implementation ALSA
+
++ (NSString *) bundleDescription
+{
+  return LOCALIZED (@"Output plug-in for ALSA");
+}
+
+
++ (NSArray *) bundleCopyrightStrings
+{
+  return [NSArray arrayWithObjects:
+                    LOCALIZED (@"Copyright (C) 2010 Free Software Foundation,"
+			       @" Inc."),
+                  nil];
+}
+
+
++ (BOOL) isThreaded
+{
+  return YES;
+}
+
+
+- (void) setParentPlayer: (id) aPlayer;
+{
+  parentPlayer = aPlayer;
+}
+
+
+- (id) init
+{
+  if ((self = [super init]))
+    {
+      parentPlayer = nil;
+      pcm_handle = NULL;
+      channels = 0;
+      rate = 0;
+      stopRequested = NO;
+    }
+
+  return self;
+}
+
+
+- (BOOL) openDevice
+{
+  int err;
+  BOOL result = NO;
+
+  if ((err = snd_pcm_open (&pcm_handle, device, SND_PCM_STREAM_PLAYBACK, 0))
+      < 0)
+    NSRunAlertPanel (LOCALIZED (@"Error"), LOCALIZED (@"Failed to open the "
+						      @"ALSA device:\n%s"),
+		     LOCALIZED (@"OK"), NULL, NULL, snd_strerror (err));
+  else if ((err = snd_pcm_set_params (pcm_handle, SND_PCM_FORMAT_S16,
+				      SND_PCM_ACCESS_RW_INTERLEAVED,
+				      channels, rate, 1, 5000000)) < 0)
+    NSRunAlertPanel (LOCALIZED (@"Error"), LOCALIZED (@"Failed to set device"
+						      @"parameters:\n%s"),
+		     LOCALIZED (@"OK"), NULL, NULL, snd_strerror (err));
+  else if ((err = snd_pcm_prepare (pcm_handle)) < 0)
+    NSRunAlertPanel (LOCALIZED (@"Error"), LOCALIZED (@"Failed to prepare the "
+						      @"ALSA device for "
+						      @"playing:\n%s"),
+		     LOCALIZED (@"OK"), NULL, NULL, snd_strerror (err));
+  else
+    result = YES;
+
+  return result;
+}
+
+
+- (BOOL) prepareDeviceWithChannels: (unsigned int) numberOfChannels
+                           andRate: (unsigned long) sampleRate
+{
+  channels = numberOfChannels;
+  rate = sampleRate;
+
+  return YES;
+}
+
+
+- (void) closeDevice
+{
+  while (stopRequested)
+    [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]];
+  snd_pcm_close (pcm_handle);
+}
+
+
+- (void) threadLoop
+{
+  NSAutoreleasePool *pool = [NSAutoreleasePool new];
+
+  while (!stopRequested)
+    {
+      snd_pcm_sframes_t written;
+      snd_pcm_uframes_t frames;
+      int bufferSize;
+
+      bufferSize = [parentPlayer readNextChunk: buffer
+				      withSize: DEFAULT_BUFFER_SIZE];
+
+      if (bufferSize > 0)
+	{
+	  frames = snd_pcm_bytes_to_frames (pcm_handle, bufferSize);
+	  written = snd_pcm_writei (pcm_handle, buffer, frames);
+	}
+
+      if (written < 0)
+	{
+	  NSLog (LOCALIZED (@"Failure writing to the ALSA device:\n"
+			    @"%s, trying to recover.\n"),
+		 snd_strerror (written));
+	  snd_pcm_recover (pcm_handle, written, 0);
+	}
+
+     if ([pool autoreleaseCount] > 50)
+       [pool emptyPool];
+    }
+
+  stopRequested = NO;
+  [pool release];
+}
+
+
+- (BOOL) startThread
+{
+  [NSThread detachNewThreadSelector: @selector (threadLoop)
+            toTarget: self
+            withObject: nil];
+
+  return YES;
+}
+
+
+- (void) stopThread
+{
+  stopRequested = YES;
+}
+
+ at end
--- cynthiune.app-0.9.5.orig/Bundles/ALSA/GNUmakefile
+++ cynthiune.app-0.9.5/Bundles/ALSA/GNUmakefile
@@ -0,0 +1,44 @@
+# GNUmakefile - this file is part of Cynthiune
+#
+# Copyright (C) 2010 Free Software Foundation, Inc.
+#
+# Author: Yavor Doganov <yavor at gnu.org>
+#
+# Cynthiune 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 2, or (at your option)
+# any later version.
+#
+# Cynthiune 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; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+PACKAGE_NAME = ALSA
+BUNDLE_NAME = ALSA
+BUNDLE_EXTENSION = .output
+BUNDLE_INSTALL_DIR = $(GNUSTEP_LIBRARY)/Cynthiune
+ALSA_PRINCIPAL_CLASS = ALSA
+
+ALSA_HEADERS = ALSA.h
+
+ALSA_OBJC_FILES = ALSA.m
+
+ADDITIONAL_INCLUDE_DIRS += -I../../Frameworks
+
+FRAMEWORKS_DIRS = ../../Frameworks/Cynthiune
+FRAMEWORKS = Cynthiune
+
+include ../../frameworks.make
+
+-include GNUmakefile.preamble
+-include GNUmakefile.local
+include $(GNUSTEP_MAKEFILES)/bundle.make
+-include GNUmakefile.postamble
--- cynthiune.app-0.9.5.orig/Bundles/ALSA/GNUmakefile.preamble
+++ cynthiune.app-0.9.5/Bundles/ALSA/GNUmakefile.preamble
@@ -0,0 +1,31 @@
+# GNUmakefile.preamble - this file is part of Cynthiune	   -*-makefile-gmake-*-
+#
+# Copyright (C) 2010 Free Software Foundation, Inc.
+#
+# Author: Yavor Doganov <yavor at gnu.org>
+#
+# Cynthiune 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 2, or (at your option)
+# any later version.
+#
+# Cynthiune 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; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+ALSA_CFLAGS := $(shell pkg-config --cflags alsa)
+ALSA_LIBS := $(shell pkg-config --libs alsa)
+
+ADDITIONAL_INCLUDE_DIRS += $(ALSA_CFLAGS)
+BUNDLE_LIBS += $(ALSA_LIBS)
+ADDITIONAL_OBJCFLAGS += -Wall -Wno-import
+
+ifeq ($(debug), yes)
+ADDITIONAL_LDFLAGS += -lmcheck
+endif
--- cynthiune.app-0.9.5.orig/GNUmakefile
+++ cynthiune.app-0.9.5/GNUmakefile
@@ -94,6 +94,14 @@ endif
 
 else
 
+ifeq (linux-gnu,$(GNUSTEP_TARGET_OS))
+
+ifneq (yes,$(disable-alsa))
+BUNDLES += ALSA
+endif
+
+endif
+
 ifneq (yes,$(disable-oss))
 BUNDLES += OSS
 endif


More information about the pkg-GNUstep-maintainers mailing list