static void entry_parsed (TotemPlParser *parser, gchar *to_uri, GHashTable *to_metadata, gpointer user_data) { PlaylistMetadata *data; data = (PlaylistMetadata *) user_data; data->track_counter++; if (data->track_counter > 1000) { /* limit playlists to 1000 entries for query performance reasons */ g_message ("Playlist has > 1000 entries. Ignoring for performance reasons."); return; } if (data->track_counter == 1) { /* first track, predicate needed */ tracker_sparql_builder_predicate (data->metadata, "nfo:hasMediaFileListEntry"); } tracker_sparql_builder_object_blank_open (data->metadata); tracker_sparql_builder_predicate (data->metadata, "a"); tracker_sparql_builder_object (data->metadata, "nfo:MediaFileListEntry"); tracker_sparql_builder_predicate (data->metadata, "nfo:entryUrl"); tracker_sparql_builder_object_unvalidated (data->metadata, to_uri); tracker_sparql_builder_predicate (data->metadata, "nfo:listPosition"); tracker_sparql_builder_object_int64 (data->metadata, (gint64) data->track_counter); tracker_sparql_builder_object_blank_close (data->metadata); if (to_metadata) { gchar *duration; duration = g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_DURATION); if (duration == NULL) { duration = g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_DURATION_MS); } if (duration != NULL) { gint64 secs = totem_pl_parser_parse_duration (duration, FALSE); if (secs > 0) { data->total_time += secs; } } } }
static void entry_metadata_foreach (const char *key, const char *value, gpointer data) { RBPodcastItem *item = (RBPodcastItem *) data; if (strcmp (key, TOTEM_PL_PARSER_FIELD_TITLE) == 0) { item->title = g_strdup (value); } else if (strcmp (key, TOTEM_PL_PARSER_FIELD_URI) == 0) { item->url = g_strdup (value); } else if (strcmp (key, TOTEM_PL_PARSER_FIELD_DESCRIPTION) == 0) { item->description = g_strdup (value); } else if (strcmp (key, TOTEM_PL_PARSER_FIELD_AUTHOR) == 0) { item->author = g_strdup (value); } else if (strcmp (key, TOTEM_PL_PARSER_FIELD_PUB_DATE) == 0) { item->pub_date = totem_pl_parser_parse_date (value, FALSE); } else if (strcmp (key, TOTEM_PL_PARSER_FIELD_DURATION) == 0) { item->duration = totem_pl_parser_parse_duration (value, FALSE); } else if (strcmp (key, TOTEM_PL_PARSER_FIELD_FILESIZE) == 0) { item->filesize = g_ascii_strtoull (value, NULL, 10); } }
TotemPlParserResult totem_pl_parser_add_m3u (TotemPlParser *parser, GFile *file, GFile *base_file, TotemPlParseData *parse_data, gpointer data) { TotemPlParserResult retval = TOTEM_PL_PARSER_RESULT_UNHANDLED; char *contents, **lines; gsize size; guint i, num_lines; gboolean dos_mode = FALSE; const char *extinfo, *extvlcopt_audiotrack; char *pl_uri; if (g_file_load_contents (file, NULL, &contents, &size, NULL, NULL) == FALSE) { DEBUG (file, g_print ("Failed to load '%s'\n", uri)); return TOTEM_PL_PARSER_RESULT_ERROR; } /* .pls files with a .m3u extension, the nasties */ if (g_str_has_prefix (contents, "[playlist]") != FALSE || g_str_has_prefix (contents, "[Playlist]") != FALSE || g_str_has_prefix (contents, "[PLAYLIST]") != FALSE) { DEBUG (file, g_print ("Parsing '%s' playlist as PLS\n", uri)); retval = totem_pl_parser_add_pls_with_contents (parser, file, base_file, contents, parse_data); g_free (contents); return retval; } if (strstr (contents, EXTINF_HLS) || strstr (contents, EXTINF_HLS2)) { DEBUG (file, g_print ("Unhandled HLS playlist '%s', should be passed to player\n", uri)); g_free (contents); return retval; } /* Try to use ISO-8859-1 if we don't have valid UTF-8, * try to parse anyway if it's not ISO-8859-1 */ if (g_utf8_validate (contents, -1, NULL) == FALSE) { char *fixed; fixed = g_convert (contents, -1, "UTF-8", "ISO8859-1", NULL, NULL, NULL); if (fixed != NULL) { g_free (contents); contents = fixed; } } /* is non-NULL if there's an EXTINF on a preceding line */ extinfo = NULL; extvlcopt_audiotrack = NULL; /* figure out whether we're a unix m3u or dos m3u */ if (strstr(contents, "\x0d")) { dos_mode = TRUE; } lines = g_strsplit_set (contents, "\r\n", 0); g_free (contents); num_lines = g_strv_length (lines); /* We don't count the terminating NULL */ num_lines--; /* Send out the playlist start and get crackin' */ pl_uri = g_file_get_uri (file); totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_IS_PLAYLIST, TRUE, TOTEM_PL_PARSER_FIELD_URI, pl_uri, TOTEM_PL_PARSER_FIELD_CONTENT_TYPE, "audio/x-mpegurl", NULL); for (i = 0; lines[i] != NULL; i++) { const char *line; char *length; gint64 length_num = 0; char *audio_track; line = lines[i]; if (line[0] == '\0') continue; retval = TOTEM_PL_PARSER_RESULT_SUCCESS; /* Ignore leading spaces */ for (; g_ascii_isspace (line[0]); line++) ; /* Ignore comments, but mark it if we have extra info */ if (line[0] == '#') { if (extinfo == NULL && g_str_has_prefix (line, EXTINF) != FALSE) extinfo = line; if (extvlcopt_audiotrack == NULL && g_str_has_prefix (line, EXTVLCOPT_AUDIOTRACK) != FALSE) extvlcopt_audiotrack = line; continue; } length = totem_pl_parser_get_extinfo_length (extinfo); if (length != NULL) length_num = totem_pl_parser_parse_duration (length, totem_pl_parser_is_debugging_enabled (parser)); g_free (length); audio_track = totem_pl_parser_get_extvlcopt_audio_track (extvlcopt_audiotrack); /* Either it's a URI, or it has a proper path ... */ if (strstr(line, "://") != NULL || line[0] == G_DIR_SEPARATOR) { GFile *uri; uri = g_file_new_for_commandline_arg (line); if (length_num < 0 || totem_pl_parser_parse_internal (parser, uri, NULL, parse_data) != TOTEM_PL_PARSER_RESULT_SUCCESS) { totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_URI, line, TOTEM_PL_PARSER_FIELD_TITLE, totem_pl_parser_get_extinfo_title (extinfo), TOTEM_PL_PARSER_FIELD_AUDIO_TRACK, audio_track, NULL); } g_object_unref (uri); } else if (g_ascii_isalpha (line[0]) != FALSE && g_str_has_prefix (line + 1, ":\\")) { /* Path relative to a drive on Windows, we need to use * the base that was passed to us */ GFile *uri; lines[i] = g_strdelimit (lines[i], "\\", '/'); /* + 2, skip drive letter */ uri = g_file_get_child (base_file, line + 2); totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_FILE, uri, TOTEM_PL_PARSER_FIELD_TITLE, totem_pl_parser_get_extinfo_title (extinfo), TOTEM_PL_PARSER_FIELD_AUDIO_TRACK, audio_track, NULL); g_object_unref (uri); } else if (line[0] == '\\' && line[1] == '\\') { /* ... Or it's in the windows smb form * (\\machine\share\filename), Note drive names * (C:\ D:\ etc) are unhandled (unknown base for * drive letters) */ char *tmpuri; lines[i] = g_strdelimit (lines[i], "\\", '/'); tmpuri = g_strjoin (NULL, "smb:", line, NULL); totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_URI, tmpuri, TOTEM_PL_PARSER_FIELD_TITLE, totem_pl_parser_get_extinfo_title (extinfo), TOTEM_PL_PARSER_FIELD_AUDIO_TRACK, audio_track, NULL); g_free (tmpuri); } else { /* Try with a base */ GFile *uri, *_base_file; char sep; _base_file = g_file_get_parent (file); sep = (dos_mode ? '\\' : '/'); if (sep == '\\') lines[i] = g_strdelimit (lines[i], "\\", '/'); uri = g_file_get_child (_base_file, line); g_object_unref (_base_file); totem_pl_parser_add_uri (parser, TOTEM_PL_PARSER_FIELD_FILE, uri, TOTEM_PL_PARSER_FIELD_TITLE, totem_pl_parser_get_extinfo_title (extinfo), TOTEM_PL_PARSER_FIELD_AUDIO_TRACK, audio_track, NULL); g_object_unref (uri); } extinfo = NULL; extvlcopt_audiotrack = NULL; g_free (audio_track); } g_strfreev (lines); totem_pl_parser_playlist_end (parser, pl_uri); g_free (pl_uri); return retval; }