Implement afs events.
[paraslash.git] / playlist.c
index 6f9f966..56e19fe 100644 (file)
@@ -1,8 +1,8 @@
 #include "para.h"
 #include "error.h"
 #include "para.h"
 #include "error.h"
+#include "string.h"
 #include "afh.h"
 #include "afs.h"
 #include "afh.h"
 #include "afs.h"
-#include "string.h"
 
 /** \file playlist.c Functions for loading and saving playlists. */
 
 
 /** \file playlist.c Functions for loading and saving playlists. */
 
@@ -40,7 +40,7 @@ static int add_playlist_entry(char *path, void *data)
        }
        ret = score_add(aft_row, -playlist->length);
        if (ret < 0) {
        }
        ret = score_add(aft_row, -playlist->length);
        if (ret < 0) {
-               PARA_ERROR_LOG("failed to add %s: %d\n", path, ret);
+               PARA_ERROR_LOG("failed to add %s: %s\n", path, PARA_STRERROR(-ret));
                return ret;
        }
        playlist->length++;
                return ret;
        }
        playlist->length++;
@@ -122,6 +122,14 @@ static int check_playlist(struct osl_row *row, void *data)
        return 1;
 }
 
        return 1;
 }
 
+/**
+ * Check the playlist table for inconsistencies.
+ *
+ * \param query Unused.
+ * \param result Contains messages about inconsistencies.
+ *
+ * \return The return value of the underlying call to osl_rbtree_loop().
+ */
 int playlist_check_callback(__a_unused const struct osl_object *query,
                struct osl_object *result)
 {
 int playlist_check_callback(__a_unused const struct osl_object *query,
                struct osl_object *result)
 {
@@ -173,5 +181,73 @@ int playlist_open(char *name)
                PARA_NOTICE_LOG("failed to load playlist %s\n", name);
                return ret;
        }
                PARA_NOTICE_LOG("failed to load playlist %s\n", name);
                return ret;
        }
-       return load_playlist(row, &current_playlist);
+       ret = load_playlist(row, &current_playlist);
+       return (ret == -E_PLAYLIST_LOADED)? 1 : ret;
+}
+
+static int search_path(char *path, void *data)
+{
+       if (strcmp(path, data))
+               return 1;
+       return -E_PATH_FOUND;
+}
+
+static int handle_audio_file_event(enum afs_events event, void *data)
+{
+       int ret, was_admissible = 0, is_admissible;
+       struct osl_object playlist_def;
+       char *new_path;
+       const struct osl_row *row = data;
+
+       if (!current_playlist.name)
+               return 1;
+       if (event == AUDIO_FILE_RENAME) {
+               ret = row_belongs_to_score_table(row, NULL);
+               if (ret < 0)
+                       return ret;
+               was_admissible = ret;
+       }
+       ret = get_audio_file_path_of_row(row, &new_path);
+       if (ret < 0)
+               return ret;
+       ret = pl_get_def_by_name(current_playlist.name, &playlist_def);
+       if (ret < 0)
+               return ret;
+       ret = for_each_line_ro(playlist_def.data, playlist_def.size,
+               search_path, new_path);
+       osl_close_disk_object(&playlist_def);
+       is_admissible = (ret < 0);
+       if (was_admissible && is_admissible)
+               return 1;
+       if (!was_admissible && !is_admissible)
+               return 1;
+       if (was_admissible && !is_admissible) {
+               current_playlist.length--;
+               return score_delete(row);
+       }
+       /* !was_admissible && is_admissible */
+       current_playlist.length++;
+       return score_add(row, 0); /* play it immediately */
+}
+
+int playlists_event_handler(enum afs_events event, struct para_buffer *pb,
+               void *data)
+{
+       int ret;
+
+       switch(event) {
+       case AUDIO_FILE_RENAME:
+       case AUDIO_FILE_ADD:
+               return handle_audio_file_event(event, data);
+       case AUDIO_FILE_REMOVE:
+               ret = row_belongs_to_score_table(data, NULL);
+               if (ret < 0)
+                       return ret;
+               if (!ret)
+                       return 1;
+               current_playlist.length--;
+               return score_delete(data);
+       default:
+               return 1;
+       }
 }
 }