/** * Simple data fetcher. * @param url path or url of data to fetch. * @return data fetched, or NULL on error. Must be freed with g_free. */ static char * lastfm_get(const char *url, GMutex *mutex, GCond *cond) { struct input_stream *input_stream; GError *error = NULL; char buffer[4096]; size_t length = 0, nbytes; input_stream = input_stream_open(url, mutex, cond, &error); if (input_stream == NULL) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } return NULL; } g_mutex_lock(mutex); input_stream_wait_ready(input_stream); do { nbytes = input_stream_read(input_stream, buffer + length, sizeof(buffer) - length, &error); if (nbytes == 0) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } if (input_stream_eof(input_stream)) break; /* I/O error */ g_mutex_unlock(mutex); input_stream_close(input_stream); return NULL; } length += nbytes; } while (length < sizeof(buffer)); g_mutex_unlock(mutex); input_stream_close(input_stream); return g_strndup(buffer, length); }
static int dump_input_stream(struct input_stream *is) { GError *error = NULL; input_stream_lock(is); /* wait until the stream becomes ready */ input_stream_wait_ready(is); if (!input_stream_check(is, &error)) { g_warning("%s", error->message); g_error_free(error); input_stream_unlock(is); return EXIT_FAILURE; } /* read data and tags from the stream */ input_stream_unlock(is); struct text_input_stream *tis = text_input_stream_new(is); dump_text_file(tis); text_input_stream_free(tis); input_stream_lock(is); if (!input_stream_check(is, &error)) { g_warning("%s", error->message); g_error_free(error); input_stream_unlock(is); return EXIT_FAILURE; } input_stream_unlock(is); return 0; }
static struct playlist_provider * lastfm_open_uri(const char *uri, GMutex *mutex, GCond *cond) { struct lastfm_playlist *playlist; GError *error = NULL; char *p, *q, *response, *session; /* handshake */ p = g_strconcat("http://ws.audioscrobbler.com/radio/handshake.php?" "version=1.1.1&platform=linux&" "username="******"&" "passwordmd5=", lastfm_config.md5, "&" "debug=0&partner=", NULL); response = lastfm_get(p, mutex, cond); g_free(p); if (response == NULL) return NULL; /* extract session id from response */ session = lastfm_find(response, "session"); g_free(response); if (session == NULL) { g_warning("last.fm handshake failed"); return NULL; } q = g_uri_escape_string(session, NULL, false); g_free(session); session = q; g_debug("session='%s'", session); /* "adjust" last.fm radio */ if (strlen(uri) > 9) { char *escaped_uri; escaped_uri = g_uri_escape_string(uri, NULL, false); p = g_strconcat("http://ws.audioscrobbler.com/radio/adjust.php?" "session=", session, "&url=", escaped_uri, "&debug=0", NULL); g_free(escaped_uri); response = lastfm_get(p, mutex, cond); g_free(response); g_free(p); if (response == NULL) { g_free(session); return NULL; } } /* create the playlist object */ playlist = g_new(struct lastfm_playlist, 1); playlist_provider_init(&playlist->base, &lastfm_playlist_plugin); /* open the last.fm playlist */ p = g_strconcat("http://ws.audioscrobbler.com/radio/xspf.php?" "sk=", session, "&discovery=0&desktop=1.5.1.31879", NULL); g_free(session); playlist->is = input_stream_open(p, mutex, cond, &error); g_free(p); if (playlist->is == NULL) { if (error != NULL) { g_warning("Failed to load XSPF playlist: %s", error->message); g_error_free(error); } else g_warning("Failed to load XSPF playlist"); g_free(playlist); return NULL; } g_mutex_lock(mutex); input_stream_wait_ready(playlist->is); /* last.fm does not send a MIME type, we have to fake it here :-( */ g_free(playlist->is->mime); playlist->is->mime = g_strdup("application/xspf+xml"); g_mutex_unlock(mutex); /* parse the XSPF playlist */ playlist->xspf = playlist_list_open_stream(playlist->is, NULL); if (playlist->xspf == NULL) { input_stream_close(playlist->is); g_free(playlist); g_warning("Failed to parse XSPF playlist"); return NULL; } return &playlist->base; }
static int dump_input_stream(struct input_stream *is) { GError *error = NULL; char buffer[4096]; size_t num_read; ssize_t num_written; input_stream_lock(is); /* wait until the stream becomes ready */ input_stream_wait_ready(is); if (!input_stream_check(is, &error)) { g_warning("%s", error->message); g_error_free(error); input_stream_unlock(is); return EXIT_FAILURE; } /* print meta data */ if (is->mime != NULL) g_printerr("MIME type: %s\n", is->mime); /* read data and tags from the stream */ while (!input_stream_eof(is)) { struct tag *tag = input_stream_tag(is); if (tag != NULL) { g_printerr("Received a tag:\n"); tag_save(stderr, tag); tag_free(tag); } num_read = input_stream_read(is, buffer, sizeof(buffer), &error); if (num_read == 0) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } break; } num_written = write(1, buffer, num_read); if (num_written <= 0) break; } if (!input_stream_check(is, &error)) { g_warning("%s", error->message); g_error_free(error); input_stream_unlock(is); return EXIT_FAILURE; } input_stream_unlock(is); return 0; }
/** * Read JSON data and parse it using the given YAJL parser. * @param url URL of the JSON data. * @param hand YAJL parser handle. * @return -1 on error, 0 on success. */ static int soundcloud_parse_json(const char *url, yajl_handle hand, GMutex* mutex, GCond* cond) { struct input_stream *input_stream; GError *error = NULL; char buffer[4096]; unsigned char *ubuffer = (unsigned char *)buffer; size_t nbytes; input_stream = input_stream_open(url, mutex, cond, &error); if (input_stream == NULL) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } return -1; } g_mutex_lock(mutex); input_stream_wait_ready(input_stream); yajl_status stat; int done = 0; while (!done) { nbytes = input_stream_read(input_stream, buffer, sizeof(buffer), &error); if (nbytes == 0) { if (error != NULL) { g_warning("%s", error->message); g_error_free(error); } if (input_stream_eof(input_stream)) { done = true; } else { g_mutex_unlock(mutex); input_stream_close(input_stream); return -1; } } if (done) stat = yajl_parse_complete(hand); else stat = yajl_parse(hand, ubuffer, nbytes); if (stat != yajl_status_ok && stat != yajl_status_insufficient_data) { unsigned char *str = yajl_get_error(hand, 1, ubuffer, nbytes); g_warning("%s", str); yajl_free_error(hand, str); break; } } g_mutex_unlock(mutex); input_stream_close(input_stream); return 0; }