Beispiel #1
0
static void
test_setup (void)
{
  app = bt_test_application_new ();
  song = bt_song_new (app);
  bt_child_proxy_set (song, "sequence::length", 16, "sequence::loop", FALSE,
      NULL);
}
Beispiel #2
0
static void
on_changelog_can_undo_changed (BtChangeLog * change_log, GParamSpec * arg,
    gpointer user_data)
{
  BtEditApplication *self = BT_EDIT_APPLICATION (user_data);

  if (self->priv->need_dts_reset) {
    self->priv->need_dts_reset = FALSE;
    // this updates the time-stamp (we need that, to show the since when we have
    // unsaved changes, if someone closes the song)
    bt_child_proxy_set (self->priv->song, "song-info::change-dts", NULL, NULL);
  }
}
Beispiel #3
0
static void
on_songio_status_changed (BtSongIO * songio, GParamSpec * arg,
    gpointer user_data)
{
  BtEditApplication *self = BT_EDIT_APPLICATION (user_data);
  gchar *str;

  /* IDEA(ensonic): bind properties */
  g_object_get (songio, "status", &str, NULL);
  GST_INFO ("songio_status has changed : \"%s\"", safe_string (str));
  bt_child_proxy_set (self->priv->main_window, "statusbar::status", str, NULL);
  g_free (str);
}
Beispiel #4
0
static void
test_bt_child_proxy_set (BT_TEST_ARGS)
{
  BT_TEST_START;
  GST_INFO ("-- arrange --");
  gboolean loop;

  GST_INFO ("-- act --");
  bt_child_proxy_set (song, "sequence::loop", TRUE, NULL);

  GST_INFO ("-- assert --");
  bt_child_proxy_get (song, "sequence::loop", &loop, NULL);
  ck_assert_int_eq (TRUE, loop);

  GST_INFO ("-- cleanup --");
  BT_TEST_END;
}
Beispiel #5
0
/**
 * bt_edit_application_save_song:
 * @self: the application instance to save a song from
 * @file_name: the song filename to save
 * @err: where to store the error message in case of an error, or %NULL
 *
 * Saves a song.
 *
 * Returns: true for success
 */
gboolean
bt_edit_application_save_song (const BtEditApplication * self,
    const char *file_name, GError ** err)
{
  gboolean res = FALSE;
  BtSongIO *saver;

  g_return_val_if_fail (BT_IS_EDIT_APPLICATION (self), FALSE);

  GST_INFO ("song name = %s", file_name);

  if ((saver = bt_song_io_from_file (file_name, err))) {
    gchar *old_file_name = NULL, *bak_file_name = NULL;

    bt_edit_application_ui_lock (self);
    g_signal_connect (saver, "notify::status",
        G_CALLBACK (on_songio_status_changed), (gpointer) self);

    // update the time-stamp
    bt_child_proxy_set (self->priv->song, "song-info::change-dts", NULL, NULL);

    bt_child_proxy_get (self->priv->song, "song-info::file-name",
        &old_file_name, NULL);

    /* save file saving (bak files)
     * save
     *   new file (!old_file_name)
     *     chosen file-name already exist
     *       - move to <existing>.bak
     *       - save newfile
     *       - if saving failed, move <existing>.bak back
     *       - if saving worked, delete <existing>.bak
     *     chosen file-name does not exist
     *       - save newfile
     *   existing file
     *     - move to <existing>.bak
     *       - save newfile
     *       - if saving failed, move <existing>.bak back
     * save-as
     *   new file (!old_file_name)
     *     like save of a new-file
     *   existing file
     *     chosen file-name already exist
     *       - like save of an existing file
     *     chosen file-name does not exist
     *       - save newfile
     *
     * - check how other apps do it (check if inodes change if various scenarios)
     * - when loading a file, should we keep the file-handle open, so then when
     *   saving, we can just update it?
     *   - this can help with the wavetable (only updated changed wavetable slots)
     *   - if we can't update it, we can use gsf_input_copy() for external files
     *     (if unchanged)
     * - if the user deletes the file that is currently open -> user error
     */
    if (g_file_test (file_name, G_FILE_TEST_EXISTS)) {
      bak_file_name = g_strconcat (file_name, ".bak", NULL);
      g_rename (file_name, bak_file_name);
    }
    if (bt_song_io_save (saver, self->priv->song, err)) {
      res = TRUE;
      if (!old_file_name || strcmp (old_file_name, file_name)) {
        // saving worked, we remove the bak file as
        // - there was no old_file_name and/or
        // - user has chosen to overwrite this file
        g_unlink (bak_file_name);
      }
    } else {
      GST_WARNING ("could not save song \"%s\"", file_name);
      if (bak_file_name) {
        // saving failed, so move a file we renamed to .bak back
        g_rename (bak_file_name, file_name);
      }
    }
    GST_INFO ("saving done");
    self->priv->unsaved = FALSE;
    g_object_notify (G_OBJECT (self), "unsaved");
    self->priv->need_dts_reset = TRUE;

    bt_edit_application_ui_unlock (self);

    g_free (old_file_name);
    g_free (bak_file_name);
    g_object_unref (saver);
  } else {
    GST_WARNING ("Unknown extension \"%s\"", file_name);
  }
  return res;
}
Beispiel #6
0
/**
 * bt_edit_application_new_song:
 * @self: the application instance to create a new song in
 *
 * Creates a new blank song instance. If there is a previous song instance it
 * will be freed.
 *
 * Returns: %TRUE for success
 */
gboolean
bt_edit_application_new_song (const BtEditApplication * self)
{
  gboolean res = FALSE;
  BtSong *song;
  BtSetup *setup;
  BtMachine *machine;
  gchar *id;
  gulong bars;
  GError *err = NULL;

  g_return_val_if_fail (BT_IS_EDIT_APPLICATION (self), FALSE);

  // create new song
  song = bt_song_new (BT_APPLICATION (self));

  bt_child_proxy_get (song, "setup", &setup, "song-info::bars", &bars, NULL);
  // make initial song length 4 timelines
  bt_child_proxy_set (song, "sequence::length", bars * 4, NULL);
  // add audiosink
  id = bt_setup_get_unique_machine_id (setup, "master");
  machine = BT_MACHINE (bt_sink_machine_new (song, id, &err));
  if (err == NULL) {
    GHashTable *properties;

    GST_DEBUG ("sink-machine=%" G_OBJECT_REF_COUNT_FMT,
        G_OBJECT_LOG_REF_COUNT (machine));
    g_object_get (machine, "properties", &properties, NULL);
    if (properties) {
      gchar str[G_ASCII_DTOSTR_BUF_SIZE];
      g_hash_table_insert (properties, g_strdup ("xpos"),
          g_strdup (g_ascii_dtostr (str, G_ASCII_DTOSTR_BUF_SIZE, 0.0)));
      g_hash_table_insert (properties, g_strdup ("ypos"),
          g_strdup (g_ascii_dtostr (str, G_ASCII_DTOSTR_BUF_SIZE, 0.0)));
    }
    if (bt_machine_enable_input_post_level (machine)) {
      GST_DEBUG ("sink-machine=%" G_OBJECT_REF_COUNT_FMT,
          G_OBJECT_LOG_REF_COUNT (machine));
      // set new song in application
      g_object_set ((gpointer) self, "song", song, NULL);
      res = TRUE;
    } else {
      GST_WARNING ("Can't add input level/gain element in sink machine");
    }
    GST_DEBUG ("sink-machine=%" G_OBJECT_REF_COUNT_FMT,
        G_OBJECT_LOG_REF_COUNT (machine));
  } else {
    GST_WARNING ("Can't create sink machine: %s", err->message);
    g_error_free (err);
    gst_object_unref (machine);
  }
  g_free (id);

  self->priv->unsaved = FALSE;
  g_object_notify (G_OBJECT (self), "unsaved");

  // release references
  g_object_unref (setup);
  g_object_unref (song);
  return res;
}