[Rhythmbox-devel] covert art thingo to play with



Heya,

I was bored at work (about an hour before I head off to my holidays),
and I wrote this little program.

It takes a song title (artist included) and creates a desktop file
(~/.Desktop/rb-current.desktop) with a nifty icon of the cover (see
attached shot).

As I'm going on holiday without any computers, here's a TODO list for
people who want to play:
- make it possible to pass artist and complete title (artist + song
title) separately to get better results
- better icon when there's no cover available, or the cover is the
default empty one.
- cache requests and downloaded images
- add to RB, in the song change code, a way to launch this script.
(which script is used should probably be configurable, via gconf only)
(it should probably also only be launched a couple of seconds into the
song...)

Enjoy

-- 
/Bastien Nocera
http://hadess.net

#2  0x4205a2cc in printf ("Oh my %s\n", preferred_deity) from
/lib/i686/libc.so.6 printf ("Oh my %s\n", preferred_deity);
Segmentation fault

// Under the GPL, hadess@hadess.net
// Compile with:
// gcc -o test-cover `pkg-config --cflags --libs gnome-vfs-2.0 libxml-2.0` test-cover.c


#include <libgnomevfs/gnome-vfs.h>
#include <glib.h>
#include <libxml/tree.h>
#include <libxml/parser.h>

#define SMALL_SIZE  "ImageUrlSmall"
#define MEDIUM_SIZE "ImageUrlMedium"
#define LARGE_SIZE  "ImageUrlLarge"

#define CURRENT_SIZE SMALL_SIZE
#define READ_CHUNK_SIZE 8192

static char *img_url = NULL;

static void
usage (const char *msg)
{
	if (msg != NULL) {
		g_print ("Error: %s\n", msg);
	}
	g_print ("Usage: test-cover <title>\n");
	exit (1);
}

static GnomeVFSResult
my_eel_read_entire_file (const char *uri,
                int *file_size,
                char **file_contents)
{
        GnomeVFSResult result;
        GnomeVFSHandle *handle;
        char *buffer;
        GnomeVFSFileSize total_bytes_read;
        GnomeVFSFileSize bytes_read;
                                                                                
        *file_size = 0;
        *file_contents = NULL;
                                                                                
        /* Open the file. */
        result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
        if (result != GNOME_VFS_OK) {
                return result;
        }
                                                                                
        /* Read the whole thing. */
        buffer = NULL;
        total_bytes_read = 0;
        do {
                buffer = g_realloc (buffer, total_bytes_read + READ_CHUNK_SIZE);                result = gnome_vfs_read (handle,
                                buffer + total_bytes_read,
                                READ_CHUNK_SIZE,
                                &bytes_read);
                if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_EOF) {
                        g_free (buffer);
                        gnome_vfs_close (handle);
                        return result;
                }
                                                                                
                /* Check for overflow. */
                if (total_bytes_read + bytes_read < total_bytes_read) {
                        g_free (buffer);
                        gnome_vfs_close (handle);
                        return GNOME_VFS_ERROR_TOO_BIG;
                }
                                                                                
                total_bytes_read += bytes_read;
        } while (result == GNOME_VFS_OK);

        /* Close the file. */
        result = gnome_vfs_close (handle);
        if (result != GNOME_VFS_OK) {
                g_free (buffer);
                return result;
        }
                                                                                
        /* Return the file. */
        *file_size = total_bytes_read;
        *file_contents = g_realloc (buffer, total_bytes_read);
                                                                                
        return GNOME_VFS_OK;
}

static char *
print_uri (const char *title)
{
	char *escaped, *url;

	/* Construct the URL */
	escaped = gnome_vfs_escape_path_string (title);
	url = g_strdup_printf ("http://xml.amazon.com/onca/xml3?t=hadess@hadess.net&dev-t=D1EEUYQ7Y68BJ3&KeywordSearch=%s&mode=music&sort=+pmrank&offer=All&type=lite&page=&f=xml";, escaped);
	g_free (escaped);

	return url;
}

static gboolean
parse_document (xmlDocPtr doc, xmlNodePtr parent)
{
	xmlNodePtr node;

	for (node = parent->children; node != NULL; node = node->next)
	{
		if (node->name == NULL) {
			continue;
		}

		if (g_ascii_strcasecmp (node->name, LARGE_SIZE) == 0)
		{
			img_url = xmlNodeListGetString (doc, node->children, 1);
			return TRUE;
		}

		if (parse_document (doc, node) != FALSE) {
			return TRUE;
		}
	}
}

static void
parse_xml (const char *url)
{
	int size;
	char *contents = NULL;
	xmlDocPtr doc;
	xmlNodePtr node;

	if (my_eel_read_entire_file (url, &size, &contents) != GNOME_VFS_OK) {
		return;
	}

	contents = g_realloc (contents, size + 1);
	contents[size] = '\0';

	doc = xmlParseMemory (contents, size);
	if (doc == NULL)
		doc = xmlRecoverMemory (contents, size);
	g_free (contents);

	/* If the document has no root, or no name */
	if(!doc || !doc->children || !doc->children->name)
	{
		if (doc != NULL)
			xmlFreeDoc(doc);
		return;
	}

	node = doc->children;
	parse_document (doc, node);
	xmlFreeDoc(doc);
}

static char *
get_desktop_path (void)
{
	char *fullpath;
	gboolean desktop_exists;

	fullpath = g_build_path (G_DIR_SEPARATOR_S, g_get_home_dir (), "Desktop", NULL);
	desktop_exists = g_file_test (fullpath, G_FILE_TEST_EXISTS);
	g_free (fullpath);

	if (desktop_exists == TRUE)
	{
		return g_build_filename (G_DIR_SEPARATOR_S,
				g_get_home_dir (), "Desktop",
				"rb-current.desktop", NULL);
	} else {
		return g_build_filename (G_DIR_SEPARATOR_S,
				g_get_home_dir (), ".gnome-desktop",
				"rb-current.desktop", NULL);
	}

	return NULL;
}

static char *
copy_img_local (const char *url)
{
	GnomeVFSURI *src_uri, *dest_uri;
	GnomeVFSResult result;
	char *dest;

	if (url == NULL) {
		url = "http://g-images.amazon.com/images/G/01/music/icons/music-no-image.gif";;
	}

	dest = g_build_filename (G_DIR_SEPARATOR_S,
			g_get_home_dir (), ".gnome2",
			"rhythmbox", "rb-current.jpg", NULL);

	src_uri = gnome_vfs_uri_new(url);
	dest_uri = gnome_vfs_uri_new(dest);

	result = gnome_vfs_xfer_uri (src_uri, dest_uri,
			GNOME_VFS_XFER_DEFAULT,
			GNOME_VFS_XFER_ERROR_MODE_ABORT,
			GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE,
			NULL, NULL);
	gnome_vfs_uri_unref (src_uri);
	gnome_vfs_uri_unref (dest_uri);

	if (result != GNOME_VFS_OK)
	{
		g_free (dest);
		return NULL;
	}

	return dest;
}

static gboolean
write_string (GnomeVFSHandle *handle, const char *buf)
{
	GnomeVFSResult res;
	GnomeVFSFileSize written;
	int len;

	len = strlen (buf);
	res = gnome_vfs_write (handle, buf, len, &written);
	if (res != GNOME_VFS_OK || written < len)
	{
		gnome_vfs_close (handle);
		return FALSE;
	}
	return TRUE;
}

static void
create_desktop_file (const char *title, const char *icon)
{
	GnomeVFSHandle *handle;
	GnomeVFSResult res;
	char *desktop_path, *str;

	desktop_path = get_desktop_path ();
	if (desktop_path == NULL) {
		return;
	}

	res = gnome_vfs_open (&handle, desktop_path, GNOME_VFS_OPEN_WRITE);
	if (res == GNOME_VFS_ERROR_NOT_FOUND)
	{
		res = gnome_vfs_create (&handle, desktop_path,
				GNOME_VFS_OPEN_WRITE, FALSE,
				GNOME_VFS_PERM_USER_WRITE
				| GNOME_VFS_PERM_USER_READ
				| GNOME_VFS_PERM_GROUP_READ);
	}

	g_free (desktop_path);

	if (res != GNOME_VFS_OK) {
		return;
	}

	write_string (handle, "[Desktop Entry]\n");
	write_string (handle, "Encoding=UTF-8\n");

	str = g_strdup_printf ("Name=%s\n", title);
	write_string (handle, str);
	g_free (str);

	write_string (handle, "Exec=rhythmbox\n");

	if (icon != NULL) {
		str = g_strdup_printf ("Icon=%s\n", icon);
	} else {
		str = g_strdup ("Icon=\n");
	}
	write_string (handle, str);
	g_free (str);

	write_string (handle, "Terminal=0\n");
	write_string (handle, "Type=Application\n");

	gnome_vfs_close (handle);
}

int main (int argc, char **argv)
{
	char *url, *icon;

	if (argc != 2) {
		usage (NULL);
	}

	if (gnome_vfs_init () == FALSE) {
		usage ("Can't initialise gnome-vfs");
	}

	url = print_uri (argv[1]);
	parse_xml (url);
	g_free (url);

	icon = copy_img_local (img_url);
	create_desktop_file (argv[1], icon);

	return 0;
}

test-cover.png



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]