Code

go to root/parent dir key added
[ncmpc.git] / src / screen_file.c
index d25229d1e1a41070179b1296ab584ca8dc374914..4a4bdf70c1bcb0b65b5842cf5ba1c2d13a71bbbd 100644 (file)
@@ -33,7 +33,8 @@
 #include "command.h"
 #include "screen.h"
 #include "screen_utils.h"
-
+#include "screen_browse.h"
+#include "screen_play.h"
 
 #define USE_OLD_LAYOUT
 #undef  USE_OLD_ADD
 
 
 static list_window_t *lw = NULL;
-static GList *lw_state_list = NULL;
+static list_window_state_t *lw_state = NULL;
 static mpdclient_filelist_t *filelist = NULL;
 
 
 
 /* clear the highlight flag for all items in the filelist */
-static void
+void
 clear_highlights(mpdclient_filelist_t *filelist)
 {
   GList *list = g_list_first(filelist->list);
@@ -65,7 +66,7 @@ clear_highlights(mpdclient_filelist_t *filelist)
 }
 
 /* change the highlight flag for a song */
-static void
+void
 set_highlight(mpdclient_filelist_t *filelist, mpd_Song *song, int highlight)
 {
   GList *list = g_list_first(filelist->list);
@@ -95,7 +96,7 @@ set_highlight(mpdclient_filelist_t *filelist, mpd_Song *song, int highlight)
 }
 
 /* sync highlight flags with playlist */
-static void
+void
 sync_highlights(mpdclient_t *c, mpdclient_filelist_t *filelist)
 {
   GList *list = g_list_first(filelist->list);
@@ -152,37 +153,12 @@ playlist_changed_callback(mpdclient_t *c, int event, gpointer data)
     }
 }
 
-/* store current state when entering a subdirectory */
-static void
-push_lw_state(void)
-{
-  list_window_t *tmp = g_malloc(sizeof(list_window_t));
-
-  memcpy(tmp, lw, sizeof(list_window_t));
-  lw_state_list = g_list_prepend(lw_state_list, (gpointer) tmp);
-}
-
-/* get previous state when leaving a directory */
-static void
-pop_lw_state(void)
-{
-  if( lw_state_list )
-    {
-      list_window_t *tmp = lw_state_list->data;
-
-      memcpy(lw, tmp, sizeof(list_window_t));
-      g_free(tmp);
-      lw_state_list->data = NULL;
-      lw_state_list = g_list_delete_link(lw_state_list, lw_state_list);
-    }
-}
-
 /* list_window callback */
-static char *
-list_callback(int index, int *highlight, void *data)
+char *
+browse_lw_callback(int index, int *highlight, void *data)
 {
   static char buf[BUFSIZE];
-  /*mpdclient_t *c = (mpdclient_t *) data;*/
+  mpdclient_filelist_t *filelist = (mpdclient_filelist_t *) data;
   filelist_entry_t *entry;
   mpd_InfoEntity *entity;
 
@@ -226,28 +202,41 @@ list_callback(int index, int *highlight, void *data)
       g_free(filename);
       return buf;
     }
-  return "Error: Unknow entry!";
+  return "Error: Unknown entry!";
 }
 
 /* chdir */
 static int
-change_directory(screen_t *screen, mpdclient_t *c, filelist_entry_t *entry)
+change_directory(screen_t *screen, mpdclient_t *c, filelist_entry_t *entry, char *new_path)
 {
-  mpd_InfoEntity *entity = entry->entity;
+  mpd_InfoEntity *entity = NULL;
   gchar *path = NULL;
 
+  if( entry!=NULL )
+    entity = entry->entity;
+  else if( new_path==NULL )
+    return -1;
+
   if( entity==NULL )
     {
-      /* return to parent */
-      char *parent = g_path_get_dirname(filelist->path);
-      if( strcmp(parent, ".") == 0 )
+      if( entry || 0==strcmp(new_path, "..") )
        {
-         parent[0] = '\0';
+         /* return to parent */
+         char *parent = g_path_get_dirname(filelist->path);
+         if( strcmp(parent, ".") == 0 )
+           {
+             parent[0] = '\0';
+           }
+         path = g_strdup(parent);
+       }
+      else
+       {
+         /* entry==NULL, then new_path ("" is root) */
+         path = g_strdup(new_path);
        }
-      path = g_strdup(parent);
       list_window_reset(lw);
       /* restore previous list window state */
-      pop_lw_state(); 
+      list_window_pop_state(lw_state,lw); 
     }
   else
     if( entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY)
@@ -256,8 +245,7 @@ change_directory(screen_t *screen, mpdclient_t *c, filelist_entry_t *entry)
        mpd_Directory *dir = entity->info.directory;
        path = utf8_to_locale(dir->path);      
        /* save current list window state */
-       push_lw_state(); 
-       list_window_reset(lw);
+       list_window_push_state(lw_state,lw); 
       }
     else
       return -1;
@@ -283,6 +271,26 @@ load_playlist(screen_t *screen, mpdclient_t *c, filelist_entry_t *entry)
   return 0;
 }
 
+static int
+handle_save(screen_t *screen, mpdclient_t *c)
+{
+  filelist_entry_t *entry;
+  char *defaultname = NULL;
+
+
+  entry=( filelist_entry_t *) g_list_nth_data(filelist->list,lw->selected);
+  if( entry && entry->entity )
+    { 
+      mpd_InfoEntity *entity = entry->entity;
+      if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
+       {
+         mpd_PlaylistFile *plf = entity->info.playlistFile;
+         defaultname = plf->path;
+       }
+    }
+  return playlist_save(screen, c, NULL, defaultname);
+}
+
 static int 
 handle_delete(screen_t *screen, mpdclient_t *c)
 {
@@ -327,22 +335,55 @@ handle_delete(screen_t *screen, mpdclient_t *c)
   return 0;
 }
 
-
 static int
-handle_enter(screen_t *screen, mpdclient_t *c)
+enqueue_and_play(screen_t *screen, mpdclient_t *c, filelist_entry_t *entry)
+{
+  int index;
+  mpd_InfoEntity *entity = entry->entity;
+  mpd_Song *song = entity->info.song;
+  
+  if(!( entry->flags & HIGHLIGHT ))
+    {
+      if( mpdclient_cmd_add(c, song) == 0 )
+       {
+         char buf[BUFSIZE];
+         
+         entry->flags |= HIGHLIGHT;
+         strfsong(buf, BUFSIZE, LIST_FORMAT, song);
+         screen_status_printf(_("Adding \'%s\' to playlist\n"), buf);
+         mpdclient_update(c); /* get song id */
+       } 
+      else
+       return -1;
+    }
+  
+  index = playlist_get_index_from_file(c, song->file);
+  mpdclient_cmd_play(c, index);
+  return 0;
+}
+
+int
+browse_handle_enter(screen_t *screen, 
+                   mpdclient_t *c,
+                   list_window_t *lw,
+                   mpdclient_filelist_t *filelist)
 {
   filelist_entry_t *entry;
   mpd_InfoEntity *entity;
   
+  if ( filelist==NULL )
+    return -1;
   entry = ( filelist_entry_t *) g_list_nth_data(filelist->list, lw->selected);
   if( entry==NULL )
     return -1;
 
   entity = entry->entity;
   if( entity==NULL || entity->type==MPD_INFO_ENTITY_TYPE_DIRECTORY )
-    return change_directory(screen, c, entry);
+    return change_directory(screen, c, entry, NULL);
   else if( entity->type==MPD_INFO_ENTITY_TYPE_PLAYLISTFILE )
     return load_playlist(screen, c, entry);
+  else if( entity->type==MPD_INFO_ENTITY_TYPE_SONG )
+    return enqueue_and_play(screen, c, entry);
   return -1;
 }
 
@@ -403,11 +444,16 @@ add_directory(mpdclient_t *c, char *dir)
 }
 #endif
 
-static int
-handle_select(screen_t *screen, mpdclient_t *c)
+int
+browse_handle_select(screen_t *screen, 
+                    mpdclient_t *c,
+                    list_window_t *lw,
+                    mpdclient_filelist_t *filelist)
 {
   filelist_entry_t *entry;
 
+  if ( filelist==NULL )
+    return -1;
   entry=( filelist_entry_t *) g_list_nth_data(filelist->list, lw->selected);
   if( entry==NULL || entry->entity==NULL)
     return -1;
@@ -478,6 +524,7 @@ static void
 browse_init(WINDOW *w, int cols, int rows)
 {
   lw = list_window_init(w, cols, rows);
+  lw_state = list_window_init_state();
 }
 
 static void
@@ -490,22 +537,10 @@ browse_resize(int cols, int rows)
 static void
 browse_exit(void)
 {
-  if( lw_state_list )
-    {
-      GList *list = lw_state_list;
-      while( list )
-       {
-         g_free(list->data);
-         list->data = NULL;
-         list = list->next;
-       }
-      g_list_free(lw_state_list);
-      lw_state_list = NULL;
-
-    }
   if( filelist )
     filelist = mpdclient_filelist_free(filelist);
-  list_window_free(lw);
+  lw = list_window_free(lw);
+  lw_state = list_window_free_state(lw_state);
 }
 
 static void 
@@ -527,7 +562,20 @@ browse_close(void)
 static char *
 browse_title(char *str, size_t size)
 {
-  g_snprintf(str, size, _("Browse: %s"), basename(filelist->path));
+  char *pathcopy;
+  char *parentdir;
+  pathcopy = strdup(filelist->path);
+  parentdir = dirname(pathcopy);
+  parentdir = basename(parentdir);
+  if( parentdir[0] == '.' && strlen(parentdir) == 1 )
+    {
+      parentdir = NULL;
+    }
+  g_snprintf(str, size, _("Browse: %s%s%s"),
+            parentdir ? parentdir : "",
+            parentdir ? "/" : "",
+            basename(filelist->path));
+  free(pathcopy);
   return str;
 }
 
@@ -536,7 +584,7 @@ browse_paint(screen_t *screen, mpdclient_t *c)
 {
   lw->clear = 1;
   
-  list_window_paint(lw, list_callback, (void *) c);
+  list_window_paint(lw, browse_lw_callback, (void *) filelist);
   wnoutrefresh(lw->w);
 }
 
@@ -549,41 +597,48 @@ browse_update(screen_t *screen, mpdclient_t *c)
       filelist->updated = FALSE;
       return;
     }
-  list_window_paint(lw, list_callback, (void *) c);
+  list_window_paint(lw, browse_lw_callback, (void *) filelist);
   wnoutrefresh(lw->w);
 }
 
 
 #ifdef HAVE_GETMOUSE
-static int
-handle_mouse_event(screen_t *screen, mpdclient_t *c)
+int
+browse_handle_mouse_event(screen_t *screen, 
+                         mpdclient_t *c,
+                         list_window_t *lw,
+                         mpdclient_filelist_t *filelist)
 {
   int row;
   int prev_selected = lw->selected;
   unsigned long bstate;
+  int length;
 
-  if( screen_get_mouse_event(c, lw, filelist->length, &bstate, &row) )
+  if ( filelist )
+    length = filelist->length;
+  else
+    length = 0;
+
+  if( screen_get_mouse_event(c, lw, length, &bstate, &row) )
     return 1;
 
   lw->selected = lw->start+row;
-  list_window_check_selected(lw, filelist->length);
+  list_window_check_selected(lw, length);
 
   if( bstate & BUTTON1_CLICKED )
     {
       if( prev_selected == lw->selected )
-       handle_enter(screen, c);
+       browse_handle_enter(screen, c, lw, filelist);
     }
   else if( bstate & BUTTON3_CLICKED )
     {
       if( prev_selected == lw->selected )
-       handle_select(screen, c);
+       browse_handle_select(screen, c, lw, filelist);
     }
 
   return 1;
 }
-#else
-#define handle_mouse_event(s,c) (0)
-#endif
+#endif 
 
 static int 
 browse_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
@@ -591,10 +646,16 @@ browse_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
   switch(cmd)
     {
     case CMD_PLAY:
-      handle_enter(screen, c);
+      browse_handle_enter(screen, c, lw, filelist);
       return 1;
+    case CMD_GO_ROOT_DIRECTORY:
+      return change_directory(screen, c, NULL, "");
+      break;
+    case CMD_GO_PARENT_DIRECTORY:
+      return change_directory(screen, c, NULL, "..");
+      break;
     case CMD_SELECT:
-      if( handle_select(screen, c) == 0 )
+      if( browse_handle_select(screen, c, lw, filelist) == 0 )
        {
          /* continue and select next item... */
          cmd = CMD_LIST_NEXT;
@@ -603,6 +664,9 @@ browse_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
     case CMD_DELETE:
       handle_delete(screen, c);
       break;
+    case CMD_SAVE_PLAYLIST:
+      handle_save(screen, c);
+      break;
     case CMD_SCREEN_UPDATE:
       screen->painted = 0;
       lw->clear = 1;
@@ -616,8 +680,12 @@ browse_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
        {
          if( mpdclient_cmd_db_update_utf8(c,filelist->path)==0 )
            {
-             screen_status_printf(_("Database update of %s started!"),
+             if(strcmp(filelist->path,"")) {
+                screen_status_printf(_("Database update of %s started!"),
                                   filelist->path);
+             } else {
+               screen_status_printf(_("Database update started!"));
+             }
              /* set updatingDb to make shure the browse callback gets called
               * even if the updated has finished before status is updated */
              c->status->updatingDb = 1; 
@@ -632,9 +700,9 @@ browse_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
     case CMD_LIST_RFIND_NEXT:
       return screen_find(screen, c, 
                         lw, filelist->length,
-                        cmd, list_callback);
+                        cmd, browse_lw_callback, (void *) filelist);
     case CMD_MOUSE_EVENT:
-      return handle_mouse_event(screen,c);
+      return browse_handle_mouse_event(screen,c,lw,filelist);
     default:
       break;
     }