예제 #1
0
/*
MpdData_head *mpd_data_get_head(MpdData const * const data) {
	return ((MpdData_real*)data)->head;
}
*/
MpdData* mpd_data_concatenate( MpdData  * const first, MpdData  * const second) 
{
	MpdData_real *first_real  = (MpdData_real*)first;
	MpdData_real *second_real = (MpdData_real*)second;
	MpdData_real *first_head  = NULL;

	if ( first == NULL ) {
		if ( second != NULL ) 
			return (MpdData*)second_real;
		else
			return NULL;
	} else {
		if ( second == NULL )
			return (MpdData*)first_real;
	}

	first_head = (MpdData_real *)mpd_data_get_first(first);

	/* find last element in first data list */	
	while (!mpd_data_is_last((MpdData*)first_real)) first_real = (MpdData_real*)mpd_data_get_next_real((MpdData*)first_real, FALSE);
	second_real =(MpdData_real*) mpd_data_get_first((MpdData*)second_real);

	first_real->next = second_real;
	second_real->prev = first_real;

	/* I need to set all the -> first correct */
	while (second_real)
	{
		second_real->first = first_head;
		second_real = (MpdData_real*)mpd_data_get_next_real((MpdData*)second_real, FALSE);
	} 

	return (MpdData*)first_head;
}
예제 #2
0
MpdData* magnatune_db_get_song_list(const char *wanted_genre,const char *wanted_artist, const char *wanted_album, gboolean exact)
{
    MpdData *data = NULL;
    char *query;

    if(!wanted_genre && !wanted_artist && !wanted_album) return NULL;

    GTimer *timer = g_timer_new();
    if(wanted_album) /* album seems to be unique */
    {
        data = __magnatune_get_data_album(wanted_album, exact);
    }else if (wanted_genre && !wanted_artist)
    {
        data = __magnatune_get_data_album_from_genre(wanted_genre, exact);
    }
    else 
    {
        char **albums = __magnatune_get_albums(wanted_genre, wanted_artist, exact);
        if(albums)
        {
            int i;
            for(i=0; albums[i];i++)
            {
                MpdData *data2 =  __magnatune_get_data_album(albums[i], exact);
                data = mpd_data_concatenate(data, data2);
            }
            g_strfreev(albums);
        }
    }

    g_debug("%f s elapsed song list\n", g_timer_elapsed(timer,NULL));
    g_timer_destroy(timer);
    return mpd_data_get_first(data);
}
예제 #3
0
MpdData * mpd_server_get_output_devices(MpdObj *mi)
{
    mpd_OutputEntity *output = NULL;
    MpdData *data = NULL;
    if(!mpd_check_connected(mi))
    {
        debug_printf(DEBUG_WARNING,"not connected\n");
        return NULL;
    }
    /* TODO: Check version */
    if(mpd_lock_conn(mi))
    {
        debug_printf(DEBUG_ERROR,"lock failed\n");
        return NULL;
    }

    mpd_sendOutputsCommand(mi->connection);
    while (( output = mpd_getNextOutput(mi->connection)) != NULL)
    {	
        data = mpd_new_data_struct_append(data);
        data->type = MPD_DATA_TYPE_OUTPUT_DEV; 
        data->output_dev = output;
    }
    mpd_finishCommand(mi->connection);

    /* unlock */
    mpd_unlock_conn(mi);
    if(data == NULL) 
    {
        return NULL;
    }
    return mpd_data_get_first(data);
}
예제 #4
0
void mpd_data_free(MpdData *data)
{
    MpdData_real *data_real,*temp;
    if(data == NULL)
    {
        debug_printf(DEBUG_ERROR, "data != NULL Failed");
        return;
    }
    data_real = (MpdData_real *)mpd_data_get_first(data);
    while(data_real){
        temp = data_real;
        if (data_real->type == MPD_DATA_TYPE_SONG) {
            if(data_real->song) mpd_freeSong(data_real->song);
        } else if (data_real->type == MPD_DATA_TYPE_OUTPUT_DEV) {
            mpd_freeOutputElement(data_real->output_dev);
        } else if(data_real->type == MPD_DATA_TYPE_DIRECTORY) {
            if(data_real->directory)free(data_real->directory);
        } else if(data_real->type == MPD_DATA_TYPE_PLAYLIST) {
            if(data_real->playlist)free(data_real->playlist);				
        } else {
            free((void*)(data_real->tag));
        }
        data_real = data_real->next;
        free(temp);
    }
}
예제 #5
0
MpdData * mpd_database_get_artists(MpdObj *mi)
{
	char *string = NULL;
	MpdData *data = NULL;
	if(!mpd_check_connected(mi))
	{
		debug_printf(DEBUG_WARNING,"not connected\n");
		return NULL;
	}
	if(mpd_lock_conn(mi))
	{
		debug_printf(DEBUG_ERROR,"lock failed\n");
		return NULL;
	}

	mpd_sendListCommand(mi->connection,MPD_TABLE_ARTIST,NULL);
	while (( string = mpd_getNextArtist(mi->connection)) != NULL)
	{
		data = mpd_new_data_struct_append(data);
		data->type = MPD_DATA_TYPE_TAG;
		data->tag_type = MPD_TAG_ITEM_ARTIST;
		data->tag = string;
	}
	mpd_finishCommand(mi->connection);

	/* unlock */
	mpd_unlock_conn(mi);
	if(data == NULL)
	{
		return NULL;
	}
	data = mpd_misc_sort_tag_list(data);
	return mpd_data_get_first(data);
}
예제 #6
0
MpdData *mpd_database_get_playlist_content(MpdObj *mi,char *playlist)
{
	MpdData *data = NULL;
	mpd_InfoEntity *ent = NULL;
	if(!mpd_check_connected(mi))
	{
		debug_printf(DEBUG_WARNING,"not connected\n");
		return NULL;
	}
	if(!mpd_server_check_version(mi, 0,12,0))
	{
		debug_printf(DEBUG_WARNING, "only works with mpd higher then 0.12.0");
		return NULL;
	}
	if(mpd_server_check_command_allowed(mi, "listplaylistinfo") != MPD_SERVER_COMMAND_ALLOWED)
	{
		debug_printf(DEBUG_WARNING, "Listing playlist content not supported or allowed");
		return NULL;
	}
	if(mpd_lock_conn(mi))
	{
		debug_printf(DEBUG_WARNING,"lock failed\n");
		return NULL;
	}
	mpd_sendListPlaylistInfoCommand(mi->connection, playlist);
	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
	{
		data = mpd_new_data_struct_append( data );
		if(ent->type == MPD_INFO_ENTITY_TYPE_DIRECTORY)
		{
			data->type = MPD_DATA_TYPE_DIRECTORY;
			data->directory = ent->info.directory->path;
			ent->info.directory->path = NULL;
		}
		else if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
		{
			data->type = MPD_DATA_TYPE_SONG;
			data->song = ent->info.song;
			ent->info.song = NULL;
		}
		else if (ent->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
		{
			data->type = MPD_DATA_TYPE_PLAYLIST;
			data->playlist = ent->info.playlistFile->path;
			ent->info.playlistFile->path = NULL;
		}

		mpd_freeInfoEntity(ent);
	}
	mpd_finishCommand(mi->connection);

	/* unlock */
	mpd_unlock_conn(mi);
	if(data == NULL)
	{
		return NULL;
	}
	return mpd_data_get_first(data);
}
예제 #7
0
MpdData * mpd_database_get_directory(MpdObj *mi,char *path)
{
	MpdData *data = NULL;
	mpd_InfoEntity *ent = NULL;
	if(!mpd_check_connected(mi))
	{
		debug_printf(DEBUG_WARNING,"not connected\n");
		return NULL;
	}
	if(path == NULL)
	{
		path = "/";
	}
	if(mpd_lock_conn(mi))
	{
		debug_printf(DEBUG_WARNING,"lock failed\n");
		return NULL;
	}

	mpd_sendLsInfoCommand(mi->connection,path);
	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
	{
		data = mpd_new_data_struct_append(data);
		if(ent->type == MPD_INFO_ENTITY_TYPE_DIRECTORY)
		{
			data->type = MPD_DATA_TYPE_DIRECTORY;
			data->directory = ent->info.directory->path;
			ent->info.directory->path = NULL;
		}
		else if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
		{
			data->type = MPD_DATA_TYPE_SONG;
			data->song = ent->info.song;
			ent->info.song = NULL;
		}
		else if (ent->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
		{
			data->type = MPD_DATA_TYPE_PLAYLIST;
			data->playlist = ent->info.playlistFile->path;
			ent->info.playlistFile->path = NULL;
		}

		mpd_freeInfoEntity(ent);
	}
	mpd_finishCommand(mi->connection);

	/* unlock */
	mpd_unlock_conn(mi);
	if(data == NULL)
	{
		return NULL;
	}
	return mpd_data_get_first(data);
}
예제 #8
0
MpdData * mpd_playlist_get_changes_posid(MpdObj *mi,int old_playlist_id)
{
	MpdData *data = NULL;
	mpd_InfoEntity *ent = NULL;
	debug_printf(DEBUG_INFO, "Fetching using new plchangesposid command");
	if(!mpd_check_connected(mi))
	{
		debug_printf(DEBUG_WARNING,"not connected\n");
		return NULL;
	}
	if(mpd_lock_conn(mi))
	{
		debug_printf(DEBUG_WARNING,"lock failed\n");
		return NULL;
	}

	if(old_playlist_id == -1)
	{
		debug_printf(DEBUG_INFO,"get fresh playlist\n");
		mpd_sendPlChangesPosIdCommand (mi->connection, 0);
/*		mpd_sendPlaylistIdCommand(mi->connection, -1); */
	}
	else
	{
		mpd_sendPlChangesPosIdCommand (mi->connection, old_playlist_id);
	}

	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
	{
		if(ent->type == MPD_INFO_ENTITY_TYPE_SONG)
		{
			data = mpd_new_data_struct_append(data);
			data->type = MPD_DATA_TYPE_SONG;
			data->song = ent->info.song;
			ent->info.song = NULL;
		}
		mpd_freeInfoEntity(ent);
	}
	mpd_finishCommand(mi->connection);

	/* unlock */
	if(mpd_unlock_conn(mi))
	{
		debug_printf(DEBUG_WARNING,"mpd_playlist_get_changes: unlock failed.\n");
		mpd_data_free(data);
		return NULL;
	}
	if(data == NULL)
	{
		return NULL;
	}
	return mpd_data_get_first(data);
}
예제 #9
0
MpdData * mpd_playlist_search_commit(MpdObj *mi)
{
	mpd_InfoEntity *ent = NULL;
	MpdData *data = NULL;
	if(!mpd_check_connected(mi))
	{
		debug_printf(DEBUG_WARNING,"not connected\n");
		return NULL;
	}
	if(mi->search_type < MPD_SEARCH_TYPE_PLAYLIST_FIND )
	{
		debug_printf(DEBUG_ERROR, "no or wrong search in progress to commit");
		return NULL;
	}
	if(mpd_lock_conn(mi))
	{
		debug_printf(DEBUG_ERROR,"lock failed\n");
		return NULL;
	}
	mpd_commitSearch(mi->connection);
	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
	{
		if(ent->type == MPD_INFO_ENTITY_TYPE_SONG)
		{
			data = mpd_new_data_struct_append(data);
			data->type = MPD_DATA_TYPE_SONG;
			data->song = ent->info.song;
			ent->info.song = NULL;
		}
		mpd_freeInfoEntity(ent);
	}
	mpd_finishCommand(mi->connection);
	/*
	 * reset search type
	 */
	mi->search_type = MPD_SEARCH_TYPE_NONE;
	mi->search_field = MPD_TAG_ITEM_ARTIST;
	/* unlock */
	if(mpd_unlock_conn(mi))
	{
		debug_printf(DEBUG_ERROR, "Failed to unlock connection");
		if(data)mpd_data_free(data);
		return NULL;
	}
	if(data == NULL)
	{
		return NULL;
	}
	return mpd_data_get_first(data);
}
예제 #10
0
MpdData *mpd_misc_sort_tag_list(MpdData *data)
{
	char **array;
	MpdData *test;
	int i=0;
	int length=0;
	test = data = mpd_data_get_first(data);

	do{
		length++;
		test = mpd_data_get_next_real(test, FALSE);
	}while(test != NULL);
	array = malloc(length*sizeof(char*));
	test = data;

	do
	{
		array[i] = test->tag;
		test = mpd_data_get_next_real(test, FALSE);
		i++;
	}while(test != NULL);

	qsort(array,length,sizeof(char *),(QsortCompare)compa);

	/* reset list */
	test = mpd_data_get_first(data);
	i=0;
	do
	{
		test->tag = array[i];
		test = mpd_data_get_next_real(test, FALSE);
		i++;
	}while(test != NULL);
	free(array);
	return mpd_data_get_first(data);
}
예제 #11
0
static void serverstats_combo_changed(GtkComboBox * box, GtkWidget * pb)
{
    ss_str *s;
    int hits, total;
    gulong max_i;
    MpdData *node, *data;
    GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(serverstats_tree));
    int tag = gtk_combo_box_get_active(box);

    if (!mpd_check_connected(connection))
        return;
    if (!mpd_server_check_version(connection, 0, 13, 0))
    {
        playlist3_show_error_message("This feature is not supported in mpd older then version 0.13.0.", ERROR_WARNING);
        return;
    }
    /* reset the cancel flag */
    cancel_query = FALSE;
    /* show progress bar */

    gtk_widget_show_all(gtk_widget_get_parent(pb));

    /** make the combo box insensitive and remove the model from the treeview */
    gtk_tree_view_set_model(GTK_TREE_VIEW(serverstats_tree), NULL);
    gtk_widget_set_sensitive(GTK_WIDGET(box), FALSE);

    gtk_list_store_clear(GTK_LIST_STORE(model));
    mpd_database_search_field_start(connection, tag);
    data = mpd_database_search_commit(connection);
    max_i = 0;

    hits = 0;
    total = 0;
    for (node = mpd_data_get_first(data); node != NULL; node = (MpdData *) mpd_data_get_next_real(node, FALSE))
        total++;
    s = g_malloc0(sizeof(*s));
    s->total = total;
    s->model = model;
    s->data = data;
    s->hits = 0;
    s->tag = tag;
    s->pb = pb;
    s->box = GTK_WIDGET(box);
    g_idle_add((GSourceFunc) serverstats_idle_handler, s);

}
예제 #12
0
MpdData * mpd_database_get_directory_recursive(MpdObj *mi, const char *path)
{
	MpdData *data = NULL;
	mpd_InfoEntity *ent = NULL;
	if(!mpd_check_connected(mi))
	{
		debug_printf(DEBUG_WARNING,"not connected\n");
		return NULL;
	}
	if(path == '\0' || path[0] == '\0')
	{
		debug_printf(DEBUG_ERROR, "argumant invalid\n");
		return NULL;
	}
	if(mpd_lock_conn(mi))
	{
		debug_printf(DEBUG_ERROR,"lock failed\n");
		return NULL;
	}
	mpd_sendListallInfoCommand(mi->connection,path); 
	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
	{

		if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
		{
			data = mpd_new_data_struct_append(data);
			data->type = MPD_DATA_TYPE_SONG;
			data->song = ent->info.song;
			ent->info.song = NULL;
		}
		mpd_freeInfoEntity(ent);
	}
	mpd_finishCommand(mi->connection);

	/* unlock */
	mpd_unlock_conn(mi);
	if(data == NULL)
	{
		return NULL;
	}
	return mpd_data_get_first(data);
}
예제 #13
0
MpdData *magnatune_db_get_album_list(char *wanted_genre,char *wanted_artist)
{
    int r;
    MpdData *list = NULL;
    /** check if there is data */

    char *query = sqlite3_mprintf("SELECT albumname from 'albums' WHERE artist=%Q",wanted_artist);
    sqlite3_stmt *stmt = NULL;
    const char *tail;
    GTimer *timer = g_timer_new();
    r = sqlite3_prepare_v2(magnatune_sqlhandle, query, -1,  &stmt,  &tail);
    if(r ==SQLITE_OK) {
        while((r = sqlite3_step(stmt)) == SQLITE_ROW)
        {
            sqlite3_stmt *stmt2 = NULL;
            const char *tail2;
            char *query2 = sqlite3_mprintf("SELECT albumname from 'genres' WHERE albumname=%Q AND genre=%Q", sqlite3_column_text(stmt,0),wanted_genre);
            int r2 = sqlite3_prepare_v2(magnatune_sqlhandle, query2, -1,  &stmt2,  &tail2);
            if(r2 ==SQLITE_OK) {
                while((r2 = sqlite3_step(stmt2)) == SQLITE_ROW)
                {
                    list = mpd_new_data_struct_append(list);
                    list->type = MPD_DATA_TYPE_TAG;
                    list->tag_type = MPD_TAG_ITEM_ALBUM;
                    list->tag = g_strdup(sqlite3_column_text(stmt2,0));
                }
            }
            sqlite3_finalize(stmt2);
            sqlite3_free(query2);
        }
    }
    sqlite3_finalize(stmt);
    sqlite3_free(query);
    g_debug("%f s elapsed listing albums songs\n", g_timer_elapsed(timer,NULL));
    g_timer_destroy(timer);
    return mpd_data_get_first(list); 
}
예제 #14
0
/* should be called mpd_database_find */
MpdData * mpd_database_find(MpdObj *mi, int table, char *string, int exact)
{
	MpdData *data = NULL;
/*	MpdData *artist = NULL;
	MpdData *album = NULL;
*/	mpd_InfoEntity *ent = NULL;
	if(!mpd_check_connected(mi))
	{
		debug_printf(DEBUG_WARNING,"not connected\n");
		return NULL;
	}
	if(mpd_lock_conn(mi))
	{
		debug_printf(DEBUG_WARNING,"lock failed\n");
		return NULL;
	}
	if(exact)
	{
		mpd_sendFindCommand(mi->connection,table,string);
	}
	else
	{
		mpd_sendSearchCommand(mi->connection, table,string);
	}
	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
	{
		data = mpd_new_data_struct_append(data);
		/* mpd_sendSearch|Find only returns songs */
		/*
		if(ent->type == MPD_INFO_ENTITY_TYPE_DIRECTORY)
		{
			data->type = MPD_DATA_TYPE_DIRECTORY;
			data->directory = ent->info.directory->path;
			ent->info.directory->path = NULL;
		}
		else*/ if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
		{
			data->type = MPD_DATA_TYPE_SONG;
			data->song = ent->info.song;
			ent->info.song = NULL;
			/* This is something the client can and should do */
/*			if(data->song->artist != NULL)
			{
				int found = FALSE;
				if(artist != NULL)
				{
					MpdData *fartist = mpd_data_get_first(artist);
					do{
						if( (fartist->type == MPD_DATA_TYPE_TAG) && (fartist->tag_type == MPD_TAG_ITEM_ARTIST))
						{
							if(fartist->tag == NULL)
							{
								printf("crap this should'nt be \n");
							}
							if(!strcmp(fartist->tag, data->song->artist))
							{
								found = TRUE;
							}
						}
						fartist = mpd_data_get_next_real(fartist, FALSE);
					}while(fartist && !found);
				}
				if(!found)
				{
					artist= mpd_new_data_struct_append(artist);
					artist->type = MPD_DATA_TYPE_TAG;
					artist->tag_type = MPD_TAG_ITEM_ARTIST;
					artist->tag = strdup(data->song->artist);
				}
			}
			if(data->song->album != NULL)
			{
				int found = FALSE;
				if(album != NULL)
				{
					MpdData *falbum = mpd_data_get_first(album);
					do{
						if( (falbum->type == MPD_DATA_TYPE_TAG) && (falbum->tag_type == MPD_TAG_ITEM_ALBUM))
						{
							if(falbum->tag == NULL)
							{
								printf("crap this should'nt be \n");
							}
							if(!strcmp(falbum->tag, data->song->album))
							{
								found = TRUE;
							}
						}
						falbum = mpd_data_get_next_real(falbum, FALSE);
					}while(falbum && !found);
				}
				if(!found)
				{
					album = mpd_new_data_struct_append(album);
					album->type = MPD_DATA_TYPE_TAG;
					album->tag_type = MPD_TAG_ITEM_ALBUM;
					album->tag = strdup(data->song->album);
				}
			}
*/
		}
		/*
		else if (ent->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
		{
			data->type = MPD_DATA_TYPE_PLAYLIST;
			data->playlist = ent->info.playlistFile->path;
			ent->info.playlistFile->path = NULL;
		}
		*/

		mpd_freeInfoEntity(ent);
	}
	mpd_finishCommand(mi->connection);

	/* unlock */
	mpd_unlock_conn(mi);
	if(data == NULL)
	{
		return NULL;
	}
	data = mpd_data_get_first(data);
	/* prepend the album then artists*/
/*	if(album != NULL)
	{
		if(data){
			data  = mpd_data_concatenate( album, data);
		}else{
			data = album;
		}
	}
	if(artist != NULL)
	{
		if(data) {
			album = mpd_data_concatenate( artist, data );
		}else{
			data = artist;
		}
	}                                                     	
*/
	return mpd_data_get_first(data);
}
예제 #15
0
MpdData *mpd_database_token_find(MpdObj *mi , char *string)
{
	MpdData *data = NULL;
	mpd_InfoEntity *ent = NULL;
	regex_t ** strdata = NULL;
	if(!mpd_check_connected(mi))
	{
		debug_printf(DEBUG_WARNING,"not connected\n");
		return NULL;
	}
	if(mpd_lock_conn(mi))
	{
		debug_printf(DEBUG_ERROR,"lock failed\n");
		return NULL;
	}

	if(string == NULL || !strlen(string) )
	{
		debug_printf(DEBUG_INFO, "no string found");
		mpd_unlock_conn(mi);
		return NULL;
	}
	else{
		strdata = mpd_misc_tokenize(string);
	}
	if(strdata == NULL)
	{
		mpd_unlock_conn(mi);
		debug_printf(DEBUG_INFO, "no split string found");
		return NULL;
	}

	mpd_sendListallInfoCommand(mi->connection, "/");
	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
	{
		if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
		{
			int i = 0;
			int match = 0;
			int loop = 1;
			for(i=0; strdata[i] != NULL && loop; i++)
			{
				match = 0;
				if(ent->info.song->file && !regexec(strdata[i],ent->info.song->file, 0, NULL, 0))
				{
					match = 1;
				}
				else if(ent->info.song->artist && !regexec(strdata[i],ent->info.song->artist, 0, NULL, 0))
				{
					match = 1;
				}
				else if(ent->info.song->title && !regexec(strdata[i],ent->info.song->title, 0, NULL, 0)) 
				{
					match = 1;
				}
				else if(ent->info.song->album && !regexec(strdata[i],ent->info.song->album, 0, NULL, 0))
				{
					match = 1;
				}
				if(!match)
				{
					loop = 0;
				}
			}

			if(match)
			{
				data = mpd_new_data_struct_append(data);
				data->type = MPD_DATA_TYPE_SONG;
				/*
				data->song = mpd_songDup(ent->info.song);
				*/
				data->song = ent->info.song;
				ent->info.song = NULL;
			}
		}
		mpd_freeInfoEntity(ent);
	}
	mpd_finishCommand(mi->connection);
	mpd_misc_tokens_free(strdata);




	mpd_unlock_conn(mi);
	if(data == NULL)
	{
		return NULL;
	}
	return mpd_data_get_first(data);
}
예제 #16
0
/* searches in the mpd database for a given string and outputs the result (data contains a GtkEntry and a GtkWindow)*/
static void mpd_search(GtkWidget *widget, gpointer data) {

	GList *args,*vbox_content,*argument_list;
	gpointer list_data;
	GtkWidget *vbox, *entry, *label, *result_tree_view, *add_button, *scrolled_window, *window;
   	GtkBox *box;
	GtkBoxChild *child;
	const gchar *entry_string;
	gchar *search_string;
	GtkListStore *list_store;
	GtkTreeSelection *tree_selection;
	GtkObject *h_adjustment, *v_adjustment;

	MpdData *result, *res_ptr;
	int result_count = 0;
	int i = 0;

	GList *song_handle_list;
	MpdPlContainer *result_list;

   	args = (GList *)data;


	/* remove old results, if any */
	vbox = g_list_nth_data(args, 1);
	box = GTK_BOX(vbox);
	vbox_content = box->children;
	list_data = g_list_nth_data(vbox_content, 4);
	if(list_data != NULL) {
		child = list_data;
		gtk_widget_destroy(child->widget);
	}
	list_data = g_list_nth_data(vbox_content, 3);
	if(list_data != NULL) {
		child = list_data;
		gtk_widget_destroy(child->widget);
	}

	if(debug) {
		fprintf(log_file, "[%s:%3i] %s(): Type = %i\n", __FILE__, __LINE__, __FUNCTION__, search_type);
		fflush(log_file);
	}

	/* search for the typed string */
	entry = g_list_nth_data(args, 0);
	entry_string = gtk_entry_get_text(GTK_ENTRY(entry));
	search_string = g_strdup(entry_string);
	/* table ^= search_type */
	if(!mpd_check_connected(mpd_info.obj)) {
		if(mpd_connect(mpd_info.obj)!=MPD_OK)  {
		    msi_clear(&mpd_info);
		    mpd_info.msi.connected = FALSE;
		    return;
		}
		msi_fill(&mpd_info);
		mpd_info.msi.connected = TRUE;
	}
	/*
	 * Last argument: TRUE -> only exact matches 
	 *		  FALSE -> more matches 
	 */
	result = mpd_database_find(mpd_info.obj, search_type, search_string, FALSE);
	/* Iterate through the found songs, using
	 * the function mpd_data_get_next_keep(md), which
	 * calls mpd_data_get_next_real(md,FALSE) which
	 * prevents the list being killed when reaching
	 * the end.
	 */
	for(
		res_ptr =  mpd_data_get_first(result);
		res_ptr != NULL;
		res_ptr =  mpd_data_get_next_keep(res_ptr)
	   )
	{
		/* count only songs ... */
		if(res_ptr->type == MPD_DATA_TYPE_SONG)
			++result_count;
	}

	/* no matches */
	if(result_count == 0) {
		label = gtk_label_new("No songs found!");
		gtk_box_pack_end_defaults(GTK_BOX(vbox), label);
		gtk_widget_show(label);
	}
	/* output found songs */
	else {
		song_handle_list = NULL;
		result_list = mpd_pl_container_new_alloc(result_count);
		//mpd_Song *result_list[result_count];

		/* as above: the song info is still needed, as
		 * the mpd_Song objects are *not* copied into the
		 * result list
		 */

		for(
			res_ptr =  mpd_data_get_first(result);
			res_ptr != NULL;
			res_ptr =  mpd_data_get_next_keep(res_ptr)
		   )
		{
			/* only songs */
			if(res_ptr->type == MPD_DATA_TYPE_SONG) {
				result_list->list[i++] = mpd_songDup(res_ptr->song);
				song_handle_list = g_list_append(song_handle_list, strdup(res_ptr->song->file));
			}
		}


		list_store = pl_create_list_store(result_list);
		mpd_pl_container_free(result_list);
		result_tree_view = pl_create_tree_view(GTK_TREE_MODEL(list_store));
		/* create a facility to select only some of the found songs for adding...*/
		tree_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(result_tree_view));
		gtk_tree_selection_set_mode(tree_selection, GTK_SELECTION_MULTIPLE);

		/**********/
		argument_list = NULL;
		argument_list = g_list_append(argument_list, song_handle_list);
		argument_list = g_list_append(argument_list, tree_selection);
		add_button = gtk_button_new_with_label("add selected songs");
		g_signal_connect(GTK_BUTTON(add_button), "clicked",
						 G_CALLBACK(mpd_add_song_list), argument_list);
		/* g_signal_connect_swapped(GTK_BUTTON(add_button), "clicked",
						 G_CALLBACK(gtk_widget_destroy), g_list_nth_data(data, 2)); */
		gtk_box_pack_end(GTK_BOX(vbox), add_button,FALSE,FALSE,0);

		/* put a scrolled window in between the treeview and the window... */
		/* I just don't know how this works exactly, but the result is acceptable, so why bother */
		h_adjustment = gtk_adjustment_new(0, 0, 4, 1, 4, 4);
		v_adjustment = gtk_adjustment_new(0, 0, 20, 1, 20, 20);

		scrolled_window = gtk_scrolled_window_new(GTK_ADJUSTMENT(h_adjustment), GTK_ADJUSTMENT(v_adjustment));
		gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_NONE);
		/* display scrollbars only when needed */
		gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);

		gtk_container_add(GTK_CONTAINER(scrolled_window), result_tree_view);

		gtk_box_pack_end_defaults(GTK_BOX(vbox), scrolled_window);
		gtk_box_set_homogeneous(GTK_BOX(vbox), FALSE);

		gtk_widget_show_all(scrolled_window);
		gtk_widget_show_all(add_button);
		window = g_list_nth_data(args, 2);
		gtk_window_resize(GTK_WINDOW(window), 700, 500);
	}

	/* delete search result, have to do this ourselves
	 * because we needed the song data until now
	 */
	mpd_data_free(result);

	return;
}