No issues found
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2007 Christophe Fergeau <teuf@gnome.org>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * The Rhythmbox authors hereby grant permission for non-GPL compatible
11 * GStreamer plugins to be used and distributed together with GStreamer
12 * and Rhythmbox. This permission is above and beyond the permissions granted
13 * by the GPL license by which Rhythmbox is covered. If you modify this code
14 * you may extend this exception to your version of the code, but you are not
15 * obligated to do so. If you do not wish to do so, delete this exception
16 * statement from your version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 */
28
29 #define __EXTENSIONS__
30
31 #include "config.h"
32
33 #include <string.h>
34 #include <time.h>
35
36 #include <glib.h>
37 #include <glib/gi18n.h>
38
39 #include "rb-debug.h"
40 #include "rhythmdb.h"
41 #include <libsoup/soup.h>
42
43 #include "rb-audioscrobbler-entry.h"
44 #include "rb-audioscrobbler-radio-track-entry-type.h"
45
46
47 void
48 rb_audioscrobbler_entry_init (AudioscrobblerEntry *entry)
49 {
50 entry->artist = g_strdup ("");
51 entry->album = g_strdup ("");
52 entry->title = g_strdup ("");
53 entry->length = 0;
54 entry->play_time = 0;
55 entry->mbid = g_strdup ("");
56 entry->source = g_strdup ("P");
57 }
58
59 void
60 rb_audioscrobbler_entry_free (AudioscrobblerEntry *entry)
61 {
62 g_free (entry->artist);
63 g_free (entry->album);
64 g_free (entry->title);
65 g_free (entry->mbid);
66 g_free (entry->source);
67
68 g_free (entry);
69 }
70
71 void
72 rb_audioscrobbler_encoded_entry_free (AudioscrobblerEncodedEntry *entry)
73 {
74 g_free (entry->artist);
75 g_free (entry->album);
76 g_free (entry->title);
77 g_free (entry->mbid);
78 g_free (entry->timestamp);
79 g_free (entry->source);
80 g_free (entry->track);
81
82 g_free (entry);
83 }
84
85
86 AudioscrobblerEntry *
87 rb_audioscrobbler_entry_create (RhythmDBEntry *rb_entry, RBAudioscrobblerService *service)
88 {
89 AudioscrobblerEntry *as_entry = g_new0 (AudioscrobblerEntry, 1);
90
91 as_entry->title = rhythmdb_entry_dup_string (rb_entry, RHYTHMDB_PROP_TITLE);
92 as_entry->track = rhythmdb_entry_get_ulong (rb_entry, RHYTHMDB_PROP_TRACK_NUMBER);
93 as_entry->artist = rhythmdb_entry_dup_string (rb_entry, RHYTHMDB_PROP_ARTIST);
94 as_entry->album = rhythmdb_entry_dup_string (rb_entry, RHYTHMDB_PROP_ALBUM);
95 if (strcmp (as_entry->album, _("Unknown")) == 0) {
96 g_free (as_entry->album);
97 as_entry->album = g_strdup ("");
98 }
99
100 as_entry->length = rhythmdb_entry_get_ulong (rb_entry, RHYTHMDB_PROP_DURATION);
101 as_entry->mbid = rhythmdb_entry_dup_string (rb_entry, RHYTHMDB_PROP_MUSICBRAINZ_TRACKID);
102 if (strcmp (as_entry->mbid, _("Unknown")) == 0) {
103 g_free (as_entry->mbid);
104 as_entry->mbid = g_strdup ("");
105 }
106
107 /* identify the source type. Currently we use:
108 * L for an audioscrobbler-provided radio track when scrobbling to its own service
109 * E for an audioscrobbler-provided radio track when scrobbling to a different service
110 * P for everything else
111 * TODO: Use R or E in some cases instead of P
112 */
113 if (rhythmdb_entry_get_entry_type (rb_entry) == RHYTHMDB_ENTRY_TYPE_AUDIOSCROBBLER_RADIO_TRACK) {
114 RBAudioscrobblerRadioTrackData *track_data;
115 track_data = RHYTHMDB_ENTRY_GET_TYPE_DATA (rb_entry, RBAudioscrobblerRadioTrackData);
116
117 /* only use L if we have an auth code,
118 * and the track is from the correct service (ie not for a Libre.fm track scrobbling to Last.fm)
119 */
120 if (track_data->track_auth != NULL && track_data->service == service) {
121 as_entry->source = g_strdup_printf ("L%s", track_data->track_auth);
122 } else {
123 as_entry->source = g_strdup ("E");
124 }
125 } else {
126 as_entry->source = g_strdup ("P");
127 }
128
129 return as_entry;
130 }
131
132 AudioscrobblerEncodedEntry *
133 rb_audioscrobbler_entry_encode (AudioscrobblerEntry *entry)
134 {
135
136 AudioscrobblerEncodedEntry *encoded;
137
138 encoded = g_new0 (AudioscrobblerEncodedEntry, 1);
139
140 encoded->artist = soup_uri_encode (entry->artist, EXTRA_URI_ENCODE_CHARS);
141 encoded->title = soup_uri_encode (entry->title, EXTRA_URI_ENCODE_CHARS);
142 encoded->album = soup_uri_encode (entry->album, EXTRA_URI_ENCODE_CHARS);
143 encoded->track = g_strdup_printf ("%lu", entry->track);
144
145 encoded->mbid = soup_uri_encode (entry->mbid, EXTRA_URI_ENCODE_CHARS);
146
147 encoded->timestamp = g_strdup_printf("%ld", (long)entry->play_time);
148 encoded->length = entry->length;
149 encoded->source = g_strdup (entry->source);
150
151 return encoded;
152 }
153
154 AudioscrobblerEntry*
155 rb_audioscrobbler_entry_load_from_string (const char *string)
156 {
157 AudioscrobblerEntry *entry;
158 int i = 0;
159 char **breaks;
160
161 entry = g_new0 (AudioscrobblerEntry, 1);
162 rb_audioscrobbler_entry_init (entry);
163
164 breaks = g_strsplit (string, "&", 6);
165
166 for (i = 0; breaks[i] != NULL; i++) {
167 char **breaks2 = g_strsplit (breaks[i], "=", 2);
168
169 if (breaks2[0] != NULL && breaks2[1] != NULL) {
170 if (g_str_has_prefix (breaks2[0], "a")) {
171 g_free (entry->artist);
172 entry->artist = soup_uri_decode (breaks2[1]);
173 }
174 if (g_str_has_prefix (breaks2[0], "t")) {
175 g_free (entry->title);
176 entry->title = soup_uri_decode (breaks2[1]);
177 }
178 if (g_str_has_prefix (breaks2[0], "b")) {
179 g_free (entry->album);
180 entry->album = soup_uri_decode (breaks2[1]);
181 }
182 if (g_str_has_prefix (breaks2[0], "m")) {
183 g_free (entry->mbid);
184 entry->mbid = soup_uri_decode (breaks2[1]);
185 }
186 if (g_str_has_prefix (breaks2[0], "l")) {
187 entry->length = atoi (breaks2[1]);
188 }
189 /* 'I' here is for backwards compatibility with queue files
190 * saved while we were using the 1.1 protocol. see bug 508895.
191 */
192 if (g_str_has_prefix (breaks2[0], "i") ||
193 g_str_has_prefix (breaks2[0], "I")) {
194 entry->play_time = strtol (breaks2[1], NULL, 10);
195 }
196 }
197
198 g_strfreev (breaks2);
199 }
200
201 g_strfreev (breaks);
202
203 if (strcmp (entry->artist, "") == 0 || strcmp (entry->title, "") == 0) {
204 rb_audioscrobbler_entry_free (entry);
205 entry = NULL;
206 }
207
208 return entry;
209 }
210
211 void
212 rb_audioscrobbler_entry_save_to_string (GString *string, AudioscrobblerEntry *entry)
213 {
214 AudioscrobblerEncodedEntry *encoded;
215
216 encoded = rb_audioscrobbler_entry_encode (entry);
217 g_string_append_printf (string,
218 "a=%s&t=%s&b=%s&m=%s&l=%d&i=%ld\n",
219 encoded->artist,
220 encoded->title,
221 encoded->album,
222 encoded->mbid,
223 encoded->length,
224 (long)entry->play_time);
225 rb_audioscrobbler_encoded_entry_free (encoded);
226 }
227
228 void
229 rb_audioscrobbler_entry_debug (AudioscrobblerEntry *entry, int index)
230 {
231 rb_debug ("%-3d artist: %s", index, entry->artist);
232 rb_debug (" album: %s", entry->album);
233 rb_debug (" title: %s", entry->title);
234 rb_debug (" length: %d", entry->length);
235 rb_debug (" playtime: %ld", (long)entry->play_time);
236 }