/* GStreamer OSS4 audio sink
 * Copyright (C) 2007-2008 Tim-Philipp Müller <tim centricular net>
 *
 * 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., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */
/**
 * SECTION:element-oss4sink
 *
 * This element lets you output sound using the Open Sound System (OSS)
 * version 4.
 * 
 * Note that you should almost always use generic audio conversion elements
 * like audioconvert and audioresample in front of an audiosink to make sure
 * your pipeline works under all circumstances (those conversion elements will
 * act in passthrough-mode if no conversion is necessary).
 * 
 * <refsect2>
 * <title>Example pipelines</title>
 * |[
 * gst-launch-1.0 -v audiotestsrc ! audioconvert ! volume volume=0.1 ! oss4sink
 * ]| will output a sine wave (continuous beep sound) to your sound card (with
 * a very low volume as precaution).
 * |[
 * gst-launch-1.0 -v filesrc location=music.ogg ! decodebin ! audioconvert ! audioresample ! oss4sink
 * ]| will play an Ogg/Vorbis audio file and output it using the Open Sound System
 * version 4.
 * </refsect2>
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

#include <gst/gst-i18n-plugin.h>
#include <gst/audio/streamvolume.h>

#define NO_LEGACY_MIXER
#include "oss4-audio.h"
#include "oss4-sink.h"
#include "oss4-property-probe.h"
#include "oss4-soundcard.h"

GST_DEBUG_CATEGORY_EXTERN (oss4sink_debug);
#define GST_CAT_DEFAULT oss4sink_debug

static void gst_oss4_sink_dispose (GObject * object);
static void gst_oss4_sink_finalize (GObject * object);

static void gst_oss4_sink_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec);
static void gst_oss4_sink_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec);

static GstCaps *gst_oss4_sink_getcaps (GstBaseSink * bsink, GstCaps * filter);
static gboolean gst_oss4_sink_open (GstAudioSink * asink,
    gboolean silent_errors);
static gboolean gst_oss4_sink_open_func (GstAudioSink * asink);
static gboolean gst_oss4_sink_close (GstAudioSink * asink);
static gboolean gst_oss4_sink_prepare (GstAudioSink * asink,
    GstAudioRingBufferSpec * spec);
static gboolean gst_oss4_sink_unprepare (GstAudioSink * asink);
static gint gst_oss4_sink_write (GstAudioSink * asink, gpointer data,
    guint length);
static guint gst_oss4_sink_delay (GstAudioSink * asink);
static void gst_oss4_sink_reset (GstAudioSink * asink);

#define DEFAULT_DEVICE      NULL
#define DEFAULT_DEVICE_NAME NULL
#define DEFAULT_MUTE        FALSE
#define DEFAULT_VOLUME      1.0
#define MAX_VOLUME          10.0

enum
{
  PROP_0,
  PROP_DEVICE,
  PROP_DEVICE_NAME,
  PROP_VOLUME,
  PROP_MUTE,
  PROP_LAST
};

#define gst_oss4_sink_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstOss4Sink, gst_oss4_sink,
    GST_TYPE_AUDIO_SINK, G_IMPLEMENT_INTERFACE (GST_TYPE_STREAM_VOLUME, NULL));

static void
gst_oss4_sink_dispose (GObject * object)
{
  GstOss4Sink *osssink = GST_OSS4_SINK (object);

  if (osssink->probed_caps) {
    gst_caps_unref (osssink->probed_caps);
    osssink->probed_caps = NULL;
  }

  G_OBJECT_CLASS (parent_class)->dispose (object);
}

static void
gst_oss4_sink_class_init (GstOss4SinkClass * klass)
{
  GstAudioSinkClass *audiosink_class = (GstAudioSinkClass *) klass;
  GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass;
  GstElementClass *gstelement_class = (GstElementClass *) klass;
  GObjectClass *gobject_class = (GObjectClass *) klass;
  GstPadTemplate *templ;

  gobject_class->dispose = gst_oss4_sink_dispose;
  gobject_class->finalize = gst_oss4_sink_finalize;
  gobject_class->get_property = gst_oss4_sink_get_property;
  gobject_class->set_property = gst_oss4_sink_set_property;

  g_object_class_install_property (gobject_class, PROP_DEVICE,
      g_param_spec_string ("device", "Device",
          "OSS4 device (e.g. /dev/oss/hdaudio0/pcm0 or /dev/dspN) "
          "(NULL = use first available playback device)",
          DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  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 | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class,
      PROP_VOLUME,
      g_param_spec_double ("volume", "Volume",
          "Linear volume of this stream, 1.0=100%", 0.0, MAX_VOLUME,
          DEFAULT_VOLUME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  g_object_class_install_property (gobject_class,
      PROP_MUTE,
      g_param_spec_boolean ("mute", "Mute",
          "Mute state of this stream", DEFAULT_MUTE,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  basesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_oss4_sink_getcaps);

  audiosink_class->open = GST_DEBUG_FUNCPTR (gst_oss4_sink_open_func);
  audiosink_class->close = GST_DEBUG_FUNCPTR (gst_oss4_sink_close);
  audiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_oss4_sink_prepare);
  audiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_oss4_sink_unprepare);
  audiosink_class->write = GST_DEBUG_FUNCPTR (gst_oss4_sink_write);
  audiosink_class->delay = GST_DEBUG_FUNCPTR (gst_oss4_sink_delay);
  audiosink_class->reset = GST_DEBUG_FUNCPTR (gst_oss4_sink_reset);

  gst_element_class_set_static_metadata (gstelement_class,
      "OSS v4 Audio Sink", "Sink/Audio",
      "Output to a sound card via OSS version 4",
      "Tim-Philipp Müller <tim centricular net>");

  templ = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
      gst_oss4_audio_get_template_caps ());
  gst_element_class_add_pad_template (gstelement_class, templ);
}

static void
gst_oss4_sink_init (GstOss4Sink * osssink)
{
  const gchar *device;

  device = g_getenv ("AUDIODEV");
  if (device == NULL)
    device = DEFAULT_DEVICE;
  osssink->device = g_strdup (device);
  osssink->fd = -1;
  osssink->bytes_per_sample = 0;
  osssink->probed_caps = NULL;
  osssink->device_name = NULL;
  osssink->mute_volume = 100 | (100 << 8);
}

static void
gst_oss4_sink_finalize (GObject * object)
{
  GstOss4Sink *osssink = GST_OSS4_SINK (object);

  g_free (osssink->device);
  osssink->device = NULL;

  G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
gst_oss4_sink_set_volume (GstOss4Sink * oss, gdouble volume)
{
  int ivol;

  volume = volume * 100.0;
  ivol = (int) volume | ((int) volume << 8);
  GST_OBJECT_LOCK (oss);
  if (ioctl (oss->fd, SNDCTL_DSP_SETPLAYVOL, &ivol) < 0) {
    GST_LOG_OBJECT (oss, "SETPLAYVOL failed");
  }
  GST_OBJECT_UNLOCK (oss);
}

static gdouble
gst_oss4_sink_get_volume (GstOss4Sink * oss)
{
  int ivol, lvol, rvol;
  gdouble dvol = DEFAULT_VOLUME;

  GST_OBJECT_LOCK (oss);
  if (ioctl (oss->fd, SNDCTL_DSP_GETPLAYVOL, &ivol) < 0) {
    GST_LOG_OBJECT (oss, "GETPLAYVOL failed");
  } else {
    /* Return the higher of the two volume channels, if different */
    lvol = ivol & 0xff;
    rvol = (ivol >> 8) & 0xff;
    dvol = MAX (lvol, rvol) / 100.0;
  }
  GST_OBJECT_UNLOCK (oss);

  return dvol;
}

static void
gst_oss4_sink_set_mute (GstOss4Sink * oss, gboolean mute)
{
  int ivol;

  if (mute) {
    /*
     * OSSv4 does not have a per-channel mute, so simulate by setting
     * the value to 0.  Save the volume before doing a mute so we can
     * reset the value when the user un-mutes.
     */
    ivol = 0;

    GST_OBJECT_LOCK (oss);
    if (ioctl (oss->fd, SNDCTL_DSP_GETPLAYVOL, &oss->mute_volume) < 0) {
      GST_LOG_OBJECT (oss, "GETPLAYVOL failed");
    }
    if (ioctl (oss->fd, SNDCTL_DSP_SETPLAYVOL, &ivol) < 0) {
      GST_LOG_OBJECT (oss, "SETPLAYVOL failed");
    }
    GST_OBJECT_UNLOCK (oss);
  } else {
    /*
     * If the saved volume is 0, then reset it to 100.  Otherwise the mute
     * can get stuck.  This can happen, for example, due to rounding
     * errors in converting from the float to an integer.
     */
    if (oss->mute_volume == 0) {
      oss->mute_volume = 100 | (100 << 8);
    }
    GST_OBJECT_LOCK (oss);
    if (ioctl (oss->fd, SNDCTL_DSP_SETPLAYVOL, &oss->mute_volume) < 0) {
      GST_LOG_OBJECT (oss, "SETPLAYVOL failed");
    }
    GST_OBJECT_UNLOCK (oss);
  }
}

static gboolean
gst_oss4_sink_get_mute (GstOss4Sink * oss)
{
  int ivol, lvol, rvol;

  GST_OBJECT_LOCK (oss);
  if (ioctl (oss->fd, SNDCTL_DSP_GETPLAYVOL, &ivol) < 0) {
    GST_LOG_OBJECT (oss, "GETPLAYVOL failed");
    lvol = rvol = 100;
  } else {
    lvol = ivol & 0xff;
    rvol = (ivol >> 8) & 0xff;
  }
  GST_OBJECT_UNLOCK (oss);

  return (lvol == 0 && rvol == 0);
}

static void
gst_oss4_sink_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstOss4Sink *oss = GST_OSS4_SINK (object);

  switch (prop_id) {
    case PROP_DEVICE:
      GST_OBJECT_LOCK (oss);
      if (oss->fd == -1) {
        g_free (oss->device);
        oss->device = g_value_dup_string (value);
        if (oss->probed_caps) {
          gst_caps_unref (oss->probed_caps);
          oss->probed_caps = NULL;
        }
        g_free (oss->device_name);
        oss->device_name = NULL;
      } else {
        g_warning ("%s: can't change \"device\" property while audio sink "
            "is open", GST_OBJECT_NAME (oss));
      }
      GST_OBJECT_UNLOCK (oss);
      break;
    case PROP_VOLUME:
      gst_oss4_sink_set_volume (oss, g_value_get_double (value));
      break;
    case PROP_MUTE:
      gst_oss4_sink_set_mute (oss, g_value_get_boolean (value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static void
gst_oss4_sink_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstOss4Sink *oss = GST_OSS4_SINK (object);

  switch (prop_id) {
    case PROP_DEVICE:
      GST_OBJECT_LOCK (oss);
      g_value_set_string (value, oss->device);
      GST_OBJECT_UNLOCK (oss);
      break;
    case PROP_DEVICE_NAME:
      GST_OBJECT_LOCK (oss);
      if (oss->fd == -1 && oss->device != NULL) {
        /* If device is set, try to retrieve the name even if we're not open */
        if (gst_oss4_sink_open (GST_AUDIO_SINK (oss), TRUE)) {
          g_value_set_string (value, oss->device_name);
          gst_oss4_sink_close (GST_AUDIO_SINK (oss));
        } else {
          gchar *name = NULL;

          gst_oss4_property_probe_find_device_name_nofd (GST_OBJECT (oss),
              oss->device, &name);
          g_value_set_string (value, name);
          g_free (name);
        }
      } else {
        g_value_set_string (value, oss->device_name);
      }
      GST_OBJECT_UNLOCK (oss);
      break;
    case PROP_VOLUME:
      g_value_set_double (value, gst_oss4_sink_get_volume (oss));
      break;
    case PROP_MUTE:
      g_value_set_boolean (value, gst_oss4_sink_get_mute (oss));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}

static GstCaps *
gst_oss4_sink_getcaps (GstBaseSink * bsink, GstCaps * filter)
{
  GstOss4Sink *oss;
  GstCaps *caps;

  oss = GST_OSS4_SINK (bsink);

  if (oss->fd == -1) {
    caps = gst_oss4_audio_get_template_caps ();
  } else if (oss->probed_caps) {
    caps = gst_caps_copy (oss->probed_caps);
  } else {
    caps = gst_oss4_audio_probe_caps (GST_OBJECT (oss), oss->fd);
    if (caps != NULL && !gst_caps_is_empty (caps)) {
      oss->probed_caps = gst_caps_copy (caps);
    }
  }

  if (filter && caps) {
    GstCaps *intersection;

    intersection =
        gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
    gst_caps_unref (caps);
    return intersection;
  } else {
    return caps;
  }
}

/* note: we must not take the object lock here unless we fix up get_property */
static gboolean
gst_oss4_sink_open (GstAudioSink * asink, gboolean silent_errors)
{
  GstOss4Sink *oss;
  gchar *device;
  int mode;

  oss = GST_OSS4_SINK (asink);

  if (oss->device)
    device = g_strdup (oss->device);
  else
    device = gst_oss4_audio_find_device (GST_OBJECT_CAST (oss));

  /* desperate times, desperate measures */
  if (device == NULL)
    device = g_strdup ("/dev/dsp0");

  GST_INFO_OBJECT (oss, "Trying to open OSS4 device '%s'", device);

  /* we open in non-blocking mode even if we don't really want to do writes
   * non-blocking because we can't be sure that this is really a genuine
   * OSS4 device with well-behaved drivers etc. We really don't want to
   * hang forever under any circumstances. */
  oss->fd = open (device, O_WRONLY | O_NONBLOCK, 0);
  if (oss->fd == -1) {
    switch (errno) {
      case EBUSY:
        goto busy;
      case EACCES:
        goto no_permission;
      default:
        goto open_failed;
    }
  }

  GST_INFO_OBJECT (oss, "Opened device '%s'", device);

  /* Make sure it's OSS4. If it's old OSS, let osssink handle it */
  if (!gst_oss4_audio_check_version (GST_OBJECT_CAST (oss), oss->fd))
    goto legacy_oss;

  /* now remove the non-blocking flag. */
  mode = fcntl (oss->fd, F_GETFL);
  mode &= ~O_NONBLOCK;
  if (fcntl (oss->fd, F_SETFL, mode) < 0) {
    /* some drivers do no support unsetting the non-blocking flag, try to
     * close/open the device then. This is racy but we error out properly. */
    GST_WARNING_OBJECT (oss, "failed to unset O_NONBLOCK (buggy driver?), "
        "will try to re-open device now");
    gst_oss4_sink_close (asink);
    if ((oss->fd = open (device, O_WRONLY, 0)) == -1)
      goto non_block;
  }

  oss->open_device = device;

  /* not using ENGINEINFO here because it sometimes returns a different and
   * less useful name than AUDIOINFO for the same device */
  if (!gst_oss4_property_probe_find_device_name (GST_OBJECT (oss), oss->fd,
          oss->open_device, &oss->device_name)) {
    oss->device_name = NULL;
  }

  /* list output routings, for informational purposes only so far */
  {
    oss_mixer_enuminfo routings = { 0, };
    guint i;

    if (ioctl (oss->fd, SNDCTL_DSP_GET_PLAYTGT_NAMES, &routings) != -1) {
      GST_LOG_OBJECT (oss, "%u output routings (static list: %d)",
          routings.nvalues, ! !(routings.version == 0));
      for (i = 0; i < routings.nvalues; ++i) {
        GST_LOG_OBJECT (oss, "  output routing %d: %s", i,
            &routings.strings[routings.strindex[i]]);
      }
    }
  }

  return TRUE;

  /* ERRORS */
busy:
  {
    if (!silent_errors) {
      GST_ELEMENT_ERROR (oss, RESOURCE, BUSY,
          (_("Could not open audio device for playback. "
                  "Device is being used by another application.")), (NULL));
    }
    g_free (device);
    return FALSE;
  }
no_permission:
  {
    if (!silent_errors) {
      GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
          (_("Could not open audio device for playback. "
                  "You don't have permission to open the device.")),
          GST_ERROR_SYSTEM);
    }
    g_free (device);
    return FALSE;
  }
open_failed:
  {
    if (!silent_errors) {
      GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
          (_("Could not open audio device for playback.")), GST_ERROR_SYSTEM);
    }
    g_free (device);
    return FALSE;
  }
legacy_oss:
  {
    if (!silent_errors) {
      GST_ELEMENT_ERROR (oss, RESOURCE, OPEN_WRITE,
          (_("Could not open audio device for playback. "
                  "This version of the Open Sound System is not supported by this "
                  "element.")), ("Try the 'osssink' element instead"));
    }
    gst_oss4_sink_close (asink);
    g_free (device);
    return FALSE;
  }
non_block:
  {
    if (!silent_errors) {
      GST_ELEMENT_ERROR (oss, RESOURCE, SETTINGS, (NULL),
          ("Unable to set device %s into non-blocking mode: %s",
              oss->device, g_strerror (errno)));
    }
    g_free (device);
    return FALSE;
  }
}

static gboolean
gst_oss4_sink_open_func (GstAudioSink * asink)
{
  if (!gst_oss4_sink_open (asink, FALSE))
    return FALSE;

  /* the initial volume might not be the property default, so notify
   * application to make it get a reading of the current volume */
  g_object_notify (G_OBJECT (asink), "volume");
  return TRUE;
}

static gboolean
gst_oss4_sink_close (GstAudioSink * asink)
{
  GstOss4Sink *oss = GST_OSS4_SINK (asink);

  if (oss->fd != -1) {
    GST_DEBUG_OBJECT (oss, "closing device");
    close (oss->fd);
    oss->fd = -1;
  }

  oss->bytes_per_sample = 0;
  /* we keep the probed caps cached, at least until the device changes */

  g_free (oss->open_device);
  oss->open_device = NULL;

  g_free (oss->device_name);
  oss->device_name = NULL;

  if (oss->probed_caps) {
    gst_caps_unref (oss->probed_caps);
    oss->probed_caps = NULL;
  }

  return TRUE;
}

static gboolean
gst_oss4_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec)
{
  GstOss4Sink *oss;

  oss = GST_OSS4_SINK (asink);

  if (!gst_oss4_audio_set_format (GST_OBJECT_CAST (oss), oss->fd, spec)) {
    GST_WARNING_OBJECT (oss, "Couldn't set requested format %" GST_PTR_FORMAT,
        spec->caps);
    return FALSE;
  }

  oss->bytes_per_sample = GST_AUDIO_INFO_BPF (&spec->info);

  return TRUE;
}

static gboolean
gst_oss4_sink_unprepare (GstAudioSink * asink)
{
  /* could do a SNDCTL_DSP_HALT, but the OSS manual recommends a close/open,
   * since HALT won't properly reset some devices, apparently */

  if (!gst_oss4_sink_close (asink))
    goto couldnt_close;

  if (!gst_oss4_sink_open_func (asink))
    goto couldnt_reopen;

  return TRUE;

  /* ERRORS */
couldnt_close:
  {
    GST_DEBUG_OBJECT (asink, "Couldn't close the audio device");
    return FALSE;
  }
couldnt_reopen:
  {
    GST_DEBUG_OBJECT (asink, "Couldn't reopen the audio device");
    return FALSE;
  }
}

static gint
gst_oss4_sink_write (GstAudioSink * asink, gpointer data, guint length)
{
  GstOss4Sink *oss;
  int n;

  oss = GST_OSS4_SINK_CAST (asink);

  n = write (oss->fd, data, length);
  GST_LOG_OBJECT (asink, "wrote %d/%d samples, %d bytes",
      n / oss->bytes_per_sample, length / oss->bytes_per_sample, n);

  if (G_UNLIKELY (n < 0)) {
    switch (errno) {
      case ENOTSUP:
      case EACCES:{
        /* This is the most likely cause, I think */
        GST_ELEMENT_ERROR (asink, RESOURCE, WRITE,
            (_("Playback is not supported by this audio device.")),
            ("write: %s (device: %s) (maybe this is an input-only device?)",
                g_strerror (errno), oss->open_device));
        break;
      }
      default:{
        GST_ELEMENT_ERROR (asink, RESOURCE, WRITE,
            (_("Audio playback error.")),
            ("write: %s (device: %s)", g_strerror (errno), oss->open_device));
        break;
      }
    }
  }

  return n;
}

static guint
gst_oss4_sink_delay (GstAudioSink * asink)
{
  GstOss4Sink *oss;
  gint delay = -1;

  oss = GST_OSS4_SINK_CAST (asink);

  GST_OBJECT_LOCK (oss);
  if (ioctl (oss->fd, SNDCTL_DSP_GETODELAY, &delay) < 0 || delay < 0) {
    GST_LOG_OBJECT (oss, "GETODELAY failed");
  }
  GST_OBJECT_UNLOCK (oss);

  if (G_UNLIKELY (delay < 0))   /* error case */
    return 0;

  return delay / oss->bytes_per_sample;
}

static void
gst_oss4_sink_reset (GstAudioSink * asink)
{
  /* There's nothing we can do here really: OSS can't handle access to the
   * same device/fd from multiple threads and might deadlock or blow up in
   * other ways if we try an ioctl SNDCTL_DSP_HALT or similar */
}
