sys/sunaudio/: Add a SunAudio source plugin.
authorBrian Cameron <brian.cameron@sun.com>
Tue, 20 Jun 2006 10:35:48 +0000 (10:35 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Tue, 20 Jun 2006 10:35:48 +0000 (10:35 +0000)
Original commit message from CVS:
Patch by: Brian Cameron <brian dot cameron at sun dot com>
* sys/sunaudio/Makefile.am:
* sys/sunaudio/gstsunaudio.c: (plugin_init):
* sys/sunaudio/gstsunaudiomixerctrl.c:
(gst_sunaudiomixer_ctrl_build_list), (gst_sunaudiomixer_ctrl_new),
(gst_sunaudiomixer_ctrl_list_tracks),
(gst_sunaudiomixer_ctrl_get_volume),
(gst_sunaudiomixer_ctrl_set_volume),
(gst_sunaudiomixer_ctrl_set_mute),
(gst_sunaudiomixer_ctrl_set_record):
* sys/sunaudio/gstsunaudiomixerctrl.h:
* sys/sunaudio/gstsunaudiomixertrack.c:
(gst_sunaudiomixer_track_init), (gst_sunaudiomixer_track_new):
* sys/sunaudio/gstsunaudiomixertrack.h:
* sys/sunaudio/gstsunaudiosrc.c: (gst_sunaudiosrc_dispose),
(gst_sunaudiosrc_base_init), (gst_sunaudiosrc_class_init),
(gst_sunaudiosrc_init), (gst_sunaudiosrc_set_property),
(gst_sunaudiosrc_get_property), (gst_sunaudiosrc_getcaps),
(gst_sunaudiosrc_open), (gst_sunaudiosrc_close),
(gst_sunaudiosrc_prepare), (gst_sunaudiosrc_unprepare),
(gst_sunaudiosrc_read), (gst_sunaudiosrc_delay),
(gst_sunaudiosrc_reset):
* sys/sunaudio/gstsunaudiosrc.h:
Add a SunAudio source plugin.
Support stereo and right/left channel gain in the mixer plugin.
Support the RECORD flag so that you can switch between line-input and
microphone in gnome-volume-control.
Code cleanups like using an enumerator for track number instead of an
integer. Fixes #344923.

ChangeLog
sys/sunaudio/Makefile.am
sys/sunaudio/gstsunaudio.c
sys/sunaudio/gstsunaudiomixerctrl.c
sys/sunaudio/gstsunaudiomixerctrl.h
sys/sunaudio/gstsunaudiomixertrack.c
sys/sunaudio/gstsunaudiomixertrack.h
sys/sunaudio/gstsunaudiosrc.c [new file with mode: 0644]
sys/sunaudio/gstsunaudiosrc.h [new file with mode: 0644]

index bdc1775..b74dcdd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,38 @@
 2006-06-20  Wim Taymans  <wim@fluendo.com>
 
+       Patch by: Brian Cameron <brian dot cameron at sun dot com>
+
+       * sys/sunaudio/Makefile.am:
+       * sys/sunaudio/gstsunaudio.c: (plugin_init):
+       * sys/sunaudio/gstsunaudiomixerctrl.c:
+       (gst_sunaudiomixer_ctrl_build_list), (gst_sunaudiomixer_ctrl_new),
+       (gst_sunaudiomixer_ctrl_list_tracks),
+       (gst_sunaudiomixer_ctrl_get_volume),
+       (gst_sunaudiomixer_ctrl_set_volume),
+       (gst_sunaudiomixer_ctrl_set_mute),
+       (gst_sunaudiomixer_ctrl_set_record):
+       * sys/sunaudio/gstsunaudiomixerctrl.h:
+       * sys/sunaudio/gstsunaudiomixertrack.c:
+       (gst_sunaudiomixer_track_init), (gst_sunaudiomixer_track_new):
+       * sys/sunaudio/gstsunaudiomixertrack.h:
+       * sys/sunaudio/gstsunaudiosrc.c: (gst_sunaudiosrc_dispose),
+       (gst_sunaudiosrc_base_init), (gst_sunaudiosrc_class_init),
+       (gst_sunaudiosrc_init), (gst_sunaudiosrc_set_property),
+       (gst_sunaudiosrc_get_property), (gst_sunaudiosrc_getcaps),
+       (gst_sunaudiosrc_open), (gst_sunaudiosrc_close),
+       (gst_sunaudiosrc_prepare), (gst_sunaudiosrc_unprepare),
+       (gst_sunaudiosrc_read), (gst_sunaudiosrc_delay),
+       (gst_sunaudiosrc_reset):
+       * sys/sunaudio/gstsunaudiosrc.h:
+       Add a SunAudio source plugin.
+       Support stereo and right/left channel gain in the mixer plugin.
+       Support the RECORD flag so that you can switch between line-input and
+       microphone in gnome-volume-control.
+       Code cleanups like using an enumerator for track number instead of an 
+       integer. Fixes #344923.
+
+2006-06-20  Wim Taymans  <wim@fluendo.com>
+
        Patch by: Joni Valtanen <joni dot valtanen at movial dot fi>
 
        * gst/rtsp/rtspconnection.c: (inet_aton), (rtsp_connection_send),
index 1f7e121..15bd877 100644 (file)
@@ -4,18 +4,20 @@ libgstsunaudio_la_SOURCES = gstsunaudio.c \
                             gstsunaudiosink.c \
                             gstsunaudiomixerctrl.c \
                             gstsunaudiomixer.c \
-                            gstsunaudiomixertrack.c
+                            gstsunaudiomixertrack.c \
+                            gstsunaudiosrc.c
 
 libgstsunaudio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS)
 libgstsunaudio_la_LIBADD = \
+        -lgstinterfaces-@GST_MAJORMINOR@ \
+        -lgstaudio-@GST_MAJORMINOR@ \
         $(GST_PLUGINS_BASE_LIBS) \
-        -lgstinterfaces-$(GST_MAJORMINOR) \
-        -lgstaudio-(GST_MAJORMINOR) \
         $(GST_LIBS)
 libgstsunaudio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 
 noinst_HEADERS = gstsunaudiosink.h \
                  gstsunaudiomixer.h \
                  gstsunaudiomixerctrl.h \
-                 gstsunaudiomixertrack.h
+                 gstsunaudiomixertrack.h \
+                 gstsunaudiosrc.h
 
index 9cf7f7b..bdf3371 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "gstsunaudiomixer.h"
 #include "gstsunaudiosink.h"
+#include "gstsunaudiosrc.h"
 
 extern gchar *__gst_oss_plugin_dir;
 
@@ -37,7 +38,9 @@ plugin_init (GstPlugin * plugin)
   if (!gst_element_register (plugin, "sunaudiomixer", GST_RANK_NONE,
           GST_TYPE_SUNAUDIO_MIXER) ||
       !gst_element_register (plugin, "sunaudiosink", GST_RANK_SECONDARY,
-          GST_TYPE_SUNAUDIO_SINK)) {
+          GST_TYPE_SUNAUDIO_SINK) ||
+      !gst_element_register (plugin, "sunaudiosrc", GST_RANK_SECONDARY,
+          GST_TYPE_SUNAUDIO_SRC)) {
     return FALSE;
   }
 
index c87d8d6..0346cc4 100644 (file)
@@ -66,18 +66,42 @@ void
 gst_sunaudiomixer_ctrl_build_list (GstSunAudioMixerCtrl * mixer)
 {
   GstMixerTrack *track;
-
-  g_return_if_fail (mixer->mixer_fd != -1);
+  struct audio_info audioinfo;
 
   /*
    * Do not continue appending the same 3 static tracks onto the list
    */
   if (mixer->tracklist == NULL) {
-    track = gst_sunaudiomixer_track_new (0, 1, GST_MIXER_TRACK_OUTPUT);
+    g_return_if_fail (mixer->mixer_fd != -1);
+
+    /* Output */
+    track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_OUTPUT,
+        2, GST_MIXER_TRACK_OUTPUT);
     mixer->tracklist = g_list_append (mixer->tracklist, track);
-    track = gst_sunaudiomixer_track_new (1, 1, GST_MIXER_TRACK_INPUT);
+
+    /* Input */
+    track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_LINE_IN,
+        2, GST_MIXER_TRACK_INPUT);
+
+    /* Set whether we are recording from microphone or from line-in */
+    if (ioctl (mixer->mixer_fd, AUDIO_GETINFO, &audioinfo) < 0) {
+      g_warning ("Error getting audio device volume");
+      return;
+    }
+
+    /* Set initial RECORD status */
+    if (audioinfo.record.port == AUDIO_MICROPHONE) {
+      mixer->recdevs |= (1 << GST_SUNAUDIO_TRACK_LINE_IN);
+      track->flags |= GST_MIXER_TRACK_RECORD;
+    } else {
+      mixer->recdevs &= ~(1 << GST_SUNAUDIO_TRACK_LINE_IN);
+      track->flags &= ~GST_MIXER_TRACK_RECORD;
+    }
+
+    /* Monitor */
     mixer->tracklist = g_list_append (mixer->tracklist, track);
-    track = gst_sunaudiomixer_track_new (2, 1, GST_MIXER_TRACK_OUTPUT);
+    track = gst_sunaudiomixer_track_new (GST_SUNAUDIO_TRACK_MONITOR,
+        2, GST_MIXER_TRACK_OUTPUT);
     mixer->tracklist = g_list_append (mixer->tracklist, track);
   }
 }
@@ -135,6 +159,7 @@ const GList *
 gst_sunaudiomixer_ctrl_list_tracks (GstSunAudioMixerCtrl * mixer)
 {
   gst_sunaudiomixer_ctrl_build_list (mixer);
+
   return (const GList *) mixer->tracklist;
 }
 
@@ -142,6 +167,8 @@ void
 gst_sunaudiomixer_ctrl_get_volume (GstSunAudioMixerCtrl * mixer,
     GstMixerTrack * track, gint * volumes)
 {
+  gint gain, balance;
+  float ratio;
   struct audio_info audioinfo;
   GstSunAudioMixerTrack *sunaudiotrack = GST_SUNAUDIO_MIXER_TRACK (track);
 
@@ -153,57 +180,136 @@ gst_sunaudiomixer_ctrl_get_volume (GstSunAudioMixerCtrl * mixer,
   }
 
   switch (sunaudiotrack->track_num) {
-    case 0:
-      sunaudiotrack->vol = volumes[0] =
-          (audioinfo.play.gain / SCALE_FACTOR) + 0.5;
+    case GST_SUNAUDIO_TRACK_OUTPUT:
+      gain = (int) ((float) audioinfo.play.gain / (float) SCALE_FACTOR + 0.5);
+      balance = audioinfo.play.balance;
       break;
-    case 1:
-      sunaudiotrack->vol = volumes[0] =
-          (audioinfo.record.gain / SCALE_FACTOR) + 0.5;
+    case GST_SUNAUDIO_TRACK_LINE_IN:
+      gain = (int) ((float) audioinfo.record.gain / (float) SCALE_FACTOR + 0.5);
+      balance = audioinfo.record.balance;
       break;
-    case 2:
-      sunaudiotrack->vol = volumes[0] =
-          (audioinfo.monitor_gain / SCALE_FACTOR) + 0.5;
+    case GST_SUNAUDIO_TRACK_MONITOR:
+      gain =
+          (int) ((float) audioinfo.monitor_gain / (float) SCALE_FACTOR + 0.5);
+      balance = audioinfo.record.balance;
       break;
   }
+
+  if (balance == AUDIO_MID_BALANCE) {
+    volumes[0] = gain;
+    volumes[1] = gain;
+  } else if (balance < AUDIO_MID_BALANCE) {
+    volumes[0] = gain;
+    ratio = 1 - (float) (AUDIO_MID_BALANCE - balance) /
+        (float) AUDIO_MID_BALANCE;
+    volumes[1] = (int) ((float) gain * ratio + 0.5);
+  } else {
+    volumes[1] = gain;
+    ratio = 1 - (float) (balance - AUDIO_MID_BALANCE) /
+        (float) AUDIO_MID_BALANCE;
+    volumes[0] = (int) ((float) gain * ratio + 0.5);
+  }
+
+  /*
+   * Reset whether we are recording from microphone or from line-in.
+   * This can change if another program resets the value (such as
+   * sdtaudiocontrol), so it is good to update the flag when we
+   * get the volume.  The gnome-volume-control program calls this
+   * function in a loop so the value will update properly when
+   * changed.
+   */
+  if ((audioinfo.record.port == AUDIO_MICROPHONE &&
+          !GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) ||
+      (audioinfo.record.port == AUDIO_LINE_IN &&
+          GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD))) {
+
+    if (audioinfo.record.port == AUDIO_MICROPHONE) {
+      mixer->recdevs |= (1 << GST_SUNAUDIO_TRACK_LINE_IN);
+      track->flags |= GST_MIXER_TRACK_RECORD;
+    } else {
+      mixer->recdevs &= ~(1 << GST_SUNAUDIO_TRACK_LINE_IN);
+      track->flags &= ~GST_MIXER_TRACK_RECORD;
+    }
+  }
+
+  /* Likewise reset MUTE */
+  if ((sunaudiotrack->track_num == GST_SUNAUDIO_TRACK_OUTPUT &&
+          audioinfo.output_muted == 1) ||
+      (sunaudiotrack->track_num != GST_SUNAUDIO_TRACK_OUTPUT && gain == 0)) {
+    track->flags |= GST_MIXER_TRACK_MUTE;
+  } else {
+    /*
+     * If MUTE is set, then gain is always 0, so don't bother
+     * resetting our internal value.
+     */
+    sunaudiotrack->gain = gain;
+    sunaudiotrack->balance = balance;
+    track->flags &= ~GST_MIXER_TRACK_MUTE;
+  }
 }
 
 void
 gst_sunaudiomixer_ctrl_set_volume (GstSunAudioMixerCtrl * mixer,
     GstMixerTrack * track, gint * volumes)
 {
-  gint volume;
+  gint gain;
+  gint balance;
+  gint l_real_gain;
+  gint r_real_gain;
+  float ratio;
+  gchar buf[100];
   struct audio_info audioinfo;
   GstSunAudioMixerTrack *sunaudiotrack = GST_SUNAUDIO_MIXER_TRACK (track);
+  gint temp[2];
+
+  l_real_gain = volumes[0];
+  r_real_gain = volumes[1];
+
+  if (l_real_gain == r_real_gain) {
+    gain = (int) ((float) l_real_gain * (float) SCALE_FACTOR + 0.5);
+    balance = AUDIO_MID_BALANCE;
+  } else if (l_real_gain < r_real_gain) {
+    gain = (int) ((float) r_real_gain * (float) SCALE_FACTOR + 0.5);
+    ratio = (float) l_real_gain / (float) r_real_gain;
+    balance =
+        AUDIO_RIGHT_BALANCE - (int) (ratio * (float) AUDIO_MID_BALANCE + 0.5);
+  } else {
+    gain = (int) ((float) l_real_gain * (float) SCALE_FACTOR + 0.5);
+    ratio = (float) r_real_gain / (float) l_real_gain;
+    balance =
+        AUDIO_LEFT_BALANCE + (int) (ratio * (float) AUDIO_MID_BALANCE + 0.5);
+  }
 
-  g_return_if_fail (mixer->mixer_fd != -1);
-
-  if (volume < 0)
-    volume = 0;
+  sunaudiotrack->gain = gain;
+  sunaudiotrack->balance = balance;
 
-  volume = volumes[0] * SCALE_FACTOR;
+  if (GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE))
+    return;
 
   /* Set the volume */
   AUDIO_INITINFO (&audioinfo);
 
   switch (sunaudiotrack->track_num) {
-    case 0:
-      audioinfo.play.gain = volume;
+    case GST_SUNAUDIO_TRACK_OUTPUT:
+      audioinfo.play.gain = gain;
+      audioinfo.play.balance = balance;
       break;
-    case 1:
-      audioinfo.record.gain = volume;
+    case GST_SUNAUDIO_TRACK_LINE_IN:
+      audioinfo.record.gain = gain;
+      audioinfo.record.balance = balance;
       break;
-    case 2:
-      audioinfo.monitor_gain = volume;
+    case GST_SUNAUDIO_TRACK_MONITOR:
+      audioinfo.monitor_gain = gain;
+      audioinfo.record.balance = balance;
       break;
   }
 
+  g_return_if_fail (mixer->mixer_fd != -1);
+
   if (ioctl (mixer->mixer_fd, AUDIO_SETINFO, &audioinfo) < 0) {
     g_warning ("Error setting audio device volume");
     return;
   }
-
-  sunaudiotrack->vol = volume;
 }
 
 void
@@ -212,9 +318,7 @@ gst_sunaudiomixer_ctrl_set_mute (GstSunAudioMixerCtrl * mixer,
 {
   struct audio_info audioinfo;
   GstSunAudioMixerTrack *sunaudiotrack = GST_SUNAUDIO_MIXER_TRACK (track);
-  gint volume;
-
-  g_return_if_fail (mixer->mixer_fd != -1);
+  gint volume, balance;
 
   AUDIO_INITINFO (&audioinfo);
 
@@ -222,12 +326,14 @@ gst_sunaudiomixer_ctrl_set_mute (GstSunAudioMixerCtrl * mixer,
     volume = 0;
     track->flags |= GST_MIXER_TRACK_MUTE;
   } else {
-    volume = sunaudiotrack->vol;
+    volume = sunaudiotrack->gain;
     track->flags &= ~GST_MIXER_TRACK_MUTE;
   }
 
+  balance = sunaudiotrack->balance;
+
   switch (sunaudiotrack->track_num) {
-    case 0:
+    case GST_SUNAUDIO_TRACK_OUTPUT:
 
       if (mute)
         audioinfo.output_muted = 1;
@@ -235,15 +341,20 @@ gst_sunaudiomixer_ctrl_set_mute (GstSunAudioMixerCtrl * mixer,
         audioinfo.output_muted = 0;
 
       audioinfo.play.gain = volume;
+      audioinfo.play.balance = balance;
       break;
-    case 1:
+    case GST_SUNAUDIO_TRACK_LINE_IN:
       audioinfo.record.gain = volume;
+      audioinfo.record.balance = balance;
       break;
-    case 2:
+    case GST_SUNAUDIO_TRACK_MONITOR:
       audioinfo.monitor_gain = volume;
+      audioinfo.record.balance = balance;
       break;
   }
 
+  g_return_if_fail (mixer->mixer_fd != -1);
+
   if (ioctl (mixer->mixer_fd, AUDIO_SETINFO, &audioinfo) < 0) {
     g_warning ("Error setting audio device volume");
     return;
@@ -254,5 +365,43 @@ void
 gst_sunaudiomixer_ctrl_set_record (GstSunAudioMixerCtrl * mixer,
     GstMixerTrack * track, gboolean record)
 {
-  /* Implementation Pending */
+  GstSunAudioMixerTrack *sunaudiotrack = GST_SUNAUDIO_MIXER_TRACK (track);
+  struct audio_info audioinfo;
+  GList *trk;
+
+  /* Don't change the setting */
+  if ((record && GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)) ||
+      (!record && !GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)))
+    return;
+
+  /*
+   * So there is probably no need to look for others, but reset them all
+   * to being off.
+   */
+  for (trk = mixer->tracklist; trk != NULL; trk = trk->next) {
+    GstMixerTrack *turn = (GstMixerTrack *) trk->data;
+
+    turn->flags &= ~GST_MIXER_TRACK_RECORD;
+  }
+  mixer->recdevs = 0;
+
+  /* Set the port */
+  AUDIO_INITINFO (&audioinfo);
+
+  if (record) {
+    audioinfo.record.port = AUDIO_MICROPHONE;
+    mixer->recdevs |= (1 << sunaudiotrack->track_num);
+    track->flags |= GST_MIXER_TRACK_RECORD;
+  } else {
+    audioinfo.record.port = AUDIO_LINE_IN;
+    mixer->recdevs &= ~(1 << sunaudiotrack->track_num);
+    track->flags &= ~GST_MIXER_TRACK_RECORD;
+  }
+
+  g_return_if_fail (mixer->mixer_fd != -1);
+
+  if (ioctl (mixer->mixer_fd, AUDIO_SETINFO, &audioinfo) < 0) {
+    g_warning ("Error setting audio device volume");
+    return;
+  }
 }
index 19d93ab..c4a74d9 100644 (file)
@@ -37,6 +37,7 @@ struct _GstSunAudioMixerCtrl {
   gint                  mixer_fd;
 
   gchar *               device;
+  gint                  recdevs;
 };
 
 GstSunAudioMixerCtrl* gst_sunaudiomixer_ctrl_new          (const gchar *device);
index cef59d9..87883ae 100644 (file)
 #include <string.h>
 #include <errno.h>
 #include <sys/ioctl.h>
+#include <sys/audioio.h>
 
 #include <gst/gst-i18n-plugin.h>
 
 #include "gstsunaudiomixertrack.h"
 
-#define MIXER_DEVICES 3
 #define MASK_BIT_IS_SET(mask, bit) \
   (mask & (1 << bit))
 
 G_DEFINE_TYPE (GstSunAudioMixerTrack, gst_sunaudiomixer_track,
-    GST_TYPE_MIXER_TRACK);
+    GST_TYPE_MIXER_TRACK)
 
-static void
-gst_sunaudiomixer_track_class_init (GstSunAudioMixerTrackClass * klass)
+     static void
+         gst_sunaudiomixer_track_class_init (GstSunAudioMixerTrackClass * klass)
 {
   /* nop */
 }
@@ -52,7 +52,8 @@ gst_sunaudiomixer_track_class_init (GstSunAudioMixerTrackClass * klass)
 static void
 gst_sunaudiomixer_track_init (GstSunAudioMixerTrack * track)
 {
-  track->vol = 0;
+  track->gain = 0;
+  track->balance = AUDIO_MID_BALANCE;
   track->track_num = 0;
 }
 
@@ -85,10 +86,12 @@ fill_labels (void)
 }
 
 GstMixerTrack *
-gst_sunaudiomixer_track_new (gint track_num, gint max_chans, gint flags)
+gst_sunaudiomixer_track_new (GstSunAudioTrackType track_num,
+    gint max_chans, gint flags)
 {
   GstSunAudioMixerTrack *sunaudiotrack;
   GstMixerTrack *track;
+  gint volume;
 
   if (!labels)
     fill_labels ();
@@ -101,8 +104,8 @@ gst_sunaudiomixer_track_new (gint track_num, gint max_chans, gint flags)
   track->min_volume = 0;
   track->max_volume = 100;
   sunaudiotrack->track_num = track_num;
-
-  sunaudiotrack->vol = (0 & 0xff);
+  sunaudiotrack->gain = (0 & 0xff);
+  sunaudiotrack->balance = AUDIO_MID_BALANCE;
 
   return track;
 }
index aaf1e06..42b0fa5 100644 (file)
 
 G_BEGIN_DECLS
 
+typedef enum
+{
+   GST_SUNAUDIO_TRACK_OUTPUT   = 0,
+   GST_SUNAUDIO_TRACK_LINE_IN  = 1,
+   GST_SUNAUDIO_TRACK_MONITOR  = 2,
+} GstSunAudioTrackType;
+
+#define MIXER_DEVICES 3
+
 #define GST_TYPE_SUNAUDIO_MIXER_TRACK \
   (gst_sunaudiomixer_track_get_type ())
 #define GST_SUNAUDIO_MIXER_TRACK(obj) \
@@ -43,8 +52,9 @@ G_BEGIN_DECLS
 typedef struct _GstSunAudioMixerTrack {
   GstMixerTrack parent;
 
-  gint          vol;
-  gint          track_num;
+  gint                  gain;
+  gint                  balance;
+  GstSunAudioTrackType track_num;
 } GstSunAudioMixerTrack;
 
 typedef struct _GstSunAudioMixerTrackClass {
diff --git a/sys/sunaudio/gstsunaudiosrc.c b/sys/sunaudio/gstsunaudiosrc.c
new file mode 100644 (file)
index 0000000..b014a70
--- /dev/null
@@ -0,0 +1,400 @@
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
+ *               2000,2005 Wim Taymans <wim@fluendo.com>
+ *
+ * gstsunaudiosrc.c: 
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:element-sunaudiosrc
+ *
+ * <refsect2>
+ * <para>
+ * sunaudiosrc is an audio source designed to work with the Sun Audio
+ * interface available in Solaris.
+ * </para>
+ * <title>Example launch line</title>
+ * <para>
+ * <programlisting>
+ * 
+ * gst-launch sunaudiosrc ! filesink location=outfile 
+ * </programlisting>
+ * </para>
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stropts.h>
+
+#include "gstsunaudiosrc.h"
+
+static GstElementDetails plugin_details =
+GST_ELEMENT_DETAILS ("Sun Audio Source",
+    "Source/Audio",
+    "Audio source for Sun Audio devices",
+    "Brian Cameron <brian.cameron@sun.com>");
+
+static void gst_sunaudiosrc_base_init (gpointer g_class);
+static void gst_sunaudiosrc_class_init (GstSunAudioSrcClass * klass);
+static void gst_sunaudiosrc_init (GstSunAudioSrc * sunaudiosrc,
+    GstSunAudioSrcClass * g_class);
+static void gst_sunaudiosrc_dispose (GObject * object);
+
+static void gst_sunaudiosrc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_sunaudiosrc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static GstCaps *gst_sunaudiosrc_getcaps (GstBaseSrc * bsrc);
+
+static gboolean gst_sunaudiosrc_open (GstAudioSrc * asrc);
+static gboolean gst_sunaudiosrc_close (GstAudioSrc * asrc);
+static gboolean gst_sunaudiosrc_prepare (GstAudioSrc * asrc,
+    GstRingBufferSpec * spec);
+static gboolean gst_sunaudiosrc_unprepare (GstAudioSrc * asrc);
+static guint gst_sunaudiosrc_read (GstAudioSrc * asrc, gpointer data,
+    guint length);
+static guint gst_sunaudiosrc_delay (GstAudioSrc * asrc);
+static void gst_sunaudiosrc_reset (GstAudioSrc * asrc);
+
+#define DEFAULT_DEVICE          "/dev/audio"
+#define DEFAULT_DEVICE_NAME     ""
+
+enum
+{
+  PROP_0,
+  PROP_DEVICE,
+  PROP_DEVICE_NAME,
+};
+
+GST_BOILERPLATE_WITH_INTERFACE (GstSunAudioSrc, gst_sunaudiosrc,
+    GstAudioSrc, GST_TYPE_AUDIO_SRC, GstMixer, GST_TYPE_MIXER, gst_sunaudiosrc)
+
+    GST_IMPLEMENT_SUNAUDIO_MIXER_CTRL_METHODS (GstSunAudioSrc, gst_sunaudiosrc)
+
+     static GstStaticPadTemplate gst_sunaudiosrc_factory =
+         GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS ("audio/x-raw-int, "
+        "endianness = (int) BYTE_ORDER, "
+        "signed = (boolean) TRUE, " "width = (int) 16, " "depth = (int) 16, "
+        /* [5510,48000] seems to be a Solaris limit */
+        "rate = (int) [ 5510, 48000 ], " "channels = (int) [ 1, 2 ]")
+    );
+
+     static void gst_sunaudiosrc_dispose (GObject * object)
+{
+  G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_sunaudiosrc_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_add_pad_template (element_class,
+      gst_static_pad_template_get (&gst_sunaudiosrc_factory));
+  gst_element_class_set_details (element_class, &plugin_details);
+}
+
+static void
+gst_sunaudiosrc_class_init (GstSunAudioSrcClass * klass)
+{
+  GObjectClass *gobject_class;
+  GstElementClass *gstelement_class;
+  GstBaseSrcClass *gstbasesrc_class;
+  GstBaseAudioSrcClass *gstbaseaudiosrc_class;
+  GstAudioSrcClass *gstaudiosrc_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gstelement_class = (GstElementClass *) klass;
+  gstbasesrc_class = (GstBaseSrcClass *) klass;
+  gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass;
+  gstaudiosrc_class = (GstAudioSrcClass *) klass;
+
+  gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_dispose);
+  gobject_class->get_property =
+      GST_DEBUG_FUNCPTR (gst_sunaudiosrc_get_property);
+  gobject_class->set_property =
+      GST_DEBUG_FUNCPTR (gst_sunaudiosrc_set_property);
+
+  gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_getcaps);
+
+  gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_open);
+  gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_prepare);
+  gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_unprepare);
+  gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_close);
+  gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_read);
+  gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_delay);
+  gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_sunaudiosrc_reset);
+
+  g_object_class_install_property (gobject_class, PROP_DEVICE,
+      g_param_spec_string ("device", "Device",
+          "SunAudio device (usually /dev/audio)", DEFAULT_DEVICE,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_DEVICE_NAME,
+      g_param_spec_string ("device-name", "Device name",
+          "Human-readable name of the sound device", DEFAULT_DEVICE_NAME,
+          G_PARAM_READABLE));
+}
+
+static void
+gst_sunaudiosrc_init (GstSunAudioSrc * sunaudiosrc,
+    GstSunAudioSrcClass * g_class)
+{
+  const char *audiodev;
+
+  GST_DEBUG_OBJECT (sunaudiosrc, "initializing sunaudiosrc");
+
+  sunaudiosrc->fd = -1;
+
+  audiodev = g_getenv ("AUDIODEV");
+  if (audiodev == NULL)
+    audiodev = DEFAULT_DEVICE;
+  sunaudiosrc->device = g_strdup (audiodev);
+
+  sunaudiosrc->device_name = g_strdup (DEFAULT_DEVICE_NAME);
+}
+
+static void
+gst_sunaudiosrc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstSunAudioSrc *sunaudiosrc;
+
+  sunaudiosrc = GST_SUNAUDIO_SRC (object);
+
+  switch (prop_id) {
+    case PROP_DEVICE:
+      if (sunaudiosrc->device)
+        g_free (sunaudiosrc->device);
+      sunaudiosrc->device = g_value_dup_string (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_sunaudiosrc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstSunAudioSrc *sunaudiosrc;
+
+  sunaudiosrc = GST_SUNAUDIO_SRC (object);
+
+  switch (prop_id) {
+    case PROP_DEVICE:
+      g_value_set_string (value, sunaudiosrc->device);
+      break;
+    case PROP_DEVICE_NAME:
+      g_value_set_string (value, sunaudiosrc->device_name);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static GstCaps *
+gst_sunaudiosrc_getcaps (GstBaseSrc * bsrc)
+{
+  GstPadTemplate *pad_template;
+  GstCaps *caps = NULL;
+  GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (bsrc);
+
+  GST_DEBUG_OBJECT (sunaudiosrc, "getcaps called");
+
+  pad_template = gst_static_pad_template_get (&gst_sunaudiosrc_factory);
+  caps = gst_caps_copy (gst_pad_template_get_caps (pad_template));
+
+  gst_object_unref (pad_template);
+
+  return caps;
+}
+
+static gboolean
+gst_sunaudiosrc_open (GstAudioSrc * asrc)
+{
+  GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
+  int fd, ret;
+
+  fd = open (sunaudiosrc->device, O_RDWR);
+
+  if (fd == -1) {
+    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, OPEN_READ, (NULL),
+        ("can't open connection to Sun Audio device %s", sunaudiosrc->device));
+
+    return FALSE;
+  }
+
+  sunaudiosrc->fd = fd;
+
+  ret = ioctl (fd, AUDIO_GETDEV, &sunaudiosrc->dev);
+  if (ret == -1) {
+    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+            strerror (errno)));
+    return FALSE;
+  }
+
+  GST_DEBUG_OBJECT (sunaudiosrc, "name %s", sunaudiosrc->dev.name);
+  GST_DEBUG_OBJECT (sunaudiosrc, "version %s", sunaudiosrc->dev.version);
+  GST_DEBUG_OBJECT (sunaudiosrc, "config %s", sunaudiosrc->dev.config);
+
+  ret = ioctl (fd, AUDIO_GETINFO, &sunaudiosrc->info);
+  if (ret == -1) {
+    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+            strerror (errno)));
+    return FALSE;
+  }
+
+  GST_DEBUG_OBJECT (sunaudiosrc, "monitor_gain %d",
+      sunaudiosrc->info.monitor_gain);
+  GST_DEBUG_OBJECT (sunaudiosrc, "output_muted %d",
+      sunaudiosrc->info.output_muted);
+  GST_DEBUG_OBJECT (sunaudiosrc, "hw_features %08x",
+      sunaudiosrc->info.hw_features);
+  GST_DEBUG_OBJECT (sunaudiosrc, "sw_features %08x",
+      sunaudiosrc->info.sw_features);
+  GST_DEBUG_OBJECT (sunaudiosrc, "sw_features_enabled %08x",
+      sunaudiosrc->info.sw_features_enabled);
+
+  if (!sunaudiosrc->mixer) {
+    const char *audiodev;
+
+    audiodev = g_getenv ("AUDIODEV");
+    if (audiodev == NULL) {
+      sunaudiosrc->mixer = gst_sunaudiomixer_ctrl_new ("/dev/audioctl");
+    } else {
+      gchar *device = g_strdup_printf ("/dev/%sctl", audiodev);
+
+      sunaudiosrc->mixer = gst_sunaudiomixer_ctrl_new (device);
+      g_free (device);
+    }
+    sunaudiosrc->device_name = g_strdup (sunaudiosrc->mixer->device);
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_sunaudiosrc_close (GstAudioSrc * asrc)
+{
+  GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
+
+  close (sunaudiosrc->fd);
+  sunaudiosrc->fd = -1;
+
+  if (sunaudiosrc->mixer) {
+    gst_sunaudiomixer_ctrl_free (sunaudiosrc->mixer);
+    sunaudiosrc->mixer = NULL;
+  }
+
+  return TRUE;
+}
+
+static gboolean
+gst_sunaudiosrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec)
+{
+  GstSunAudioSrc *sunaudiosrc = GST_SUNAUDIO_SRC (asrc);
+  audio_info_t ainfo;
+  int ret;
+  int ctrl_fd = -1;
+  int ports;
+
+  ret = ioctl (sunaudiosrc->fd, AUDIO_GETINFO, &ainfo);
+  if (ret == -1) {
+    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+            strerror (errno)));
+    return FALSE;
+  }
+
+  if (spec->width != 16)
+    return FALSE;
+
+  AUDIO_INITINFO (&ainfo);
+
+  ainfo.record.sample_rate = spec->rate;
+  ainfo.record.precision = spec->width;
+  ainfo.record.channels = spec->channels;
+  ainfo.record.encoding = AUDIO_ENCODING_LINEAR;
+  ainfo.record.buffer_size = spec->buffer_time;
+
+  GstSunAudioMixerCtrl *mixer = sunaudiosrc->mixer;
+  struct audio_info audioinfo;
+
+  if (ioctl (mixer->mixer_fd, AUDIO_GETINFO, &audioinfo) < 0) {
+    g_warning ("Error getting audio device volume");
+  }
+  ainfo.record.port = audioinfo.record.port;
+  ainfo.record.gain = audioinfo.record.gain;
+  ainfo.record.balance = audioinfo.record.balance;
+
+  spec->segsize = 128;
+  spec->segtotal = spec->buffer_time / 128;
+
+  spec->silence_sample[0] = 0;
+  spec->silence_sample[1] = 0;
+  spec->silence_sample[2] = 0;
+  spec->silence_sample[3] = 0;
+
+  ret = ioctl (sunaudiosrc->fd, AUDIO_SETINFO, &ainfo);
+  if (ret == -1) {
+    GST_ELEMENT_ERROR (sunaudiosrc, RESOURCE, SETTINGS, (NULL), ("%s",
+            strerror (errno)));
+    return FALSE;
+  }
+
+
+  ioctl (sunaudiosrc->fd, I_FLUSH, FLUSHR);
+
+  return TRUE;
+}
+
+static gboolean
+gst_sunaudiosrc_unprepare (GstAudioSrc * asrc)
+{
+  return TRUE;
+}
+
+static guint
+gst_sunaudiosrc_read (GstAudioSrc * asrc, gpointer data, guint length)
+{
+  return read (GST_SUNAUDIO_SRC (asrc)->fd, data, length);
+}
+
+static guint
+gst_sunaudiosrc_delay (GstAudioSrc * asrc)
+{
+  return 0;
+}
+
+static void
+gst_sunaudiosrc_reset (GstAudioSrc * asrc)
+{
+  return;
+}
diff --git a/sys/sunaudio/gstsunaudiosrc.h b/sys/sunaudio/gstsunaudiosrc.h
new file mode 100644 (file)
index 0000000..c369178
--- /dev/null
@@ -0,0 +1,68 @@
+/* GStreamer
+ * Copyright (C) 2004 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2005 Brian Cameron <brian.cameron@sun.com>
+ *
+ * gstsunaudiosrc.h:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_SUNAUDIO_SRC_H__
+#define __GST_SUNAUDIO_SRC_H__
+
+#include <sys/audioio.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiosrc.h>
+
+#include "gstsunaudiomixerctrl.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_SUNAUDIO_SRC     (gst_sunaudiosrc_get_type())
+#define GST_SUNAUDIO_SRC(obj)     (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SUNAUDIO_SRC,GstSunAudioSrc))
+#define GST_SUNAUDIO_SRC_CLASS(klass)  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SUNAUDIO_SRC,GstSunAudioSrcClass))
+#define GST_IS_SUNAUDIO_SRC(obj)       (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SUNAUDIO_SRC))
+#define GST_IS_SUNAUDIO_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SUNAUDIO_SRC))
+
+typedef struct _GstSunAudioSrc GstSunAudioSrc;
+typedef struct _GstSunAudioSrcClass GstSunAudioSrcClass;
+
+struct _GstSunAudioSrc {
+  GstAudioSrc    src;
+
+  gchar *device;
+  gchar *device_name;
+  gint   fd;
+  gint   control_fd;
+
+  audio_device_t dev;
+  audio_info_t info;
+
+  gint   bytes_per_sample;
+
+  GstSunAudioMixerCtrl *mixer;
+};
+
+struct _GstSunAudioSrcClass {
+  GstAudioSrcClass parent_class;
+};
+
+GType gst_sunaudiosrc_get_type(void);
+
+G_END_DECLS
+
+#endif /* __GST_SUNAUDIO_SRC_H__ */
+