Esempio n. 1
0
static BtPersistence *
bt_wavelevel_persistence_load (const GType type,
    const BtPersistence * const persistence, xmlNodePtr node, GError ** err,
    va_list var_args)
{
  BtWavelevel *const self = BT_WAVELEVEL (persistence);
  xmlChar *root_note_str, *rate_str, *loop_start_str, *loop_end_str;
  glong loop_start, loop_end;
  gulong rate;
  GstBtNote root_note;

  GST_DEBUG ("PERSISTENCE::wavelevel");
  g_assert (node);

  // only deserialize customizable properties
  root_note_str = xmlGetProp (node, XML_CHAR_PTR ("root-note"));
  rate_str = xmlGetProp (node, XML_CHAR_PTR ("rate"));
  loop_start_str = xmlGetProp (node, XML_CHAR_PTR ("loop-start"));
  loop_end_str = xmlGetProp (node, XML_CHAR_PTR ("loop-end"));

  root_note = root_note_str ? atol ((char *) root_note_str) : GSTBT_NOTE_NONE;
  rate = rate_str ? atol ((char *) rate_str) : 0;
  loop_start = loop_start_str ? atol ((char *) loop_start_str) : 0;
  loop_end = loop_end_str ? atol ((char *) loop_end_str) : self->priv->length;

  g_object_set (self, "root-note", root_note, "rate", rate,
      "loop-start", loop_start, "loop-end", loop_end, NULL);
  xmlFree (root_note_str);
  xmlFree (rate_str);
  xmlFree (loop_start_str);
  xmlFree (loop_end_str);

  return BT_PERSISTENCE (persistence);
}
Esempio n. 2
0
/**
 * bt_wavelevel_new:
 * @song: the song the new instance belongs to
 * @wave: the wave the new wavelevel belongs to
 * @root_note: the keyboard note this sample is related
 * @length: the number of samples
 * @loop_start: the start of the loop
 * @loop_end: the end of the loop
 * @rate: the sampling rate
 * @sample: the sample data
 *
 * Create a new instance
 *
 * Returns: (transfer full): the new instance or %NULL in case of an error
 */
BtWavelevel *
bt_wavelevel_new (const BtSong * const song, const BtWave * const wave,
    const GstBtNote root_note, const gulong length, const gulong loop_start,
    const gulong loop_end, const gulong rate, gconstpointer sample)
{
  return BT_WAVELEVEL (g_object_new (BT_TYPE_WAVELEVEL, "song", song, "wave",
          wave, "root-note", root_note, "length", length, "loop_start",
          loop_start, "loop_end", loop_end, "rate", rate, "data", sample,
          NULL));
}
Esempio n. 3
0
static void
bt_wavelevel_finalize (GObject * const object)
{
  const BtWavelevel *const self = BT_WAVELEVEL (object);

  GST_DEBUG ("!!!! self=%p", self);

  g_free (self->priv->sample);

  G_OBJECT_CLASS (bt_wavelevel_parent_class)->finalize (object);
}
Esempio n. 4
0
static void
bt_wavelevel_constructed (GObject * object)
{
  BtWavelevel *self = BT_WAVELEVEL (object);

  if (G_OBJECT_CLASS (bt_wavelevel_parent_class)->constructed)
    G_OBJECT_CLASS (bt_wavelevel_parent_class)->constructed (object);

  g_return_if_fail (BT_IS_SONG (self->priv->song));
  g_return_if_fail (BT_IS_WAVE (self->priv->wave));

  // add the wavelevel to the wave
  bt_wave_add_wavelevel (self->priv->wave, self);
}
Esempio n. 5
0
static void
bt_wavelevel_dispose (GObject * const object)
{
  const BtWavelevel *const self = BT_WAVELEVEL (object);

  return_if_disposed ();
  self->priv->dispose_has_run = TRUE;

  GST_DEBUG ("!!!! self=%p", self);

  g_object_try_weak_unref (self->priv->song);
  g_object_try_weak_unref (self->priv->wave);

  G_OBJECT_CLASS (bt_wavelevel_parent_class)->dispose (object);
}
Esempio n. 6
0
static xmlNodePtr
bt_wavelevel_persistence_save (const BtPersistence * const persistence,
    xmlNodePtr const parent_node)
{
  const BtWavelevel *const self = BT_WAVELEVEL (persistence);
  xmlNodePtr node = NULL;

  GST_DEBUG ("PERSISTENCE::wavelevel");

  if ((node =
          xmlNewChild (parent_node, NULL, XML_CHAR_PTR ("wavelevel"), NULL))) {
    // only serialize customizable properties
    xmlNewProp (node, XML_CHAR_PTR ("root-note"),
        XML_CHAR_PTR (bt_str_format_uchar (self->priv->root_note)));
    xmlNewProp (node, XML_CHAR_PTR ("rate"),
        XML_CHAR_PTR (bt_str_format_ulong (self->priv->rate)));
    xmlNewProp (node, XML_CHAR_PTR ("loop-start"),
        XML_CHAR_PTR (bt_str_format_long (self->priv->loop_start)));
    xmlNewProp (node, XML_CHAR_PTR ("loop-end"),
        XML_CHAR_PTR (bt_str_format_long (self->priv->loop_end)));
  }
  return node;
}
Esempio n. 7
0
static void
bt_wavelevel_get_property (GObject * const object, const guint property_id,
    GValue * const value, GParamSpec * const pspec)
{
  const BtWavelevel *const self = BT_WAVELEVEL (object);
  return_if_disposed ();
  switch (property_id) {
    case WAVELEVEL_SONG:
      g_value_set_object (value, self->priv->song);
      break;
    case WAVELEVEL_WAVE:
      g_value_set_object (value, self->priv->wave);
      break;
    case WAVELEVEL_ROOT_NOTE:
      g_value_set_enum (value, self->priv->root_note);
      break;
    case WAVELEVEL_LENGTH:
      g_value_set_ulong (value, self->priv->length);
      break;
    case WAVELEVEL_LOOP_START:
      g_value_set_ulong (value, self->priv->loop_start);
      break;
    case WAVELEVEL_LOOP_END:
      g_value_set_ulong (value, self->priv->loop_end);
      break;
    case WAVELEVEL_RATE:
      g_value_set_ulong (value, self->priv->rate);
      break;
    case WAVELEVEL_DATA:
      g_value_set_pointer (value, self->priv->sample);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
  }
}
Esempio n. 8
0
/* bt_wave_save_to_fd:
 *
 * Write the sample data as a wav to a filedescriptor and keep it open
 */
static gboolean
bt_wave_save_to_fd (const BtWave * const self)
{
  gboolean res = TRUE;
  GstElement *pipeline = NULL;
  GstElement *src, *fmt, *enc, *sink;
  BtWavelevel *wavelevel;
  GstBus *bus = NULL;
  GstCaps *caps;
  //gchar *fn_wav;
  gulong srate, length, size, written;
  gint16 *data;
  gint fd = -1;

  if (!self->priv->wavelevels) {
    res = FALSE;
    GST_WARNING ("No wave data.");
    goto Error;
  }

  if ((fd = g_file_open_tmp (NULL, NULL, NULL)) == -1) {
    res = FALSE;
    GST_WARNING ("Can't create tempfile.");
    goto Error;
  }
  if ((self->priv->ext_fd = g_file_open_tmp (NULL, NULL, NULL)) == -1) {
    res = FALSE;
    GST_WARNING ("Can't create tempfile.");
    goto Error;
  }
  // the data is in the wave-level :/
  wavelevel = BT_WAVELEVEL (self->priv->wavelevels->data);
  g_object_get (wavelevel,
      "data", &data, "length", &length, "rate", &srate, NULL);
  size = length * self->priv->channels * sizeof (gint16);
  GST_INFO ("about to format data as wav to fd=%d, %lu bytes to write",
      self->priv->ext_fd, size);

  // create saver pipeline
  pipeline = gst_pipeline_new ("wave-saver");
  src = gst_element_factory_make ("fdsrc", NULL);
  fmt = gst_element_factory_make ("capsfilter", NULL);
  enc = gst_element_factory_make ("wavenc", NULL);
  sink = gst_element_factory_make ("fdsink", NULL);
  GST_DEBUG ("%p ! %p ! %p ! %p", src, fmt, enc, sink);

  // configure elements
  caps = gst_caps_new_simple ("audio/x-raw",
      "format", G_TYPE_STRING, GST_AUDIO_NE (S16),
      "layout", G_TYPE_STRING, "interleaved",
      "rate", G_TYPE_INT, srate,
      "channels", G_TYPE_INT, self->priv->channels, NULL);
  g_object_set (fmt, "caps", caps, NULL);
  gst_caps_unref (caps);

  g_object_set (src, "fd", fd, "num-buffers", 1, "blocksize", size, NULL);
  g_object_set (sink, "fd", self->priv->ext_fd, "sync", FALSE, NULL);

  // add and link
  gst_bin_add_many (GST_BIN (pipeline), src, fmt, enc, sink, NULL);
  res = gst_element_link_many (src, fmt, enc, sink, NULL);
  if (!res) {
    GST_WARNING ("Can't link wave loader pipeline (src ! dec).");
    goto Error;
  }

  bus = gst_element_get_bus (pipeline);

  GST_INFO ("run pipeline");

  written = write (fd, data, size);
  size -= written;
  GST_INFO ("wrote %lu, todo %lu", written, size);
  lseek (fd, 0, SEEK_SET);

  // play and wait for EOS
  if (gst_element_set_state (pipeline,
          GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
    GST_WARNING ("Can't set wave saver pipeline for to playing");
    gst_element_set_state (pipeline, GST_STATE_NULL);
    res = FALSE;
  } else {
    GstMessage *msg;

    // we have num-buffers
    //gst_element_send_event(src,gst_event_new_eos());

    // we need to run this sync'ed with eos
    GST_INFO ("saving sample ...");

    msg = gst_bus_poll (bus, GST_MESSAGE_EOS | GST_MESSAGE_ERROR,
        GST_CLOCK_TIME_NONE);
    if (msg) {
      switch (msg->type) {
        case GST_MESSAGE_EOS:
          res = TRUE;
          break;
        case GST_MESSAGE_ERROR:
          BT_GST_LOG_MESSAGE_ERROR (msg, NULL, NULL);
          res = FALSE;
          break;
        default:
          break;
      }
      gst_message_unref (msg);
    }
  }

  GST_INFO ("sample saved");

Error:
  if (bus)
    gst_object_unref (bus);
  if (pipeline) {
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);
  }
  if (fd != -1)
    close (fd);
  if (!res)
    wave_io_free (self);
  return res;
}
Esempio n. 9
0
static void
bt_wavelevel_set_property (GObject * const object, const guint property_id,
    const GValue * const value, GParamSpec * const pspec)
{
  const BtWavelevel *const self = BT_WAVELEVEL (object);
  return_if_disposed ();
  switch (property_id) {
    case WAVELEVEL_SONG:
      self->priv->song = BT_SONG (g_value_get_object (value));
      g_object_try_weak_ref (self->priv->song);
      //GST_DEBUG("set the song for wavelevel: %p",self->priv->song);
      break;
    case WAVELEVEL_WAVE:
      self->priv->wave = BT_WAVE (g_value_get_object (value));
      g_object_try_weak_ref (self->priv->wave);
      GST_DEBUG ("set the wave for wavelevel: %p", self->priv->wave);
      break;
    case WAVELEVEL_ROOT_NOTE:
      self->priv->root_note = g_value_get_enum (value);
      GST_DEBUG ("set the root-note for wavelevel: %d", self->priv->root_note);
      break;
    case WAVELEVEL_LENGTH:
      self->priv->length = g_value_get_ulong (value);
      GST_DEBUG ("set the length for wavelevel: %lu", self->priv->length);
      break;
    case WAVELEVEL_LOOP_START:
      self->priv->loop_start = g_value_get_ulong (value);
      GST_INFO ("loop: 0 / %lu .. %lu / %lu", self->priv->loop_start,
          self->priv->loop_end, self->priv->length);
      // make sure its less then loop_end/length
      if (self->priv->loop_end > 0) {
        if (self->priv->loop_start >= self->priv->loop_end) {
          GST_DEBUG ("clip loop-start by loop-end: %lu", self->priv->loop_end);
          self->priv->loop_start = self->priv->loop_end - 1;
        }
      }
      if (self->priv->length > 0) {
        if (self->priv->loop_start >= self->priv->length) {
          GST_DEBUG ("clip loop-start by length: %lu", self->priv->length);
          self->priv->loop_start = self->priv->length - 1;
        }
      }
      GST_DEBUG ("set the loop-start for wavelevel: %lu",
          self->priv->loop_start);
      break;
    case WAVELEVEL_LOOP_END:
      self->priv->loop_end = g_value_get_ulong (value);
      GST_INFO ("loop: 0 / %lu .. %lu / %lu", self->priv->loop_start,
          self->priv->loop_end, self->priv->length);
      // make sure its more then loop-start
      if (self->priv->loop_start > 0) {
        if (self->priv->loop_end < self->priv->loop_start) {
          GST_DEBUG ("clip loop-end by loop-start: %lu",
              self->priv->loop_start);
          self->priv->loop_end = self->priv->loop_start + 1;
        }
      }
      // make sure its less then or equal to length
      if (self->priv->length > 0) {
        if (self->priv->loop_end > self->priv->length) {
          GST_DEBUG ("clip loop-end by length: %lu", self->priv->length);
          self->priv->loop_end = self->priv->length;
        }
      }
      GST_DEBUG ("set the loop-start for wavelevel: %lu",
          self->priv->loop_start);
      break;
    case WAVELEVEL_RATE:
      self->priv->rate = g_value_get_ulong (value);
      GST_DEBUG ("set the rate for wavelevel: %lu", self->priv->rate);
      break;
    case WAVELEVEL_DATA:
      g_free (self->priv->sample);
      self->priv->sample = g_value_get_pointer (value);
      GST_DEBUG ("set the data-pointer for wavelevel: %p", self->priv->sample);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
  }
}