Skip to content

Commit

Permalink
Support multiple playlist formats with the same extension (i.e. ASXv1…
Browse files Browse the repository at this point in the history
…/v2 and ASXv3, which are totally different).
  • Loading branch information
jlindgren90 committed Jun 9, 2013
1 parent d0f2f0b commit 574af96
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 82 deletions.
177 changes: 104 additions & 73 deletions src/audacious/playlist-files.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* playlist-files.c
* Copyright 2010-2011 John Lindgren
* Copyright 2010-2013 John Lindgren
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
Expand All @@ -27,81 +27,98 @@
#include "plugin.h"
#include "plugins.h"

static PluginHandle * get_plugin_silent (const char * filename)
typedef struct
{
char buf[32];
if (! uri_get_extension (filename, buf, sizeof buf))
return NULL;

return playlist_plugin_for_extension (buf);
const char * filename;
char * title;
Index * filenames;
Index * tuples;
bool_t plugin_found;
bool_t success;
}
PlaylistData;

bool_t filename_is_playlist (const char * filename)
static void plugin_for_filename (const char * filename, PluginForEachFunc func, void * data)
{
return (get_plugin_silent (filename) != NULL);
char ext[32];
if (uri_get_extension (filename, ext, sizeof ext))
playlist_plugin_for_ext (ext, func, data);
}

static PluginHandle * get_plugin (const char * filename, bool_t saving)
static bool_t plugin_found_cb (PluginHandle * plugin, void * data)
{
PluginHandle * plugin = get_plugin_silent (filename);

if (! plugin)
{
char * error = str_printf (_("Cannot %s %s: unsupported file "
"extension."), saving ? _("save") : _("load"), filename);
interface_show_error (error);
str_unref (error);
return NULL;
}

return plugin;
* (PluginHandle * *) data = plugin;
return FALSE; /* stop when first plugin is found */
}

bool_t playlist_load (const char * filename, char * * title,
Index * * filenames_p, Index * * tuples_p)
bool_t filename_is_playlist (const char * filename)
{
AUDDBG ("Loading playlist %s.\n", filename);
PluginHandle * plugin = NULL;
plugin_for_filename (filename, plugin_found_cb, & plugin);
return (plugin != NULL);
}

PluginHandle * plugin = get_plugin (filename, FALSE);
if (! plugin)
return FALSE;
static bool_t playlist_load_cb (PluginHandle * plugin, void * data_)
{
PlaylistData * data = (PlaylistData *) data_;

PlaylistPlugin * pp = plugin_get_header (plugin);
g_return_val_if_fail (pp && PLUGIN_HAS_FUNC (pp, load), FALSE);
if (! pp || ! PLUGIN_HAS_FUNC (pp, load))
return TRUE; /* try another plugin */

VFSFile * file = vfs_fopen (filename, "r");
data->plugin_found = TRUE;

VFSFile * file = vfs_fopen (data->filename, "r");
if (! file)
return FALSE;
return FALSE; /* stop if we can't open file */

Index * filenames = index_new ();
Index * tuples = index_new ();
bool_t success = pp->load (filename, file, title, filenames, tuples);
data->success = pp->load (data->filename, file, & data->title, data->filenames, data->tuples);

vfs_fclose (file);
return ! data->success; /* stop when playlist is loaded */
}

if (! success)
bool_t playlist_load (const char * filename, char * * title, Index * * filenames, Index * * tuples)
{
PlaylistData data =
{
index_free (filenames);
index_free (tuples);
.filename = filename,
.filenames = index_new (),
.tuples = index_new ()
};

AUDDBG ("Loading playlist %s.\n", filename);
plugin_for_filename (filename, playlist_load_cb, & data);

if (! data.plugin_found)
{
SPRINTF (error, _("Cannot load %s: unsupported file extension."), filename);
interface_show_error (error);
}

if (! data.success)
{
str_unref (data.title);
index_free (data.filenames);
index_free (data.tuples);
return FALSE;
}

if (index_count (tuples))
g_return_val_if_fail (index_count (tuples) == index_count (filenames),
FALSE);
if (index_count (data.tuples))
g_return_val_if_fail (index_count (data.tuples) == index_count (data.filenames), FALSE);
else
{
index_free (tuples);
tuples = NULL;
index_free (data.tuples);
data.tuples = NULL;
}

* filenames_p = filenames;
* tuples_p = tuples;
* title = data.title;
* filenames = data.filenames;
* tuples = data.tuples;
return TRUE;
}

bool_t playlist_insert_playlist_raw (int list, int at,
const char * filename)
bool_t playlist_insert_playlist_raw (int list, int at, const char * filename)
{
char * title = NULL;
Index * filenames, * tuples;
Expand All @@ -118,52 +135,66 @@ bool_t playlist_insert_playlist_raw (int list, int at,
return TRUE;
}

bool_t playlist_save (int list, const char * filename)
static bool_t playlist_save_cb (PluginHandle * plugin, void * data_)
{
AUDDBG ("Saving playlist %s.\n", filename);

PluginHandle * plugin = get_plugin (filename, TRUE);
if (! plugin)
return FALSE;
PlaylistData * data = data_;

PlaylistPlugin * pp = plugin_get_header (plugin);
g_return_val_if_fail (pp && PLUGIN_HAS_FUNC (pp, load), FALSE);
if (! pp || ! PLUGIN_HAS_FUNC (pp, save))
return TRUE; /* try another plugin */

bool_t fast = get_bool (NULL, "metadata_on_play");
data->plugin_found = TRUE;

VFSFile * file = vfs_fopen (filename, "w");
VFSFile * file = vfs_fopen (data->filename, "w");
if (! file)
return FALSE;
return FALSE; /* stop if we can't open file */

data->success = pp->save (data->filename, file, data->title, data->filenames, data->tuples);

vfs_fclose (file);
return FALSE; /* stop after first attempt (successful or not) */
}

char * title = playlist_get_title (list);
bool_t playlist_save (int list, const char * filename)
{
PlaylistData data =
{
.filename = filename,
.title = playlist_get_title (list),
.filenames = index_new (),
.tuples = index_new ()
};

int entries = playlist_entry_count (list);
Index * filenames = index_new ();
index_allocate (filenames, entries);
Index * tuples = index_new ();
index_allocate (tuples, entries);
bool_t fast = get_bool (NULL, "metadata_on_play");

index_allocate (data.filenames, entries);
index_allocate (data.tuples, entries);

for (int i = 0; i < entries; i ++)
{
index_append (filenames, playlist_entry_get_filename (list, i));
index_append (tuples, playlist_entry_get_tuple (list, i, fast));
index_append (data.filenames, playlist_entry_get_filename (list, i));
index_append (data.tuples, playlist_entry_get_tuple (list, i, fast));
}

bool_t success = pp->save (filename, file, title, filenames, tuples);
AUDDBG ("Saving playlist %s.\n", filename);
plugin_for_filename (filename, playlist_save_cb, & data);

vfs_fclose (file);
str_unref (title);
if (! data.plugin_found)
{
SPRINTF (error, _("Cannot save %s: unsupported file extension."), filename);
interface_show_error (error);
}

for (int i = 0; i < entries; i ++)
{
str_unref (index_get (filenames, i));
Tuple * tuple = index_get (tuples, i);
if (tuple)
tuple_unref (tuple);
str_unref (index_get (data.filenames, i));
tuple_unref (index_get (data.tuples, i));
}

index_free (filenames);
index_free (tuples);
str_unref (data.title);
index_free (data.filenames);
index_free (data.tuples);

return success;
return data.success;
}
11 changes: 5 additions & 6 deletions src/audacious/plugin-registry.c
Original file line number Diff line number Diff line change
Expand Up @@ -754,7 +754,8 @@ PluginHandle * transport_plugin_for_scheme (const char * scheme)

typedef struct {
const char * ext;
PluginHandle * plugin;
PluginForEachFunc func;
void * data;
} PlaylistPluginForExtState;

static bool_t playlist_plugin_for_ext_cb (PluginHandle * plugin,
Expand All @@ -764,16 +765,14 @@ static bool_t playlist_plugin_for_ext_cb (PluginHandle * plugin,
(GCompareFunc) g_ascii_strcasecmp))
return TRUE;

state->plugin = plugin;
return FALSE;
return state->func (plugin, state->data);
}

PluginHandle * playlist_plugin_for_extension (const char * extension)
void playlist_plugin_for_ext (const char * ext, PluginForEachFunc func, void * data)
{
PlaylistPluginForExtState state = {extension, NULL};
PlaylistPluginForExtState state = {ext, func, data};
plugin_for_enabled (PLUGIN_TYPE_PLAYLIST, (PluginForEachFunc)
playlist_plugin_for_ext_cb, & state);
return state.plugin;
}

typedef struct {
Expand Down
6 changes: 3 additions & 3 deletions src/audacious/plugins.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <audacious/types.h>
#include <libaudcore/core.h>

/* returns TRUE to call again for the next plugin, FALSE to stop */
typedef bool_t (* PluginForEachFunc) (PluginHandle * plugin, void * data);

#define AUD_API_NAME PluginsAPI
Expand Down Expand Up @@ -58,9 +59,8 @@ void plugin_set_enabled (PluginHandle * plugin, bool_t enabled);
void * plugin_get_misc_data (PluginHandle * plugin, int size);

PluginHandle * transport_plugin_for_scheme (const char * scheme);
PluginHandle * playlist_plugin_for_extension (const char * extension);
void input_plugin_for_key (int key, const char * value, PluginForEachFunc
func, void * data);
void playlist_plugin_for_ext (const char * ext, PluginForEachFunc func, void * data);
void input_plugin_for_key (int key, const char * value, PluginForEachFunc func, void * data);
bool_t input_plugin_has_images (PluginHandle * plugin);
bool_t input_plugin_has_subtunes (PluginHandle * plugin);
bool_t input_plugin_can_write_tuple (PluginHandle * plugin);
Expand Down

0 comments on commit 574af96

Please sign in to comment.