[gnome-initial-setup/shell/4765: 362/362] Add a music player



commit dfef0d981720ce071ca70c5688afb114ccb2a800
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Thu Mar 12 17:32:49 2015 -0700

    Add a music player
    
    Add the ability to play some chill tunes in a loop while going through
    the FBE. There's a minimal rampout fade, but it's not hooked up yet.
    
    We aren't going to install the actual music asset yet, pending approval
    our creative team. Thankfully, it's super simple to drop in once we do
    approve it.

 gnome-initial-setup/Makefile.am           |    9 +-
 gnome-initial-setup/gis-driver.c          |    5 +
 gnome-initial-setup/gis-music-player.c    |  216 +++++++++++++++++++++++++++++
 gnome-initial-setup/gis-music-player.h    |   54 +++++++
 gnome-initial-setup/gnome-initial-setup.c |    3 +
 5 files changed, 283 insertions(+), 4 deletions(-)
---
diff --git a/gnome-initial-setup/Makefile.am b/gnome-initial-setup/Makefile.am
index ba8557a..514a254 100644
--- a/gnome-initial-setup/Makefile.am
+++ b/gnome-initial-setup/Makefile.am
@@ -2,16 +2,16 @@ SUBDIRS = pages
 
 BUILT_SOURCES =
 
-uidir = $(datadir)/gnome-initial-setup
+pkgdatadir = $(datadir)/gnome-initial-setup
 
 AM_CPPFLAGS = \
        $(INITIAL_SETUP_CFLAGS) \
        -DSECRET_API_SUBJECT_TO_CHANGE \
        -DGCR_API_SUBJECT_TO_CHANGE \
-       -DUIDIR="\"$(uidir)\"" \
+       -DUIDIR="\"$(pkgdatadir)\"" \
+       -DPKGDATADIR="\"$(pkgdatadir)\"" \
        -DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-       -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\" \
-       -DDATADIR=\""$(datadir)"\"
+       -DLIBLOCALEDIR=\""$(prefix)/lib/locale"\"
 
 libexec_PROGRAMS = gnome-initial-setup gnome-initial-setup-copy-worker
 
@@ -29,6 +29,7 @@ gnome_initial_setup_SOURCES = \
        gis-page.c gis-page.h \
        gis-driver.c gis-driver.h \
        gis-keyring.c gis-keyring.h \
+       gis-music-player.c gis-music-player.h \
        gis-window.c gis-window.h
 
 gnome_initial_setup_LDADD =    \
diff --git a/gnome-initial-setup/gis-driver.c b/gnome-initial-setup/gis-driver.c
index ab9237d..c2ea824 100644
--- a/gnome-initial-setup/gis-driver.c
+++ b/gnome-initial-setup/gis-driver.c
@@ -30,6 +30,7 @@
 
 #include "gis-assistant.h"
 #include "gis-window.h"
+#include "gis-music-player.h"
 
 #define GIS_TYPE_DRIVER_MODE (gis_driver_mode_get_type ())
 
@@ -85,6 +86,8 @@ struct _GisDriverPrivate {
   gchar *lang_override;
   gchar *default_timezone;
 
+  GisMusicPlayer *music_player;
+
   GisDriverMode mode;
 };
 typedef struct _GisDriverPrivate GisDriverPrivate;
@@ -264,6 +267,7 @@ gis_driver_activate (GApplication *app)
   G_APPLICATION_CLASS (gis_driver_parent_class)->activate (app);
 
   gtk_window_present (GTK_WINDOW (priv->main_window));
+  gis_music_player_play (priv->music_player);
 }
 
 static void
@@ -312,6 +316,7 @@ gis_driver_startup (GApplication *app)
 
   priv->main_window = gis_window_new (driver);
   priv->assistant = gis_window_get_assistant (GIS_WINDOW (priv->main_window));
+  priv->music_player = gis_music_player_new ("file://" PKGDATADIR "/fbe.ogg");
 
   gis_driver_set_user_language (driver, setlocale (LC_MESSAGES, NULL));
 
diff --git a/gnome-initial-setup/gis-music-player.c b/gnome-initial-setup/gis-music-player.c
new file mode 100644
index 0000000..564e74b
--- /dev/null
+++ b/gnome-initial-setup/gis-music-player.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2015 Endless Mobile
+ *
+ * This program 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 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#include "gis-music-player.h"
+
+#include <gst/gst.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+struct _GisMusicPlayerPrivate
+{
+  GstElement *playbin;
+  GstBus *bus;
+
+  gboolean playing;
+  int64_t loop_point;
+
+  /* fade */
+  GstClockTime fade_start_time;
+  int fade_timeout_id;
+  double fade_start_volume;
+};
+typedef struct _GisMusicPlayerPrivate GisMusicPlayerPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (GisMusicPlayer, gis_music_player, G_TYPE_OBJECT);
+
+static void
+gis_music_player_dispose (GObject *object)
+{
+  GisMusicPlayer *player = GIS_MUSIC_PLAYER (object);
+  GisMusicPlayerPrivate *priv = gis_music_player_get_instance_private (player);
+
+  g_clear_object (&priv->bus);
+  g_clear_object (&priv->playbin);
+}
+
+static void
+gis_music_player_class_init (GisMusicPlayerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = gis_music_player_dispose;
+}
+
+static void
+gis_music_player_init (GisMusicPlayer *player)
+{
+}
+
+static void
+on_state_changed (GstBus     *bus,
+                  GstMessage *message,
+                  gpointer    user_data)
+{
+  GisMusicPlayer *player = user_data;
+  GisMusicPlayerPrivate *priv = gis_music_player_get_instance_private (player);
+
+  GstState old, new;
+  gst_message_parse_state_changed (message, &old, &new, NULL);
+  GstStateChange trans = GST_STATE_TRANSITION (old, new);
+
+  if (priv->playing &&
+      message->src == GST_OBJECT (priv->playbin) &&
+      trans == GST_STATE_CHANGE_READY_TO_PAUSED)
+    {
+      gst_element_seek_simple (priv->playbin, GST_FORMAT_TIME,
+                               (GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_SEGMENT),
+                               0);
+      gst_element_set_state (priv->playbin, GST_STATE_PLAYING);
+    }
+}
+
+static void
+process_tag (const GstTagList *tag_list,
+             const char       *tag,
+             gpointer          user_data)
+{
+  GisMusicPlayer *player = user_data;
+  GisMusicPlayerPrivate *priv = gis_music_player_get_instance_private (player);
+
+  /* loop points are non-standard, so they go in the extended
+   * comments, which is gstreamer's "catch-all" */
+  if (strcmp (tag, GST_TAG_EXTENDED_COMMENT) == 0)
+    {
+      int n = gst_tag_list_get_tag_size (tag_list, tag);
+      while (n--)
+        {
+          char *str;
+          int64_t loop_point;
+
+          if (!gst_tag_list_get_string_index (tag_list, tag, n, &str))
+            continue;
+          if (sscanf (str, "LOOP_POINT=%" G_GINT64_FORMAT, &loop_point) != 0)
+            priv->loop_point = loop_point;
+
+          g_free (str);
+        }
+    }
+}
+
+static void
+on_tag (GstBus     *bus,
+        GstMessage *message,
+        gpointer    user_data)
+{
+  GstTagList *tag_list;
+  gst_message_parse_tag (message, &tag_list);
+  gst_tag_list_foreach (tag_list, process_tag, user_data);
+  gst_tag_list_unref (tag_list);
+}
+
+static void
+on_segment_done (GstBus     *bus,
+                 GstMessage *message,
+                 gpointer    user_data)
+{
+  GisMusicPlayer *player = user_data;
+  GisMusicPlayerPrivate *priv = gis_music_player_get_instance_private (player);
+
+  if (priv->playing &&
+      message->src == GST_OBJECT (priv->playbin))
+    {
+      gst_element_seek_simple (priv->playbin, GST_FORMAT_TIME,
+                               GST_SEEK_FLAG_SEGMENT,
+                               priv->loop_point);
+    }
+}
+
+GisMusicPlayer *
+gis_music_player_new (const char *uri)
+{
+  GisMusicPlayer *player = g_object_new (GIS_TYPE_MUSIC_PLAYER, NULL);
+  GisMusicPlayerPrivate *priv = gis_music_player_get_instance_private (player);
+
+  priv->playbin = gst_element_factory_make ("playbin", "player");
+  g_object_set (priv->playbin, "uri", uri, NULL);
+
+  priv->bus = gst_element_get_bus (priv->playbin);
+  gst_bus_add_signal_watch (priv->bus);
+  g_signal_connect (priv->bus, "message::state-changed",
+                    G_CALLBACK (on_state_changed), player);
+  g_signal_connect (priv->bus, "message::segment-done",
+                    G_CALLBACK (on_segment_done), player);
+  g_signal_connect (priv->bus, "message::tag",
+                    G_CALLBACK (on_tag), player);
+
+  return player;
+}
+
+void
+gis_music_player_play (GisMusicPlayer *player)
+{
+  GisMusicPlayerPrivate *priv = gis_music_player_get_instance_private (player);
+  priv->playing = TRUE;
+  gst_element_set_state (priv->playbin, GST_STATE_PAUSED);
+}
+
+#define FADE_N_STEPS 60
+#define FADE_TOTAL_TIME 1
+
+static gboolean
+fadeout (gpointer user_data)
+{
+  GisMusicPlayer *player = user_data;
+  GisMusicPlayerPrivate *priv = gis_music_player_get_instance_private (player);
+  GstClock *clock = GST_ELEMENT_CLOCK (priv->playbin);
+  GstClockTime time = gst_clock_get_time (clock);
+  GstClockTime dt = (time - priv->fade_start_time);
+  double t = 1.0 - (dt / ((double) GST_SECOND * FADE_TOTAL_TIME));
+
+  if (t > 0)
+    {
+      double volume = t * priv->fade_start_volume;
+      g_object_set (priv->playbin, "volume", volume, NULL);
+      return TRUE;
+    }
+  else
+    {
+      g_object_set (priv->playbin, "volume", 0.0, NULL);
+      priv->fade_timeout_id = 0;
+      gst_element_set_state (priv->playbin, GST_STATE_PAUSED);
+      return FALSE;
+    }
+}
+
+void
+gis_music_player_rampout (GisMusicPlayer *player)
+{
+  GisMusicPlayerPrivate *priv = gis_music_player_get_instance_private (player);
+  GstClock *clock = GST_ELEMENT_CLOCK (priv->playbin);
+
+  /* fade out at 60fps */
+  priv->fade_start_time = gst_clock_get_time (clock);
+  g_object_get (priv->playbin, "volume", &priv->fade_start_volume, NULL);
+  priv->fade_timeout_id = g_timeout_add (FADE_TOTAL_TIME * 1000 / FADE_N_STEPS, fadeout, player);
+}
diff --git a/gnome-initial-setup/gis-music-player.h b/gnome-initial-setup/gis-music-player.h
new file mode 100644
index 0000000..0288ab0
--- /dev/null
+++ b/gnome-initial-setup/gis-music-player.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015 Endless Mobile
+ *
+ * This program 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 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#ifndef GIS_MUSIC_PLAYER_H
+#define GIS_MUSIC_PLAYER_H
+
+#include <glib-object.h>
+
+#define GIS_TYPE_MUSIC_PLAYER            (gis_music_player_get_type ())
+#define GIS_MUSIC_PLAYER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIS_TYPE_MUSIC_PLAYER, 
GisMusicPlayer))
+#define GIS_MUSIC_PLAYER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GIS_TYPE_MUSIC_PLAYER, 
GisMusicPlayerClass))
+#define GIS_IS_MUSIC_PLAYER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIS_TYPE_MUSIC_PLAYER))
+#define GIS_IS_MUSIC_PLAYER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GIS_TYPE_MUSIC_PLAYER))
+#define GIS_MUSIC_PLAYER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GIS_TYPE_MUSIC_PLAYER, 
GisMusicPlayerClass))
+
+typedef struct _GisMusicPlayer      GisMusicPlayer;
+typedef struct _GisMusicPlayerClass GisMusicPlayerClass;
+
+struct _GisMusicPlayer
+{
+  GObject parent;
+};
+
+struct _GisMusicPlayerClass
+{
+  GObjectClass parent_class;
+};
+
+GType gis_music_player_get_type (void) G_GNUC_CONST;
+
+GisMusicPlayer * gis_music_player_new (const char *uri);
+void gis_music_player_play (GisMusicPlayer *player);
+void gis_music_player_rampout (GisMusicPlayer *player);
+
+#endif /* GIS_MUSIC_PLAYER_H */
diff --git a/gnome-initial-setup/gnome-initial-setup.c b/gnome-initial-setup/gnome-initial-setup.c
index 29385b3..b19c483 100644
--- a/gnome-initial-setup/gnome-initial-setup.c
+++ b/gnome-initial-setup/gnome-initial-setup.c
@@ -39,6 +39,8 @@
 #include <cheese-gtk.h>
 #endif
 
+#include <gst/gst.h>
+
 #include <egg-list-box.h>
 
 #include "pages/language/gis-language-page.h"
@@ -265,6 +267,7 @@ main (int argc, char *argv[])
   cheese_gtk_init (NULL, NULL);
 #endif
 
+  gst_init (&argc, &argv);
   gtk_init (&argc, &argv);
   ev_init ();
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]