changelog, control, README fixes
[nowplayingd] / nowplaying.c
1 /** Code is released under GPLv2
2  *
3  * See debian/copyright for copyright info
4  */
5
6 /** Compile binary only with:
7  * gcc -Wall `pkg-config --cflags --libs hildon-notify glib-2.0 mafw mafw-shared` nowplaying.c -o nowplayingd
8  */
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <glib.h>
13 #include <libintl.h>
14 #include <locale.h>
15 #include <hildon/hildon-notification.h>
16 #include <libmafw/mafw.h>
17 #include <libmafw-shared/mafw-shared.h>
18
19 #define WANTED_RENDERER "Mafw-Gst-Renderer"
20
21 static GMainLoop *loop = NULL;
22 static MafwRegistry *registry = NULL;
23
24 static void sig_handler( int sig G_GNUC_UNUSED )
25 {
26         if ( g_main_loop_is_running( loop ) ) {
27                 g_main_loop_quit( loop );
28         }
29 }
30
31 static gchar* filename_from_object_id(
32         const gchar *object_id)
33 {
34         /* TODO: Strip off the extension */
35         g_return_val_if_fail (object_id, NULL);
36
37         gchar *path_uri = g_filename_display_basename( object_id ); /* Remove "localtagfs::music/songs". Pointer arith. would probably work, but I don't wan't to hardcode anything. */
38         gchar *path_unescaped = g_uri_unescape_string( path_uri, NULL ); /* Make the string look normal */
39         gchar *ret_filename = g_filename_display_basename( path_unescaped ); /* Get the filename w/out path */
40
41         g_free (path_uri);
42         g_free (path_unescaped);
43
44         return ret_filename ? ret_filename : NULL;
45 }
46
47 static void metadata_callback(
48         const MafwRenderer *self G_GNUC_UNUSED,
49         const gchar *object_id,
50         GHashTable *metadata,
51         gconstpointer user_data G_GNUC_UNUSED,
52         const GError *error G_GNUC_UNUSED )
53 {
54         gchar *title = NULL;
55         const gchar *artist = NULL;
56         HildonNotification *n = NULL;
57
58         /* First: Try to get title and artist strings from tags: */
59         title = g_value_dup_string( mafw_metadata_first ( metadata, MAFW_METADATA_KEY_TITLE ) );
60         artist = g_value_get_string( mafw_metadata_first ( metadata, MAFW_METADATA_KEY_ARTIST ) );
61
62         /* Secondly: If getting the title from the tags fails, fallback to the filename, instead: */
63         if ( !title || *title == '\0' ) /* || !strcmp (title, "")) */ {
64                 title = filename_from_object_id ( object_id );
65         }
66
67         /* Thirdly: If above fails, we just resort to "(unknown song)" */
68         if ( !title || *title == '\0' ) /* || !strcmp (title, "")) */ {
69                 title = g_strdup( dgettext( "mediaplayer", "mp_li_unknown_song" ) );
70         }
71
72         if ( !artist || *artist == '\0' ) /* || !strcmp (artist, "")) */ {
73                 artist = g_dgettext( "mediaplayer", "mp_li_unknown_artist" );
74         }
75
76         n = hildon_notification_new( artist, title, "tasklaunch_media_player", "media" );
77         hildon_notification_add_dbus_action( n, "default",
78                 "tasklaunch_media_player",
79                 "com.nokia.mediaplayer",
80                 "/com/nokia/osso/mediaplayer",
81                 "com.nokia.mediaplayer",
82                 "open_mp_now_playing",
83                 G_TYPE_NONE, NULL,
84                 -1 );
85
86         notify_notification_set_timeout( NOTIFY_NOTIFICATION( n ), 4500 /* 4.5s */ );
87         notify_notification_show( NOTIFY_NOTIFICATION( n ), NULL );
88
89         g_free ( title );
90 }
91
92 static void state_changed_cb(
93         MafwRenderer *renderer,
94         const MafwPlayState state,
95         gconstpointer user_data G_GNUC_UNUSED)
96 {
97         switch (state) {
98                 case Playing:
99                         mafw_renderer_get_current_metadata( renderer,
100                                 (MafwRendererMetadataResultCB) metadata_callback,
101                                 NULL );
102                         break;
103
104                 case Stopped:
105                 default:
106                         break;
107   }
108 }
109
110 static void renderer_removed_cb(
111         const MafwRegistry *registry2 G_GNUC_UNUSED,
112         GObject *renderer,
113         gconstpointer user_data G_GNUC_UNUSED)
114 {
115         if ( MAFW_IS_RENDERER( renderer ) ) {
116                 const gchar *name = mafw_extension_get_name( MAFW_EXTENSION( renderer ) );
117
118                 if ( !strcmp( name, WANTED_RENDERER ) ) {
119                         g_signal_handlers_disconnect_by_func( renderer, G_CALLBACK( state_changed_cb ), NULL );
120                 }
121         }
122 }
123
124 static void renderer_added_cb(
125         const MafwRegistry *registry2 G_GNUC_UNUSED,
126         GObject *renderer,
127         gconstpointer user_data G_GNUC_UNUSED)
128 {
129         if ( MAFW_IS_RENDERER( renderer ) ) {
130                 const gchar *name = mafw_extension_get_name( MAFW_EXTENSION( renderer ) );
131
132                 if ( !strcmp( name, WANTED_RENDERER ) ) {
133                         g_signal_connect( renderer, "state-changed", G_CALLBACK (state_changed_cb), NULL );
134                 }
135         }
136 }
137
138 static void mafw_deinit( void )
139 {
140     GList *renderers = NULL;
141
142         g_signal_handlers_disconnect_by_func( registry, G_CALLBACK( renderer_removed_cb ), NULL );
143         renderers = mafw_registry_get_renderers( registry );
144         while ( renderers ) {
145                 renderer_removed_cb( registry, G_OBJECT( renderers->data ), NULL );
146                 renderers = g_list_next( renderers );
147         }
148 }
149
150 static void mafw_init( void )
151 {
152     GList *renderers = NULL;
153
154         g_signal_connect( registry, "renderer-added", G_CALLBACK( renderer_added_cb ), NULL );
155         renderers = mafw_registry_get_renderers( registry );
156         while ( renderers ) {
157                 renderer_added_cb( registry, G_OBJECT( renderers->data ), NULL );
158                 renderers = g_list_next( renderers );
159         }
160 }
161
162 int main (void)
163 {
164         setlocale( LC_ALL, "" );
165
166         g_type_init();
167         notify_init("nowplayingd");
168
169         loop = g_main_loop_new( NULL, FALSE );
170         g_assert( loop );
171
172         registry = MAFW_REGISTRY( mafw_registry_get_instance() );
173         g_assert( registry );
174
175         signal( SIGINT, sig_handler );
176         signal( SIGQUIT, sig_handler );
177         signal( SIGTERM, sig_handler );
178
179         mafw_shared_init( registry, NULL );
180
181         mafw_init();
182
183         g_main_loop_run( loop );
184
185         g_main_loop_unref( loop );
186
187         mafw_deinit();
188
189         mafw_shared_deinit();
190
191         notify_uninit();
192
193         return EXIT_SUCCESS;
194 }
195