~ubuntu-branches/ubuntu/oneiric/alarm-clock-applet/oneiric

« back to all changes in this revision

Viewing changes to src/player.c

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2009-05-30 23:24:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090530232427-88on1j2ily4ajxdz
Tags: upstream-0.2.6
ImportĀ upstreamĀ versionĀ 0.2.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * player.c - Simple media player based on GStreamer
 
3
 * 
 
4
 * Copyright (C) 2007-2008 Johannes H. Jensen <joh@pseudoberries.com>
 
5
 * 
 
6
 * This program is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU General Public License
 
8
 * as published by the Free Software Foundation; either version 2
 
9
 * of the License, or (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
19
 * 
 
20
 * Authors:
 
21
 *              Johannes H. Jensen <joh@pseudoberries.com>
 
22
 */
 
23
 
 
24
#include <gst/gst.h>
 
25
 
 
26
#include "player.h"
 
27
 
 
28
/**
 
29
 * Create a new media player.
 
30
 * 
 
31
 * @uri                         The file to play.
 
32
 * @loop                        Wether to loop or not.
 
33
 * @state_callback      An optional #MediaPlayerStateChangeCallback which will be
 
34
 *                                      notified when the state of the player changes.
 
35
 * @data                        Data for the state_callback
 
36
 * @error_handler       An optional #MediaPlayerErrorHandler which will be notified
 
37
 *                                      if an error occurs.
 
38
 * @error_data          Data for the error_handler.
 
39
 */
 
40
MediaPlayer *
 
41
media_player_new (const gchar *uri, gboolean loop,
 
42
                                  MediaPlayerStateChangeCallback state_callback, gpointer data,
 
43
                                  MediaPlayerErrorHandler error_handler, gpointer error_data)
 
44
{
 
45
        MediaPlayer *player;
 
46
        GstElement *audiosink, *videosink;
 
47
        
 
48
        // Initialize struct
 
49
        player = g_new (MediaPlayer, 1);
 
50
        
 
51
        player->loop     = loop;
 
52
        player->state    = MEDIA_PLAYER_STOPPED;
 
53
        player->watch_id = 0;
 
54
        
 
55
        player->state_changed           = state_callback;
 
56
        player->state_changed_data      = data;
 
57
        player->error_handler           = error_handler;
 
58
        player->error_handler_data      = error_data;
 
59
        
 
60
        // Initialize GStreamer
 
61
        gst_init (NULL, NULL);
 
62
        
 
63
        /* Set up player */
 
64
        player->player  = gst_element_factory_make ("playbin", "player");
 
65
        audiosink               = gst_element_factory_make ("gconfaudiosink", "player-audiosink");
 
66
        videosink               = gst_element_factory_make ("gconfvideosink", "player-videosink");
 
67
        
 
68
        if (!player->player || !audiosink || !videosink) {
 
69
                g_critical ("Could not create player.");
 
70
                return NULL;
 
71
        }
 
72
        
 
73
        // Set uri and sinks
 
74
        g_object_set (player->player,
 
75
                                  "uri", uri,
 
76
                                  "audio-sink", audiosink,
 
77
                                  "video-sink", videosink,
 
78
                                  NULL);
 
79
        
 
80
        return player;
 
81
}
 
82
 
 
83
/**
 
84
 * Free a media player.
 
85
 */
 
86
void
 
87
media_player_free (MediaPlayer *player)
 
88
{
 
89
        if (player->player)
 
90
                gst_object_unref (GST_OBJECT (player->player));
 
91
        
 
92
        g_free (player);
 
93
}
 
94
 
 
95
/**
 
96
 * Set the uri of player.
 
97
 */
 
98
void
 
99
media_player_set_uri (MediaPlayer *player, const gchar *uri)
 
100
{
 
101
        g_object_set (player->player, "uri", uri, NULL);
 
102
}
 
103
 
 
104
/**
 
105
 * Get the uri of player.
 
106
 * 
 
107
 * Free with g_free()
 
108
 */
 
109
gchar *
 
110
media_player_get_uri (MediaPlayer *player)
 
111
{
 
112
        gchar *uri;
 
113
        
 
114
        g_object_get (player->player, "uri", &uri, NULL);
 
115
        
 
116
        return uri;
 
117
}
 
118
 
 
119
/**
 
120
 * Set media player state.
 
121
 */
 
122
void
 
123
media_player_set_state (MediaPlayer *player, MediaPlayerState state)
 
124
{
 
125
        MediaPlayerState old = player->state;
 
126
        
 
127
        player->state = state;
 
128
        
 
129
        // Notify state change handler
 
130
        if (old != state && player->state_changed)
 
131
                player->state_changed(player, player->state, player->state_changed_data);
 
132
}
 
133
 
 
134
 
 
135
/**
 
136
 * Check for errors & call error handler
 
137
 */
 
138
static gboolean
 
139
media_player_bus_check_errors (MediaPlayer *player, GstMessage *message)
 
140
{
 
141
//      g_debug ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
 
142
        
 
143
        switch (GST_MESSAGE_TYPE (message)) {
 
144
        case GST_MESSAGE_ERROR: {
 
145
                GError *err;
 
146
                gchar *debug;
 
147
                
 
148
                gst_message_parse_error (message, &err, &debug);
 
149
                
 
150
                if (player->error_handler)
 
151
                        player->error_handler (player, err, player->error_handler_data);
 
152
                
 
153
                g_error_free (err);
 
154
                g_free (debug);
 
155
                
 
156
                return FALSE;
 
157
                break;
 
158
        }
 
159
        default:
 
160
                break;
 
161
        }
 
162
        
 
163
        // No errors
 
164
        return TRUE;
 
165
}
 
166
 
 
167
/**
 
168
 * GST bus callback.
 
169
 */
 
170
static gboolean
 
171
media_player_bus_cb (GstBus     *bus,
 
172
                                         GstMessage *message,
 
173
                                         MediaPlayer *player)
 
174
{
 
175
//      g_debug ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));
 
176
        
 
177
        if (media_player_bus_check_errors (player, message)) {
 
178
                if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS) {
 
179
                        // End of Stream, do we loop?
 
180
                        if (!player->loop) {
 
181
                                media_player_stop (player);
 
182
                                return FALSE;
 
183
                        }
 
184
                        
 
185
                        // Loop
 
186
                        gst_element_set_state (player->player, GST_STATE_READY);
 
187
                        gst_element_set_state (player->player, GST_STATE_PLAYING);
 
188
                        
 
189
                        media_player_set_state (player, MEDIA_PLAYER_PLAYING);
 
190
                }
 
191
                
 
192
                // Keep notifying us
 
193
                return TRUE;
 
194
        }
 
195
        
 
196
        // There were errors
 
197
        media_player_stop (player);
 
198
        
 
199
        return FALSE;
 
200
}
 
201
 
 
202
/**
 
203
 * Start media player
 
204
 */
 
205
void
 
206
media_player_start (MediaPlayer *player)
 
207
{
 
208
        GstBus *bus;
 
209
        
 
210
        // Attach bus watcher
 
211
        bus = gst_pipeline_get_bus (GST_PIPELINE (player->player));
 
212
        player->watch_id = gst_bus_add_watch (bus, (GstBusFunc) media_player_bus_cb, player);
 
213
        gst_object_unref (bus);
 
214
        
 
215
        gst_element_set_state (player->player, GST_STATE_PLAYING);
 
216
        media_player_set_state (player, MEDIA_PLAYER_PLAYING);
 
217
}
 
218
 
 
219
/**
 
220
 * Stop player
 
221
 */
 
222
void
 
223
media_player_stop (MediaPlayer *player)
 
224
{
 
225
        if (player->watch_id) {
 
226
                g_source_remove (player->watch_id);
 
227
                
 
228
                player->watch_id = 0;
 
229
        }
 
230
        
 
231
        if (player->player != NULL) {
 
232
                gst_element_set_state (player->player, GST_STATE_NULL);
 
233
        }
 
234
        
 
235
        media_player_set_state (player, MEDIA_PLAYER_STOPPED);
 
236
}
 
237
 
 
238
/*
 
239
 * }} Media player
 
240
 */