/* mb-desktop-xine - a desktop media playing module. Copyright 2004 Matthew Allum This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #define _FILE_OFFSET_BITS 64 #include "xinebrowser.h" static void xinebrowser_dvd_activate (MBDesktop *mb, MBDesktopItem *item) { char *mrl = "dvd://"; BrowserData *mod_data; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item); xinebrowser_win_open (mb, mod_data, 0); if((!xine_open(mod_data->stream, mrl)) || (!xine_play(mod_data->stream, 0, 0))) { fprintf(stderr, "mbdesktop-xine: failed to open '%s'\n", mrl); } else { mod_data->current_mode = MBX_MODE_MOVIE_DVD; xinebrowser_win_event_loop (mb, mod_data); } xinebrowser_win_close (mb, mod_data); } static void xinebrowser_cd_activate (MBDesktop *mb, MBDesktopItem *item) { BrowserData *mod_data; xine_post_t *vis; xine_post_out_t *audio_source; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item); mod_data->cd_mrls = xine_get_autoplay_mrls(mod_data->xine, "CD", &mod_data->cd_num_mrls); mod_data->cd_idx = 0; xinebrowser_win_open (mb, mod_data, mod_data->use_xshm_for_vis_hack); /* vis = xine_post_init (mod_data->xine, mod_data->BrowserVizPlugin, 0, &mod_data->ao_port, &mod_data->vo_port); audio_source = xine_get_audio_source (mod_data->stream); if (!xine_post_wire_audio_port (audio_source, vis->audio_input[0])) printf("audi rewire failed\n"); */ /* PLAN: *Ditched for now - too complex - I just want to play cd's - cd is actually a folder which lists tracks as items. - folder name is set to CD title ? - item names from cddb - next track automatically played - quit takes you back to list - issues - what if is cd is removed whilst browsing ? */ mod_data->current_mode = MBX_MODE_MUSIC_CD; if((!xine_open(mod_data->stream, mod_data->cd_mrls[0])) || (!xine_play(mod_data->stream, 0, 0))) { fprintf(stderr, "mbdesktop-xine: failed to open '%s'\n", mod_data->cd_mrls[0]); } else { xinebrowser_show_info (mb, mod_data, MBX_INFO_TIMEOUT); xinebrowser_win_event_loop (mb, mod_data); } xinebrowser_win_close (mb, mod_data); } void xinebrowser_disc_activate_cb (void *data1, void *data2) { BrowserData *mod_data; MBDesktop *mb = (MBDesktop *)data1; MBDesktopItem *item = (MBDesktopItem *)data2; char *error = NULL; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item); switch (xinebrowser_cd_get_disc_type(mod_data->BrowserDrivePath )) { case CD_TYPE_ERROR: fprintf(stderr, "mbdesktop-xine: Disc Error?\n"); return; case CD_TYPE_NO_DISC: fprintf(stderr, "mbdesktop-xine: No disk present\n"); return; case CD_TYPE_AUDIO: xinebrowser_cd_activate(mb, item); break; case CD_TYPE_DATA: fprintf(stderr, "mbdesktop-xine: Data Disks unsupported\n"); return; case CD_TYPE_VCD: fprintf(stderr, "mbdesktop-xine: VCD unsupported\n"); return; case CD_TYPE_DVD: xinebrowser_dvd_activate(mb, item); return; case CD_TYPE_UNKNOWN: default: fprintf(stderr, "mbdesktop-xine: Unkown disc unsupported.\n"); break; } } void xinebrowser_file_activate_cb (void *data1, void *data2) { BrowserData *mod_data; MBDesktop *mb = (MBDesktop *)data1; MBDesktopItem *item = (MBDesktopItem *)data2; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item); xinebrowser_win_open (mb, mod_data, mod_data->use_xshm_for_vis_hack && (mod_data->current_mode == MBX_MODE_MUSIC_FILE)); if (!xinebrowser_play(mb, mod_data, mbdesktop_item_get_extended_name(mb, item))) { fprintf(stderr, "mbdesktop-xine: *WARNING* Play failed"); } else { mod_data->current_item = item; xinebrowser_show_info (mb, mod_data, MBX_INFO_TIMEOUT); xinebrowser_win_event_loop (mb, mod_data); } xinebrowser_win_close (mb, mod_data); } void xinebrowser_radio_activate_cb (void *data1, void *data2) { BrowserData *mod_data; MBDesktop *mb = (MBDesktop *)data1; MBDesktopItem *item = (MBDesktopItem *)data2; char *error = NULL; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item); mod_data->current_mode = MBX_MODE_MUSIC_RADIO; xinebrowser_win_open (mb, mod_data, mod_data->use_xshm_for_vis_hack); if (!xinebrowser_play(mb, mod_data, mbdesktop_item_get_extended_name(mb, item))) { fprintf(stderr, "mbdesktop-xine: *WARNING* Play failed"); } else { mod_data->current_item = item; xinebrowser_show_info (mb, mod_data, MBX_INFO_TIMEOUT); xinebrowser_win_event_loop (mb, mod_data); } xinebrowser_win_close (mb, mod_data); mod_data->current_mode = MBX_MODE_UNKNOWN; } void /* Called on a folder open */ xinebrowser_movie_open_cb (void *data1, void *data2) { DIR *dp; BrowserData *mod_data; struct dirent **namelist; char orig_wd[512] = { 0 }; regex_t re; int n, i = 0; char *current_path = NULL; char *current_path_stripped = NULL; MBDesktopItem *subfolder = NULL; MBDesktopItem *item_new = NULL; MBDesktop *mb = (MBDesktop *)data1; MBDesktopItem *item_folder = (MBDesktopItem *)data2; Bool is_subfolder = False; Bool have_dialog = False; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item_folder); if (!strcmp(mbdesktop_item_get_name(mb, item_folder), mod_data->BrowserFolderName)) { /* Is top level */ current_path = strdup(mod_data->BrowserPath); current_path_stripped = strdup(""); } else { /* Is sub folder */ /* Figure out the 'real' directory path from name etc */ char *base_path = mbdesktop_item_get_extended_name(mb, item_folder) + (strlen(mod_data->BrowserFolderName) +1) ; int len = strlen(mod_data->BrowserPath) + strlen(mbdesktop_item_get_extended_name(mb, item_folder)) + strlen(mod_data->BrowserFolderName); current_path = malloc(sizeof(char)*len); current_path_stripped = malloc(sizeof(char)*(strlen(base_path)+3)); snprintf(current_path, len, "%s/%s", mod_data->BrowserPath, base_path); sprintf(current_path_stripped, "%s/", base_path); is_subfolder = True; } if (mbdesktop_item_folder_has_contents(mb, item_folder)) mbdesktop_item_folder_contents_free(mb, item_folder); if (regcomp(&re, ".*(avi|mpg|mpeg|wmv|asf|mov|mp4)$", REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) { fprintf(stderr, "mbdesktop-filebrowser: failed to compile regexp\n"); return; } if ((dp = opendir(current_path)) == NULL) { fprintf(stderr, "mbdesktop-filebrowser: failed to open %s\n", mod_data->BrowserPath); return; } if (getcwd(orig_wd, 255) == (char *)NULL) { fprintf(stderr, "mbdesktop-filebrowser: cant get current directory\n"); return; } if (mod_data->use_video_thumbnails) { /* Set up xine for thumbnail generation */ mod_data->vo_port = xine_open_video_driver (mod_data->xine, "none", XINE_VISUAL_TYPE_NONE, NULL); mod_data->ao_port = NULL; mod_data->stream = xine_stream_new (mod_data->xine, mod_data->ao_port, mod_data->vo_port); mod_data->event_queue = xine_event_new_queue (mod_data->stream); } chdir(current_path); n = scandir(".", &namelist, 0, alphasort); while (i < n && n > 0) { struct stat stat_buf; if (namelist[i]->d_name[0] == '.') goto end; /* Check for directory */ if (stat(namelist[i]->d_name, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode)) { char *subfolderlongname = NULL; int l = strlen(mod_data->BrowserFolderName) + strlen(current_path) + strlen(namelist[i]->d_name); subfolderlongname = malloc(sizeof(char)*l); sprintf(subfolderlongname, "%s/%s%s", mod_data->BrowserFolderName, current_path_stripped, namelist[i]->d_name); subfolder = mbdesktop_module_folder_create (mb, namelist[i]->d_name, "mbmoviefolder.png"); mbdesktop_item_set_extended_name (mb, subfolder, subfolderlongname); mbdesktop_item_set_user_data (mb, subfolder, (void *)mod_data); mbdesktop_items_append_to_folder (mb, item_folder, subfolder); mbdesktop_item_folder_set_view (mb, subfolder, VIEW_LIST); mbdesktop_item_set_activate_callback (mb, subfolder, xinebrowser_movie_open_cb); free(subfolderlongname); goto end; } if (regexec(&re, namelist[i]->d_name, 0, NULL, REG_NOTBOL) == 0) { struct stat stat_info; char *full_path = NULL; MBPixbufImage *img = NULL, *img_backing = NULL; int img_w, img_h; full_path = malloc(sizeof(char)*(strlen(current_path)+strlen(namelist[i]->d_name)+2)); sprintf(full_path, "%s/%s", current_path, namelist[i]->d_name); item_new = mbdesktop_item_from_cache (mb, full_path, stat_info.st_mtime); if (stat(full_path, &stat_info) == -1) { free(full_path); goto end; } if (item_new != NULL) { printf("Item from cache success - %s\n", item_new->name); } else { char *nice_name = NULL, *prefix = NULL; if (!have_dialog) { have_dialog = True; if (mod_data->use_video_thumbnails) mbdesktop_progress_dialog_open(mb); /* Tell em were busy ? */ } nice_name = strdup(namelist[i]->d_name); if ((prefix = rindex(nice_name, '.')) != NULL) *prefix = '\0'; item_new = mbdesktop_item_new_with_params( mb, nice_name, (mod_data->use_video_thumbnails) ? NULL : "mbmoviefile.png", NULL, ITEM_TYPE_MODULE_ITEM ); if (mod_data->use_video_thumbnails) { printf("thumbnailing %s\n", namelist[i]->d_name); img = xinebrowser_make_thumbnail (mb, mod_data, full_path); } else img = NULL; if (img != NULL) { mbdesktop_item_set_icon_data (mb, item_new, img); mb_pixbuf_img_free(mb->pixbuf, img); } mbdesktop_item_set_extended_name (mb, item_new, full_path); if (mod_data->use_video_thumbnails) mbdesktop_item_cache(mb, item_new, full_path); if (nice_name) free(nice_name); } mbdesktop_item_set_user_data (mb, item_new, (void *)mod_data); mbdesktop_item_set_activate_callback (mb, item_new, xinebrowser_file_activate_cb); mbdesktop_items_append_to_folder( mb, item_folder, item_new ); free(full_path); } end: if (have_dialog) mbdesktop_progress_dialog_set_percentage (mb, (i * 100) / n ) ; free(namelist[i]); ++i; } regfree(&re); free(namelist); closedir(dp); chdir(orig_wd); free(current_path); free(current_path_stripped); if (mod_data->use_video_thumbnails) { xine_close(mod_data->stream); xine_event_dispose_queue(mod_data->event_queue); xine_dispose(mod_data->stream); xine_close_video_driver(mod_data->xine, mod_data->vo_port); } if (have_dialog) mbdesktop_progress_dialog_close(mb); mod_data->stream = NULL; mod_data->current_mode = MBX_MODE_MOVIE_FILE; mbdesktop_item_folder_activate_cb(data1, data2); } void xinebrowser_music_open_cb (void *data1, void *data2) { DIR *dp; BrowserData *mod_data; struct dirent **namelist; char orig_wd[512] = { 0 }; regex_t re; int n, i = 0; char *current_path = NULL; char *current_path_stripped = NULL; MBDesktopItem *subfolder = NULL; MBDesktopItem *item_new = NULL; MBDesktop *mb = (MBDesktop *)data1; MBDesktopItem *item_folder = (MBDesktopItem *)data2; Bool is_subfolder = False; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item_folder); if (!strcmp(mbdesktop_item_get_name(mb, item_folder), "Browse")) { /* Is top level */ current_path = strdup(mod_data->BrowserMusicPath); current_path_stripped = strdup(""); } else { /* Is sub folder */ /* Figure out the 'real' directory path from name etc */ char *base_path = mbdesktop_item_get_extended_name(mb, item_folder) + (strlen(mod_data->BrowserMusicFolderName) +1) ; int len = strlen(mod_data->BrowserMusicPath) + strlen(mbdesktop_item_get_extended_name(mb, item_folder)) + strlen(mod_data->BrowserMusicFolderName); current_path = malloc(sizeof(char)*len); current_path_stripped = malloc(sizeof(char)*(strlen(base_path)+3)); snprintf(current_path, len, "%s/%s", mod_data->BrowserMusicPath, base_path); sprintf(current_path_stripped, "%s/", base_path); is_subfolder = True; } if (mbdesktop_item_folder_has_contents(mb, item_folder)) mbdesktop_item_folder_contents_free(mb, item_folder); if (regcomp(&re, ".*(ogg|mp3|m3u)$", REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) { fprintf(stderr, "mbdesktop-xinebrowser: failed to compile regexp\n"); return; } if ((dp = opendir(current_path)) == NULL) { fprintf(stderr, "mbdesktop-xinebrowser: failed to open %s\n", mod_data->BrowserMusicPath); return; } if (getcwd(orig_wd, 255) == (char *)NULL) { fprintf(stderr, "mbdesktop-filebrowser: cant get current directory\n"); return; } chdir(current_path); n = scandir(".", &namelist, 0, alphasort); while (i < n && n > 0) { struct stat stat_buf; if (namelist[i]->d_name[0] == '.') goto end; /* Check for directory */ if (stat(namelist[i]->d_name, &stat_buf) == 0 && S_ISDIR(stat_buf.st_mode)) { char *subfolderlongname = NULL; MBPixbufImage *img = NULL; char thumbnail_path[1024] = {0}; int l = strlen(mod_data->BrowserMusicFolderName) + strlen(current_path) + strlen(namelist[i]->d_name); subfolderlongname = malloc(sizeof(char)*l); sprintf(subfolderlongname, "%s/%s%s", mod_data->BrowserMusicFolderName, current_path_stripped, namelist[i]->d_name); subfolder = mbdesktop_module_folder_create (mb, namelist[i]->d_name, "mbmusicfolder.png"); /* Check if album cover preview exists and usef or folder */ snprintf(thumbnail_path, 1024, "%s/%s/cover.jpg", current_path, namelist[i]->d_name); if (file_exists(thumbnail_path)) { img = mb_pixbuf_img_new_from_file(mb->pixbuf, thumbnail_path); if (img != NULL) { mbdesktop_item_set_icon_data (mb, subfolder, img); mb_pixbuf_img_free(mb->pixbuf, img); } } mbdesktop_item_set_extended_name (mb, subfolder, subfolderlongname); mbdesktop_item_set_user_data (mb, subfolder, (void *)mod_data); mbdesktop_item_folder_set_view (mb, subfolder, VIEW_LIST); mbdesktop_items_append_to_folder (mb, item_folder, subfolder); mbdesktop_item_set_activate_callback (mb, subfolder, xinebrowser_music_open_cb); free(subfolderlongname); goto end; } if (regexec(&re, namelist[i]->d_name, 0, NULL, REG_NOTBOL) == 0) { struct stat stat_info; char *full_path = NULL; MBPixbufImage *img = NULL, *img_backing = NULL; int img_w, img_h; char *nice_name = NULL, *prefix = NULL; full_path = malloc(sizeof(char)*(strlen(current_path)+strlen(namelist[i]->d_name)+2)); sprintf(full_path, "%s/%s", current_path, namelist[i]->d_name); if (stat(full_path, &stat_info) == -1) { free(full_path); goto end; } nice_name = strdup(namelist[i]->d_name); if ((prefix = rindex(nice_name, '.')) != NULL) *prefix = '\0'; item_new = mbdesktop_item_new_with_params( mb, nice_name, "mbmusicfile.png", NULL, ITEM_TYPE_MODULE_ITEM ); mbdesktop_item_set_extended_name (mb, item_new, full_path); mbdesktop_item_set_user_data (mb, item_new, (void *)mod_data); mbdesktop_item_set_activate_callback (mb, item_new, xinebrowser_file_activate_cb); mbdesktop_items_append_to_folder( mb, item_folder, item_new ); free(nice_name); free(full_path); } end: free(namelist[i]); ++i; } regfree(&re); free(namelist); closedir(dp); chdir(orig_wd); free(current_path); free(current_path_stripped); mod_data->current_mode = MBX_MODE_MUSIC_FILE; mbdesktop_item_folder_activate_cb(data1, data2); } void xinebrowser_radio_open_cb (void *data1, void *data2) { BrowserData *mod_data; MBDesktopItem *item_new = NULL; MBDesktop *mb = (MBDesktop *)data1; MBDesktopItem *item_folder = (MBDesktopItem *)data2; DIR *dp; struct dirent *dir_entry; struct stat stat_info; char orig_wd[256]; int i; MBDotDesktopFolders *ddfolders; MBDotDesktopFolderEntry *ddentry; MBDotDesktop *dd; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item_folder); if (!mod_data->BrowserRadioPath) return; if (mbdesktop_item_folder_has_contents(mb, item_folder)) mbdesktop_item_folder_contents_free(mb, item_folder); if (getcwd(orig_wd, 255) == (char *)NULL) { fprintf(stderr, "Cant get current directory\n"); return; } if ((dp = opendir(mod_data->BrowserRadioPath)) == NULL) { fprintf(stderr, "mbdesktop: failed to open %s\n", mod_data->BrowserRadioPath); return; } chdir(mod_data->BrowserRadioPath); while((dir_entry = readdir(dp)) != NULL) { if (strcmp(dir_entry->d_name+strlen(dir_entry->d_name)-8,".desktop")) continue; lstat(dir_entry->d_name, &stat_info); if (!(S_ISDIR(stat_info.st_mode))) { MBDotDesktop *dd; dd = mb_dotdesktop_new_from_file(dir_entry->d_name); if (dd) { if (mb_dotdesktop_get(dd, "Name") && mb_dotdesktop_get(dd, "Mrl")) { item_new = mbdesktop_item_new_with_params( mb, mb_dotdesktop_get(dd, "Name"), mb_dotdesktop_get(dd, "Icon"), NULL, ITEM_TYPE_MODULE_ITEM ); mbdesktop_item_set_extended_name (mb, item_new, mb_dotdesktop_get(dd, "Mrl")); mbdesktop_item_set_user_data(mb, item_new, (void *)mod_data); mbdesktop_item_set_activate_callback(mb, item_new, xinebrowser_radio_activate_cb); mbdesktop_items_append_to_folder(mb, item_folder, item_new ); } mb_dotdesktop_free(dd); } } } closedir(dp); chdir(orig_wd); mod_data->current_mode = MBX_MODE_MUSIC_RADIO; mbdesktop_item_folder_activate_cb(data1, data2); } void xinebrowser_playlist_activate_cb (void *data1, void *data2) { BrowserData *mod_data; MBDesktop *mb = (MBDesktop *)data1; MBDesktopItem *item = (MBDesktopItem *)data2; FILE *fp; char data[1024]; struct stat stat_info; char *error = NULL; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item); mod_data->current_mode = MBX_MODE_MUSIC_PLAYLIST; xinebrowser_win_open (mb, mod_data, mod_data->use_xshm_for_vis_hack); /* see http://gonze.com/playlists/playlist-format-survey.html for mpu format */ if (!(fp = fopen(mbdesktop_item_get_extended_name(mb, item), "r"))) { fprintf(stderr, "mbdesktop-xine: cant open '%s'", mbdesktop_item_get_extended_name(mb, item)); goto end; } printf("mod_data->BrowserMusicPath: '%s'\n", mod_data->BrowserMusicPath); while(fgets(data,1024,fp) != NULL) { char *mrl = NULL; int i = 0; if (data[0] == '#') continue; /* XXX need to ignore black lines */ if (data[strlen(data)-1] == '\n') data[strlen(data)-1] = '\0'; if (lstat(data, &stat_info) == 0) { mrl = strdup(data); } else if (mod_data->BrowserMusicPath) { mrl = malloc(strlen(mod_data->BrowserMusicPath) + strlen(data) + 2); sprintf(mrl, "%s/%s", mod_data->BrowserMusicPath, data); if (lstat(mrl, &stat_info) != 0) { fprintf(stderr, "mbdesktop-xine: cant open '%s' ( also tried '%s' )\n", data, mrl); free(mrl); continue; } } else { fprintf(stderr, "mbdesktop-xine: cant open '%s'\n", data ); continue; } if (!xinebrowser_play(mb, mod_data, mrl)) { fprintf(stderr, "mbdesktop-xine: *WARNING* Play failed"); } else { fprintf(stderr, "%s() playing '%'", __func__, mrl); xinebrowser_show_info (mb, mod_data, MBX_INFO_TIMEOUT); xinebrowser_win_event_loop (mb, mod_data); if (mod_data->running == 0) /* Hack for catching Quit */ { fclose(fp); goto end; } } free(mrl); } fclose(fp); end: xinebrowser_win_close (mb, mod_data); mod_data->current_mode = MBX_MODE_UNKNOWN; } void xinebrowser_playlists_open_cb (void *data1, void *data2) { BrowserData *mod_data; MBDesktopItem *item_new = NULL; MBDesktop *mb = (MBDesktop *)data1; MBDesktopItem *item_folder = (MBDesktopItem *)data2; regex_t re; DIR *dp; struct dirent *dir_entry; struct stat stat_info; char orig_wd[256]; int i; mod_data = (BrowserData*)mbdesktop_item_get_user_data (mb, item_folder); if (!mod_data->BrowserPlaylistsPath) return; if (mbdesktop_item_folder_has_contents(mb, item_folder)) mbdesktop_item_folder_contents_free(mb, item_folder); if (regcomp(&re, ".*(txt|m3u)$", REG_EXTENDED|REG_ICASE|REG_NOSUB) != 0) { fprintf(stderr, "mbdesktop-xinebrowser: failed to compile regexp\n"); return; } if (getcwd(orig_wd, 255) == (char *)NULL) { fprintf(stderr, "Cant get current directory\n"); return; } if ((dp = opendir(mod_data->BrowserPlaylistsPath)) == NULL) { fprintf(stderr, "mbdesktop: failed to open %s\n", mod_data->BrowserRadioPath); return; } chdir(mod_data->BrowserPlaylistsPath); while((dir_entry = readdir(dp)) != NULL) { lstat(dir_entry->d_name, &stat_info); if (!(S_ISDIR(stat_info.st_mode))) { if (regexec(&re, dir_entry->d_name, 0, NULL, REG_NOTBOL) == 0) { char *nice_name = NULL, *prefix = NULL, *full_path = NULL; full_path = malloc(sizeof(char)*(strlen(mod_data->BrowserPlaylistsPath)+strlen(dir_entry->d_name)+2)); sprintf(full_path, "%s/%s", mod_data->BrowserPlaylistsPath, dir_entry->d_name); nice_name = strdup(dir_entry->d_name); if ((prefix = rindex(nice_name, '.')) != NULL) *prefix = '\0'; item_new = mbdesktop_item_new_with_params( mb, nice_name, NULL, NULL, ITEM_TYPE_MODULE_ITEM ); mbdesktop_item_set_user_data(mb, item_new, (void *)mod_data); mbdesktop_item_set_extended_name (mb, item_new, full_path); mbdesktop_item_set_activate_callback(mb, item_new, xinebrowser_playlist_activate_cb); mbdesktop_items_append_to_folder(mb, item_folder, item_new ); free(nice_name); free(full_path); } } } regfree(&re); closedir(dp); chdir(orig_wd); mod_data->current_mode = MBX_MODE_MUSIC_PLAYLIST; mbdesktop_item_folder_activate_cb(data1, data2); }