diff --git a/command_mode.c b/command_mode.c index 88eb8d648..609f64646 100644 --- a/command_mode.c +++ b/command_mode.c @@ -340,11 +340,11 @@ struct window *current_win(void) case TREE_VIEW: return lib_cur_win; case SORTED_VIEW: - return lib_editable.win; + return lib_editable.shared->win; case PLAYLIST_VIEW: return pl_cursor_win(); case QUEUE_VIEW: - return pq_editable.win; + return pq_editable.shared->win; case BROWSER_VIEW: return browser_win; case HELP_VIEW: diff --git a/editable.c b/editable.c index 253607273..8b0a41a0a 100644 --- a/editable.c +++ b/editable.c @@ -37,41 +37,67 @@ static struct simple_track *get_selected(struct editable *e) { struct iter sel; - if (window_get_sel(e->win, &sel)) + if (window_get_sel(e->shared->win, &sel)) return iter_to_simple_track(&sel); return NULL; } -void editable_init(struct editable *e, void (*free_track)(struct list_head *item)) +void editable_shared_init(struct editable_shared *shared, + editable_free_track free_track) { - struct iter iter; + shared->win = window_new(simple_track_get_prev, simple_track_get_next); + shared->sort_keys = xnew(sort_key_t, 1); + shared->sort_keys[0] = SORT_INVALID; + shared->sort_str[0] = 0; + shared->free_track = free_track; + shared->owner = NULL; + + struct iter iter = { 0 }; + shared->searchable = searchable_new(shared->win, &iter, + &simple_search_ops); +} +void editable_init(struct editable *e, struct editable_shared *shared, + int take_ownership) +{ list_init(&e->head); e->tree_root = RB_ROOT; e->nr_tracks = 0; e->nr_marked = 0; e->total_time = 0; - e->sort_keys = xnew(sort_key_t, 1); - e->sort_keys[0] = SORT_INVALID; - e->sort_str[0] = 0; - e->free_track = free_track; - - e->win = window_new(simple_track_get_prev, simple_track_get_next); - window_set_contents(e->win, &e->head); - - iter.data0 = &e->head; - iter.data1 = NULL; - iter.data2 = NULL; - e->searchable = searchable_new(e->win, &iter, &simple_search_ops); + e->shared = shared; + + + if (take_ownership) + editable_take_ownership(e); +} + +static int editable_owns_shared(struct editable *e) +{ + return e->shared->owner == e; +} + +void editable_take_ownership(struct editable *e) +{ + if (!editable_owns_shared(e)) { + e->shared->owner = e; + window_set_contents(e->shared->win, &e->head); + e->shared->win->changed = 1; + + struct iter iter = { .data0 = &e->head }; + searchable_set_head(e->shared->searchable, &iter); + } } static void do_editable_add(struct editable *e, struct simple_track *track, int tiebreak) { - sorted_list_add_track(&e->head, &e->tree_root, track, e->sort_keys, tiebreak); + sorted_list_add_track(&e->head, &e->tree_root, track, + e->shared->sort_keys, tiebreak); e->nr_tracks++; if (track->info->duration != -1) e->total_time += track->info->duration; - window_changed(e->win); + if (editable_owns_shared(e)) + window_changed(e->shared->win); } void editable_add(struct editable *e, struct simple_track *track) @@ -90,7 +116,8 @@ void editable_remove_track(struct editable *e, struct simple_track *track) struct iter iter; editable_track_to_iter(e, track, &iter); - window_row_vanishes(e->win, &iter); + if (editable_owns_shared(e)) + window_row_vanishes(e->shared->win, &iter); e->nr_tracks--; e->nr_marked -= track->marked; @@ -98,7 +125,7 @@ void editable_remove_track(struct editable *e, struct simple_track *track) e->total_time -= ti->duration; sorted_list_remove_track(&e->head, &e->tree_root, track); - e->free_track(&track->node); + e->shared->free_track(e, &track->node); } void editable_remove_sel(struct editable *e) @@ -127,17 +154,19 @@ void editable_sort(struct editable *e) { if (e->nr_tracks <= 1) return; - sorted_list_rebuild(&e->head, &e->tree_root, e->sort_keys); + sorted_list_rebuild(&e->head, &e->tree_root, e->shared->sort_keys); - window_changed(e->win); - window_goto_top(e->win); + if (editable_owns_shared(e)) { + window_changed(e->shared->win); + window_goto_top(e->shared->win); + } } -void editable_set_sort_keys(struct editable *e, sort_key_t *keys) +void editable_shared_set_sort_keys(struct editable_shared *shared, + sort_key_t *keys) { - free(e->sort_keys); - e->sort_keys = keys; - editable_sort(e); + free(shared->sort_keys); + shared->sort_keys = keys; } void editable_toggle_mark(struct editable *e) @@ -149,8 +178,10 @@ void editable_toggle_mark(struct editable *e) e->nr_marked -= t->marked; t->marked ^= 1; e->nr_marked += t->marked; - e->win->changed = 1; - window_down(e->win, 1); + if (editable_owns_shared(e)) { + e->shared->win->changed = 1; + window_down(e->shared->win, 1); + } } } @@ -160,7 +191,8 @@ static void move_item(struct editable *e, struct list_head *head, struct list_he struct iter iter; editable_track_to_iter(e, t, &iter); - window_row_vanishes(e->win, &iter); + if (editable_owns_shared(e)) + window_row_vanishes(e->shared->win, &iter); list_del(item); list_add(item, head); @@ -213,8 +245,11 @@ static void move_sel(struct editable *e, struct list_head *after) /* select top-most of the moved tracks */ editable_track_to_iter(e, to_simple_track(after->next), &iter); - window_set_sel(e->win, &iter); - window_changed(e->win); + + if (editable_owns_shared(e)) { + window_set_sel(e->shared->win, &iter); + window_changed(e->shared->win); + } } static struct list_head *find_insert_after_point(struct editable *e, struct list_head *item) @@ -266,7 +301,7 @@ void editable_move_after(struct editable *e) { struct simple_track *sel; - if (e->nr_tracks <= 1 || e->sort_keys[0] != SORT_INVALID) + if (e->nr_tracks <= 1 || e->shared->sort_keys[0] != SORT_INVALID) return; sel = get_selected(e); @@ -278,7 +313,7 @@ void editable_move_before(struct editable *e) { struct simple_track *sel; - if (e->nr_tracks <= 1 || e->sort_keys[0] != SORT_INVALID) + if (e->nr_tracks <= 1 || e->shared->sort_keys[0] != SORT_INVALID) return; sel = get_selected(e); @@ -325,7 +360,9 @@ void editable_mark(struct editable *e, const char *filter) e->nr_marked++; } } - e->win->changed = 1; + + if (editable_owns_shared(e)) + e->shared->win->changed = 1; } void editable_unmark(struct editable *e) @@ -336,7 +373,9 @@ void editable_unmark(struct editable *e) e->nr_marked -= t->marked; t->marked = 0; } - e->win->changed = 1; + + if (editable_owns_shared(e)) + e->shared->win->changed = 1; } void editable_invert_marks(struct editable *e) @@ -348,7 +387,9 @@ void editable_invert_marks(struct editable *e) t->marked ^= 1; e->nr_marked += t->marked; } - e->win->changed = 1; + + if (editable_owns_shared(e)) + e->shared->win->changed = 1; } int _editable_for_each_sel(struct editable *e, track_info_cb cb, void *data, @@ -374,8 +415,8 @@ int editable_for_each_sel(struct editable *e, track_info_cb cb, void *data, int rc; rc = _editable_for_each_sel(e, cb, data, reverse); - if (e->nr_marked == 0) - window_down(e->win, 1); + if (e->nr_marked == 0 && editable_owns_shared(e)) + window_down(e->shared->win, 1); return rc; } @@ -403,8 +444,8 @@ void editable_update_track(struct editable *e, struct track_info *old, struct tr changed = 1; } } - if (changed) - e->win->changed = changed; + if (editable_owns_shared(e)) + e->shared->win->changed |= changed; } void editable_rand(struct editable *e) @@ -412,8 +453,11 @@ void editable_rand(struct editable *e) if (e->nr_tracks <=1) return; rand_list_rebuild(&e->head, &e->tree_root); - window_changed(e->win); - window_goto_top(e->win); + + if (editable_owns_shared(e)) { + window_changed(e->shared->win); + window_goto_top(e->shared->win); + } } int editable_empty(struct editable *e) diff --git a/editable.h b/editable.h index c0b22ce75..ab515c68e 100644 --- a/editable.h +++ b/editable.h @@ -26,28 +26,43 @@ #include "locking.h" #include "cmus.h" -struct editable { +struct editable; + +typedef void (*editable_free_track)(struct editable *e, struct list_head *head); + +struct editable_shared { + struct editable *owner; + struct window *win; + sort_key_t *sort_keys; + char sort_str[128]; + editable_free_track free_track; + struct searchable *searchable; +}; + +struct editable { struct list_head head; struct rb_root tree_root; unsigned int nr_tracks; unsigned int nr_marked; unsigned int total_time; - sort_key_t *sort_keys; - char sort_str[128]; - struct searchable *searchable; - - void (*free_track)(struct list_head *item); + struct editable_shared *shared; }; -void editable_init(struct editable *e, void (*free_track)(struct list_head *item)); +void editable_shared_init(struct editable_shared *shared, + editable_free_track free_track); +void editable_shared_set_sort_keys(struct editable_shared *shared, + sort_key_t *keys); + +void editable_init(struct editable *e, struct editable_shared *shared, + int take_ownership); +void editable_take_ownership(struct editable *e); void editable_add(struct editable *e, struct simple_track *track); void editable_add_before(struct editable *e, struct simple_track *track); void editable_remove_track(struct editable *e, struct simple_track *track); void editable_remove_sel(struct editable *e); void editable_sort(struct editable *e); void editable_rand(struct editable *e); -void editable_set_sort_keys(struct editable *e, sort_key_t *keys); void editable_toggle_mark(struct editable *e); void editable_move_after(struct editable *e); void editable_move_before(struct editable *e); diff --git a/lib.c b/lib.c index 174674cf9..dc5365abf 100644 --- a/lib.c +++ b/lib.c @@ -30,6 +30,8 @@ #include struct editable lib_editable; +static struct editable_shared lib_editable_shared; + struct tree_track *lib_cur_track = NULL; unsigned int play_sorted = 0; enum aaa_mode aaa_mode = AAA_MODE_ALL; @@ -66,7 +68,7 @@ static void all_wins_changed(void) { lib_tree_win->changed = 1; lib_track_win->changed = 1; - lib_editable.win->changed = 1; + lib_editable.shared->win->changed = 1; } static void shuffle_add(struct tree_track *track) @@ -302,7 +304,7 @@ void lib_reshuffle(void) shuffle_list_reshuffle(&lib_shuffle_root); } -static void free_lib_track(struct list_head *item) +static void free_lib_track(struct editable *e, struct list_head *item) { struct tree_track *track = (struct tree_track *)to_simple_track(item); struct track_info *ti = tree_track_info(track); @@ -322,7 +324,8 @@ static void free_lib_track(struct list_head *item) void lib_init(void) { - editable_init(&lib_editable, free_lib_track); + editable_shared_init(&lib_editable_shared, free_lib_track); + editable_init(&lib_editable, &lib_editable_shared, 1); tree_init(); srand(time(NULL)); } @@ -391,7 +394,7 @@ static struct tree_track *sorted_get_selected(void) if (list_empty(&lib_editable.head)) return NULL; - window_get_sel(lib_editable.win, &sel); + window_get_sel(lib_editable.shared->win, &sel); return iter_to_sorted_track(&sel); } @@ -474,8 +477,8 @@ static void do_lib_filter(int clear_before) editable_remove_matching_tracks(&lib_editable, is_filtered_cb, NULL); remove_from_hash = 1; - window_changed(lib_editable.win); - window_goto_top(lib_editable.win); + window_changed(lib_editable.shared->win); + window_goto_top(lib_editable.shared->win); lib_cur_win = lib_tree_win; window_goto_top(lib_tree_win); @@ -523,7 +526,7 @@ static void set_sel_track(struct tree_track *tt) break; case SORTED_VIEW: sorted_track_to_iter(tt, &iter); - window_set_sel(lib_editable.win, &iter); + window_set_sel(lib_editable.shared->win, &iter); break; } } @@ -637,7 +640,7 @@ void sorted_sel_current(void) struct iter iter; sorted_track_to_iter(lib_cur_track, &iter); - window_set_sel(lib_editable.win, &iter); + window_set_sel(lib_editable.shared->win, &iter); } } @@ -646,7 +649,7 @@ static int ti_cmp(const void *a, const void *b) const struct track_info *ai = *(const struct track_info **)a; const struct track_info *bi = *(const struct track_info **)b; - return track_info_cmp(ai, bi, lib_editable.sort_keys); + return track_info_cmp(ai, bi, lib_editable.shared->sort_keys); } static int do_lib_for_each(int (*cb)(void *data, struct track_info *ti), void *data, int filtered) diff --git a/options.c b/options.c index 8d1b390f8..37e416127 100644 --- a/options.c +++ b/options.c @@ -331,7 +331,7 @@ static void set_icecast_default_charset(void *data, const char *buf) static void get_lib_sort(void *data, char *buf) { - strcpy(buf, lib_editable.sort_str); + strcpy(buf, lib_editable.shared->sort_str); } static void set_lib_sort(void *data, const char *buf) @@ -339,8 +339,10 @@ static void set_lib_sort(void *data, const char *buf) sort_key_t *keys = parse_sort_keys(buf); if (keys) { - editable_set_sort_keys(&lib_editable, keys); - sort_keys_to_str(keys, lib_editable.sort_str, sizeof(lib_editable.sort_str)); + editable_shared_set_sort_keys(lib_editable.shared, keys); + editable_sort(&lib_editable); + sort_keys_to_str(keys, lib_editable.shared->sort_str, + sizeof(lib_editable.shared->sort_str)); } } diff --git a/pl.c b/pl.c index e55c60f43..bb80da510 100644 --- a/pl.c +++ b/pl.c @@ -26,10 +26,11 @@ #include "worker.h" struct editable pl_editable; +struct editable_shared pl_editable_shared; struct simple_track *pl_cur_track = NULL; struct rb_root pl_shuffle_root; -static void pl_free_track(struct list_head *item) +static void pl_free_track(struct editable *e, struct list_head *item) { struct simple_track *track = to_simple_track(item); struct shuffle_track *shuffle_track = (struct shuffle_track *) track; @@ -44,7 +45,8 @@ static void pl_free_track(struct list_head *item) void pl_init(void) { - editable_init(&pl_editable, pl_free_track); + editable_shared_init(&pl_editable_shared, pl_free_track); + editable_init(&pl_editable, &pl_editable_shared, 1); cmus_add(pl_add_track, pl_autosave_filename, FILE_TYPE_PL, JOB_TYPE_PL, 0, NULL); } @@ -63,7 +65,7 @@ static struct track_info *set_track(struct simple_track *track) track_info_ref(ti); if (follow) pl_sel_current(); - pl_editable.win->changed = 1; + pl_editable_shared.win->changed = 1; } return ti; } @@ -107,7 +109,7 @@ struct track_info *pl_activate_selected(void) if (list_empty(&pl_editable.head)) return NULL; - window_get_sel(pl_editable.win, &sel); + window_get_sel(pl_editable_shared.win, &sel); return set_track(iter_to_simple_track(&sel)); } @@ -117,7 +119,7 @@ void pl_sel_current(void) struct iter iter; editable_track_to_iter(&pl_editable, pl_cur_track, &iter); - window_set_sel(pl_editable.win, &iter); + window_set_sel(pl_editable_shared.win, &iter); } } @@ -156,7 +158,7 @@ void pl_exit(void) struct searchable *pl_get_searchable(void) { - return pl_editable.searchable; + return pl_editable_shared.searchable; } unsigned int pl_playing_total_time(void) @@ -166,12 +168,12 @@ unsigned int pl_playing_total_time(void) void pl_set_nr_rows(int h) { - window_set_nr_rows(pl_editable.win, h); + window_set_nr_rows(pl_editable_shared.win, h); } int pl_needs_redraw(void) { - return pl_editable.win->changed; + return pl_editable_shared.win->changed; } void pl_invert_marks(void) @@ -241,7 +243,7 @@ void pl_load_extern(char *path) struct window *pl_cursor_win(void) { - return pl_editable.win; + return pl_editable_shared.win; } int _pl_for_each_sel(track_info_cb cb, void *data, int reverse) @@ -251,7 +253,7 @@ int _pl_for_each_sel(track_info_cb cb, void *data, int reverse) void pl_get_sort_str(char *buf) { - strcpy(buf, pl_editable.sort_str); + strcpy(buf, pl_editable_shared.sort_str); } void pl_set_sort_str(const char *buf) @@ -259,7 +261,9 @@ void pl_set_sort_str(const char *buf) sort_key_t *keys = parse_sort_keys(buf); if (keys) { - editable_set_sort_keys(&pl_editable, keys); - sort_keys_to_str(keys, pl_editable.sort_str, sizeof(pl_editable.sort_str)); + editable_shared_set_sort_keys(&pl_editable_shared, keys); + editable_sort(&pl_editable); + sort_keys_to_str(keys, pl_editable_shared.sort_str, + sizeof(pl_editable_shared.sort_str)); } } diff --git a/play_queue.c b/play_queue.c index 0efff9977..83dd7d2fa 100644 --- a/play_queue.c +++ b/play_queue.c @@ -22,8 +22,9 @@ #include "xmalloc.h" struct editable pq_editable; +static struct editable_shared pq_editable_shared; -static void pq_free_track(struct list_head *item) +static void pq_free_track(struct editable *e, struct list_head *item) { struct simple_track *track = to_simple_track(item); @@ -33,7 +34,8 @@ static void pq_free_track(struct list_head *item) void play_queue_init(void) { - editable_init(&pq_editable, pq_free_track); + editable_shared_init(&pq_editable_shared, pq_free_track); + editable_init(&pq_editable, &pq_editable_shared, 1); } void play_queue_append(struct track_info *ti, void *opaque) diff --git a/ui_curses.c b/ui_curses.c index 3772b7149..2e11f73e2 100644 --- a/ui_curses.c +++ b/ui_curses.c @@ -1048,9 +1048,10 @@ static void update_editable_window(struct editable *e, const char *title, const } pos = strlen(buf); snprintf(buf + pos, sizeof(buf) - pos, " %s%s", - sorted_names[e->sort_str[0] != 0], e->sort_str); + sorted_names[e->shared->sort_str[0] != 0], + e->shared->sort_str); - update_window(e->win, 0, 0, COLS, buf, &print_editable); + update_window(e->shared->win, 0, 0, COLS, buf, &print_editable); } static void update_sorted_window(void) @@ -1632,13 +1633,13 @@ void set_view(int view) searchable = tree_searchable; break; case SORTED_VIEW: - searchable = lib_editable.searchable; + searchable = lib_editable.shared->searchable; break; case PLAYLIST_VIEW: searchable = pl_get_searchable(); break; case QUEUE_VIEW: - searchable = pq_editable.searchable; + searchable = pq_editable.shared->searchable; break; case BROWSER_VIEW: searchable = browser_searchable; @@ -1865,9 +1866,9 @@ static void update(void) if (h < 2) h = 2; resize_tree_view(w, h); - window_set_nr_rows(lib_editable.win, h - 1); + window_set_nr_rows(lib_editable.shared->win, h - 1); pl_set_nr_rows(h - 1); - window_set_nr_rows(pq_editable.win, h - 1); + window_set_nr_rows(pq_editable.shared->win, h - 1); window_set_nr_rows(filters_win, h - 1); window_set_nr_rows(help_win, h - 1); window_set_nr_rows(browser_win, h - 1); @@ -1901,13 +1902,13 @@ static void update(void) needs_view_update += lib_tree_win->changed || lib_track_win->changed; break; case SORTED_VIEW: - needs_view_update += lib_editable.win->changed; + needs_view_update += lib_editable.shared->win->changed; break; case PLAYLIST_VIEW: needs_view_update += pl_needs_redraw(); break; case QUEUE_VIEW: - needs_view_update += pq_editable.win->changed; + needs_view_update += pq_editable.shared->win->changed; break; case BROWSER_VIEW: needs_view_update += browser_win->changed; @@ -1922,11 +1923,11 @@ static void update(void) /* total time changed? */ if (play_library) { - needs_status_update += lib_editable.win->changed; - lib_editable.win->changed = 0; + needs_status_update += lib_editable.shared->win->changed; + lib_editable.shared->win->changed = 0; } else { needs_status_update += pl_needs_redraw(); - pl_editable.win->changed = 0; + pl_editable.shared->win->changed = 0; } if (needs_spawn)