1
/*
2
 * Copyright 2008-2011 Various Authors
3
 * Copyright 2006 Timo Hirvonen
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License as
7
 * published by the Free Software Foundation; either version 2 of the
8
 * License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful, but
11
 * WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
 * General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17
 */
18
19
#include "lib.h"
20
#include "search_mode.h"
21
#include "xmalloc.h"
22
#include "utils.h"
23
#include "debug.h"
24
#include "mergesort.h"
25
#include "options.h"
26
#include "u_collate.h"
27
#include "rbtree.h"
28
29
#include <ctype.h>
30
#include <stdio.h>
31
#include <string.h>
32
#include <strings.h>
33
34
struct searchable *tree_searchable;
35
struct window *lib_tree_win;
36
struct window *lib_track_win;
37
struct window *lib_cur_win;
38
struct rb_root lib_artist_root;
39
40
static inline void tree_search_track_to_iter(struct tree_track *track, struct iter *iter)
41
{
42
	iter->data0 = &lib_artist_root;
43
	iter->data1 = track;
44
	iter->data2 = NULL;
45
}
46
47
static inline void album_to_iter(struct album *album, struct iter *iter)
48
{
49
	iter->data0 = &lib_artist_root;
50
	iter->data1 = album->artist;
51
	iter->data2 = album;
52
}
53
54
static inline void artist_to_iter(struct artist *artist, struct iter *iter)
55
{
56
	iter->data0 = &lib_artist_root;
57
	iter->data1 = artist;
58
	iter->data2 = NULL;
59
}
60
61
static inline void tree_track_to_iter(struct tree_track *track, struct iter *iter)
62
{
63
	iter->data0 = &track->album->track_root;
64
	iter->data1 = track;
65
	iter->data2 = NULL;
66
}
67
68
static void tree_set_expand_artist(struct artist *artist, int expand)
69
{
70
	struct iter sel;
71
72
	if (expand) {
73
		artist->expanded = 1;
74
	} else {
75
		/* deselect album, select artist */
76
		artist_to_iter(artist, &sel);
77
		window_set_sel(lib_tree_win, &sel);
78
79
		artist->expanded = 0;
80
		lib_cur_win = lib_tree_win;
81
	}
82
	window_changed(lib_tree_win);
83
}
84
85
/* tree (search) iterators {{{ */
86
static int tree_search_get_prev(struct iter *iter)
87
{
88
	struct rb_root *root = iter->data0;
89
	struct tree_track *track = iter->data1;
90
	struct artist *artist;
91
	struct album *album;
92
93
	BUG_ON(iter->data2);
94
	if (root == NULL)
95
		return 0;
96
	if (track == NULL) {
97
		/* head, get last track */
98
		if (rb_root_empty(root)) {
99
			/* empty, iter points to the head already */
100
			return 0;
101
		}
102
		artist = to_artist(rb_last(root));
103
		album = to_album(rb_last(&artist->album_root));
104
		iter->data1 = to_tree_track(rb_last(&album->track_root));
105
		return 1;
106
	}
107
	/* prev track */
108
	if (rb_prev(&track->tree_node) == NULL || search_restricted) {
109
		/* prev album */
110
		if (rb_prev(&track->album->tree_node) == NULL) {
111
			/* prev artist */
112
			if (rb_prev(&track->album->artist->tree_node) == NULL)
113
				return 0;
114
			artist = to_artist(rb_prev(&track->album->artist->tree_node));
115
			album = to_album(rb_last(&artist->album_root));
116
			track = to_tree_track(rb_last(&album->track_root));
117
		} else {
118
			album = to_album(rb_prev(&track->album->tree_node));
119
			track = to_tree_track(rb_last(&album->track_root));
120
		}
121
	} else {
122
		track = to_tree_track(rb_prev(&track->tree_node));
123
	}
124
	iter->data1 = track;
125
	return 1;
126
}
127
128
static int tree_search_get_next(struct iter *iter)
129
{
130
	struct rb_root *root = iter->data0;
131
	struct tree_track *track = iter->data1;
132
	struct artist *artist;
133
	struct album *album;
134
135
	BUG_ON(iter->data2);
136
	if (root == NULL)
137
		return 0;
138
	if (track == NULL) {
139
		/* head, get first track */
140
		if (rb_root_empty(root)) {
141
			/* empty, iter points to the head already */
142
			return 0;
143
		}
144
		artist = to_artist(rb_first(root));
145
		album = to_album(rb_first(&artist->album_root));
146
		iter->data1 = to_tree_track(rb_first(&album->track_root));
147
		return 1;
148
	}
149
	/* next track */
150
	if (rb_next(&track->tree_node) == NULL || search_restricted) {
151
		/* next album */
152
		if (rb_next(&track->album->tree_node) == NULL) {
153
			/* next artist */
154
			if (rb_next(&track->album->artist->tree_node) == NULL)
155
				return 0;
156
			artist = to_artist(rb_next(&track->album->artist->tree_node));
157
			album = to_album(rb_first(&artist->album_root));
158
			track = to_tree_track(rb_first(&album->track_root));
159
		} else {
160
			album = to_album(rb_next(&track->album->tree_node));
161
			track = to_tree_track(rb_first(&album->track_root));
162
		}
163
	} else {
164
		track = to_tree_track(rb_next(&track->tree_node));
165
	}
166
	iter->data1 = track;
167
	return 1;
168
}
169
/* }}} */
170
171
/* tree window iterators {{{ */
172
static int tree_get_prev(struct iter *iter)
173
{
174
	struct rb_root *root = iter->data0;
175
	struct artist *artist = iter->data1;
176
	struct album *album = iter->data2;
177
178
	BUG_ON(root == NULL);
179
	BUG_ON(artist == NULL && album != NULL);
180
	if (artist == NULL) {
181
		/* head, get last artist and/or album */
182
		if (rb_root_empty(root)) {
183
			/* empty, iter points to the head already */
184
			return 0;
185
		}
186
		artist = to_artist(rb_last(root));
187
		if (artist->expanded) {
188
			album = to_album(rb_last(&artist->album_root));
189
		} else {
190
			album = NULL;
191
		}
192
		iter->data1 = artist;
193
		iter->data2 = album;
194
		return 1;
195
	}
196
	if (artist->expanded && album) {
197
		/* prev album */
198
		if (rb_prev(&album->tree_node) == NULL) {
199
			iter->data2 = NULL;
200
			return 1;
201
		} else {
202
			iter->data2 = to_album(rb_prev(&album->tree_node));
203
			return 1;
204
		}
205
	}
206
207
	/* prev artist */
208
	if (rb_prev(&artist->tree_node) == NULL) {
209
		iter->data1 = NULL;
210
		iter->data2 = NULL;
211
		return 0;
212
	}
213
	artist = to_artist(rb_prev(&artist->tree_node));
214
	iter->data1 = artist;
215
	iter->data2 = NULL;
216
	if (artist->expanded) {
217
		/* last album */
218
		iter->data2 = to_album(rb_last(&artist->album_root));
219
	}
220
	return 1;
221
}
222
223
static int tree_get_next(struct iter *iter)
224
{
225
	struct rb_root *root = iter->data0;
226
	struct artist *artist = iter->data1;
227
	struct album *album = iter->data2;
228
229
	BUG_ON(root == NULL);
230
	BUG_ON(artist == NULL && album != NULL);
231
	if (artist == NULL) {
232
		/* head, get first artist */
233
		if (rb_root_empty(root)) {
234
			/* empty, iter points to the head already */
235
			return 0;
236
		}
237
		iter->data1 = to_artist(rb_first(root));
238
		iter->data2 = NULL;
239
		return 1;
240
	}
241
	if (artist->expanded) {
242
		/* next album */
243
		if (album == NULL) {
244
			/* first album */
245
			iter->data2 = to_album(rb_first(&artist->album_root));
246
			return 1;
247
		}
248
		if (rb_next(&album->tree_node) != NULL) {
249
			iter->data2 = to_album(rb_next(&album->tree_node));
250
			return 1;
251
		}
252
	}
253
254
	/* next artist */
255
	if (rb_next(&artist->tree_node) == NULL) {
256
		iter->data1 = NULL;
257
		iter->data2 = NULL;
258
		return 0;
259
	}
260
	iter->data1 = to_artist(rb_next(&artist->tree_node));
261
	iter->data2 = NULL;
262
	return 1;
263
}
264
/* }}} */
265
266
static GENERIC_TREE_ITER_PREV(tree_track_get_prev, struct tree_track, tree_node)
267
static GENERIC_TREE_ITER_NEXT(tree_track_get_next, struct tree_track, tree_node)
268
269
/* search (tree) {{{ */
270
static int tree_search_get_current(void *data, struct iter *iter)
271
{
272
	struct artist *artist;
273
	struct album *album;
274
	struct tree_track *track;
275
	struct iter tmpiter;
276
277
	if (rb_root_empty(&lib_artist_root))
278
		return 0;
279
	if (window_get_sel(lib_track_win, &tmpiter)) {
280
		track = iter_to_tree_track(&tmpiter);
281
		tree_search_track_to_iter(track, iter);
282
		return 1;
283
	}
284
285
	/* artist not expanded. track_win is empty
286
	 * set tmp to the first track of the selected artist */
287
	window_get_sel(lib_tree_win, &tmpiter);
288
	artist = iter_to_artist(&tmpiter);
289
	album = to_album(rb_first(&artist->album_root));
290
	track = to_tree_track(rb_first(&album->track_root));
291
	tree_search_track_to_iter(track, iter);
292
	return 1;
293
}
294
295
static inline struct tree_track *iter_to_tree_search_track(const struct iter *iter)
296
{
297
	BUG_ON(iter->data0 != &lib_artist_root);
298
	return iter->data1;
299
}
300
301
static int tree_search_matches(void *data, struct iter *iter, const char *text);
302
303
static const struct searchable_ops tree_search_ops = {
304
	.get_prev = tree_search_get_prev,
305
	.get_next = tree_search_get_next,
306
	.get_current = tree_search_get_current,
307
	.matches = tree_search_matches
308
};
309
/* search (tree) }}} */
310
311
static inline int album_selected(struct album *album)
312
{
313
	struct iter sel;
314
315
	if (window_get_sel(lib_tree_win, &sel))
316
		return album == iter_to_album(&sel);
317
	return 0;
318
}
319
320
static void tree_sel_changed(void)
321
{
322
	struct iter sel;
323
	struct album *album;
324
325
	window_get_sel(lib_tree_win, &sel);
326
	album = iter_to_album(&sel);
327
	if (album == NULL) {
328
		window_set_empty(lib_track_win);
329
	} else {
330
		window_set_contents(lib_track_win, &album->track_root);
331
	}
332
}
333
334
static inline void tree_win_get_selected(struct artist **artist, struct album **album)
335
{
336
	struct iter sel;
337
338
	*artist = NULL;
339
	*album = NULL;
340
	if (window_get_sel(lib_tree_win, &sel)) {
341
		*artist = iter_to_artist(&sel);
342
		*album = iter_to_album(&sel);
343
	}
344
}
345
346
static char *auto_artist_sort_name(const char *name)
347
{
348
	const char *name_orig = name;
349
	char *buf;
350
351
	if (strncasecmp(name, "the ", 4) != 0)
352
		return NULL;
353
354
	name += 4;
355
	while (isspace((int)*name))
356
		++name;
357
358
	if (*name == '\0')
359
		return NULL;
360
361
	buf = xnew(char, strlen(name_orig) + 2);
362
	sprintf(buf, "%s, %c%c%c", name, name_orig[0],
363
					 name_orig[1],
364
					 name_orig[2]);
365
	return buf;
366
}
367
368
static struct artist *artist_new(const char *name, const char *sort_name, int is_compilation)
369
{
370
	struct artist *a = xnew(struct artist, 1);
371
372
	a->name = xstrdup(name);
373
	a->sort_name = sort_name ? xstrdup(sort_name) : NULL;
374
	a->auto_sort_name = auto_artist_sort_name(name);
375
	a->collkey_name = u_strcasecoll_key(a->name);
376
	a->collkey_sort_name = u_strcasecoll_key0(a->sort_name);
377
	a->collkey_auto_sort_name = u_strcasecoll_key0(a->auto_sort_name);
378
	a->expanded = 0;
379
	a->is_compilation = is_compilation;
380
	rb_root_init(&a->album_root);
381
382
	return a;
383
}
384
385
static struct artist *artist_copy(const struct artist *artist)
386
{
387
	return artist_new(artist->name, artist->sort_name, artist->is_compilation);
388
}
389
390
static void artist_free(struct artist *artist)
391
{
392
	free(artist->name);
393
	free(artist->sort_name);
394
	free(artist->auto_sort_name);
395
	free(artist->collkey_name);
396
	free(artist->collkey_sort_name);
397
	free(artist->collkey_auto_sort_name);
398
	free(artist);
399
}
400
401
static struct album *album_new(struct artist *artist, const char *name,
402
		const char *sort_name, int date)
403
{
404
	struct album *album = xnew(struct album, 1);
405
406
	album->name = xstrdup(name);
407
	album->sort_name = sort_name ? xstrdup(sort_name) : NULL;
408
	album->collkey_name = u_strcasecoll_key(name);
409
	album->collkey_sort_name = u_strcasecoll_key0(sort_name);
410
	album->date = date;
411
	rb_root_init(&album->track_root);
412
	album->artist = artist;
413
414
	return album;
415
}
416
417
static void album_free(struct album *album)
418
{
419
	free(album->name);
420
	free(album->sort_name);
421
	free(album->collkey_name);
422
	free(album->collkey_sort_name);
423
	free(album);
424
}
425
426
void tree_init(void)
427
{
428
	struct iter iter;
429
430
	rb_root_init(&lib_artist_root);
431
432
	lib_tree_win = window_new(tree_get_prev, tree_get_next);
433
	lib_track_win = window_new(tree_track_get_prev, tree_track_get_next);
434
	lib_cur_win = lib_tree_win;
435
436
	lib_tree_win->sel_changed = tree_sel_changed;
437
438
	window_set_empty(lib_track_win);
439
	window_set_contents(lib_tree_win, &lib_artist_root);
440
441
	iter.data0 = &lib_artist_root;
442
	iter.data1 = NULL;
443
	iter.data2 = NULL;
444
	tree_searchable = searchable_new(NULL, &iter, &tree_search_ops);
445
}
446
447
struct tree_track *tree_get_selected(void)
448
{
449
	struct artist *artist;
450
	struct album *album;
451
	struct tree_track *track;
452
	struct iter sel;
453
454
	if (rb_root_empty(&lib_artist_root))
455
		return NULL;
456
457
	tree_win_get_selected(&artist, &album);
458
	if (album == NULL) {
459
		/* only artist selected, track window is empty
460
		 * => get first album of the selected artist and first track of that album
461
		 */
462
		album = to_album(rb_first(&artist->album_root));
463
		track = to_tree_track(rb_first(&album->track_root));
464
	} else {
465
		window_get_sel(lib_track_win, &sel);
466
		track = iter_to_tree_track(&sel);
467
	}
468
469
	return track;
470
}
471
472
struct track_info *tree_set_selected(void)
473
{
474
	struct track_info *info;
475
476
	lib_cur_track = tree_get_selected();
477
	if (!lib_cur_track)
478
		return NULL;
479
480
	lib_tree_win->changed = 1;
481
	lib_track_win->changed = 1;
482
483
	info = tree_track_info(lib_cur_track);
484
	track_info_ref(info);
485
	return info;
486
}
487
488
static int special_name_cmp(const char *a, const char *collkey_a,
489
		               const char *b, const char *collkey_b)
490
{
491
	/* keep <Stream> etc. top */
492
	int cmp = (*a != '<') - (*b != '<');
493
494
	if (cmp)
495
		return cmp;
496
	return strcmp(collkey_a, collkey_b);
497
}
498
499
static inline const char *album_sort_collkey(const struct album *a)
500
{
501
        if (a->sort_name)
502
                return a->collkey_sort_name;
503
504
        return a->collkey_name;
505
}
506
507
static int special_album_cmp(const struct album *a, const struct album *b)
508
{
509
	return special_name_cmp(a->name, album_sort_collkey(a), b->name, album_sort_collkey(b));
510
}
511
512
static int special_album_cmp_date(const struct album *a, const struct album *b)
513
{
514
	/* keep <Stream> etc. top */
515
	int cmp = (*a->name != '<') - (*b->name != '<');
516
	if (cmp)
517
		return cmp;
518
519
	cmp = a->date - b->date;
520
	if (cmp)
521
		return cmp;
522
523
	return strcmp(album_sort_collkey(a), album_sort_collkey(b));
524
}
525
526
/* has to follow the same logic as artist_sort_name() */
527
static inline const char *artist_sort_collkey(const struct artist *a)
528
{
529
        if (a->sort_name)
530
                return a->collkey_sort_name;
531
532
        if (smart_artist_sort && a->auto_sort_name)
533
                return a->collkey_auto_sort_name;
534
535
        return a->collkey_name;
536
}
537
538
static struct artist *do_find_artist(const struct artist *artist,
539
		                     struct rb_root *root,
540
				     struct rb_node ***p_new,
541
				     struct rb_node **p_parent)
542
{
543
	struct rb_node **new = &(root->rb_node), *parent = NULL;
544
	const char *a = artist_sort_name(artist);
545
	const char *collkey_a = artist_sort_collkey(artist);
546
547
	while (*new) {
548
		struct artist *cur_artist = to_artist(*new);
549
		const char *b = artist_sort_name(cur_artist);
550
		const char *collkey_b = artist_sort_collkey(cur_artist);
551
		int result = special_name_cmp(a, collkey_a, b, collkey_b);
552
553
		parent = *new;
554
		if (result < 0)
555
			new = &((*new)->rb_left);
556
		else if (result > 0)
557
			new = &((*new)->rb_right);
558
		else
559
			return cur_artist;
560
	}
561
	if (p_new)
562
		*p_new = new;
563
	if (p_parent)
564
		*p_parent = parent;
565
	return NULL;
566
}
567
568
/* search (tree) {{{ */
569
static struct artist *collapse_artist;
570
571
static int tree_search_matches(void *data, struct iter *iter, const char *text)
572
{
573
	struct tree_track *track;
574
	struct iter tmpiter;
575
	unsigned int flags = TI_MATCH_ARTIST | TI_MATCH_ALBUM | TI_MATCH_ALBUMARTIST;
576
577
	if (!search_restricted)
578
		flags |= TI_MATCH_TITLE;
579
	track = iter_to_tree_search_track(iter);
580
	if (!track_info_matches(tree_track_info(track), text, flags))
581
		return 0;
582
583
	/* collapse old search result */
584
	if (collapse_artist) {
585
		struct artist *artist = do_find_artist(collapse_artist, &lib_artist_root, NULL, NULL);
586
		if (artist && artist != track->album->artist) {
587
			if (artist->expanded)
588
				tree_set_expand_artist(artist, 0);
589
			artist_free(collapse_artist);
590
			collapse_artist = (!track->album->artist->expanded) ? artist_copy(track->album->artist) : NULL;
591
		}
592
	} else if (!track->album->artist->expanded)
593
		collapse_artist = artist_copy(track->album->artist);
594
595
	track->album->artist->expanded = 1;
596
	album_to_iter(track->album, &tmpiter);
597
	window_set_sel(lib_tree_win, &tmpiter);
598
599
	tree_track_to_iter(track, &tmpiter);
600
	window_set_sel(lib_track_win, &tmpiter);
601
	return 1;
602
}
603
/* search (tree) }}} */
604
605
static void insert_artist(struct artist *artist, struct rb_root *root)
606
{
607
	struct rb_node **new = &(root->rb_node), *parent = NULL;
608
	struct artist *found;
609
610
	found = do_find_artist(artist, root, &new, &parent);
611
	if (!found) {
612
		rb_link_node(&artist->tree_node, parent, new);
613
		rb_insert_color(&artist->tree_node, root);
614
	}
615
}
616
617
static void add_artist(struct artist *artist)
618
{
619
	insert_artist(artist, &lib_artist_root);
620
}
621
622
static struct artist *find_artist(const struct artist *artist)
623
{
624
	return do_find_artist(artist, &lib_artist_root, NULL, NULL);
625
}
626
627
static struct album *do_find_album(const struct album *album,
628
				   int (*cmp)(const struct album *, const struct album *),
629
				   struct rb_node ***p_new,
630
				   struct rb_node **p_parent)
631
{
632
	struct rb_node **new = &(album->artist->album_root.rb_node), *parent = NULL;
633
634
	while (*new) {
635
		struct album *a = to_album(*new);
636
637
		int result = cmp(album, a);
638
639
		parent = *new;
640
		if (result < 0)
641
			new = &((*new)->rb_left);
642
		else if (result > 0)
643
			new = &((*new)->rb_right);
644
		else
645
			return a;
646
	}
647
	if (p_new)
648
		*p_new = new;
649
	if (p_parent)
650
		*p_parent = parent;
651
	return NULL;
652
}
653
654
static struct album *find_album(const struct album *album)
655
{
656
	struct album *a;
657
	struct rb_node *tmp;
658
659
	/* do a linear search because we want find albums with different date */
660
	rb_for_each_entry(a, tmp, &album->artist->album_root, tree_node) {
661
		if (special_album_cmp(album, a) == 0)
662
			return a;
663
	}
664
	return NULL;
665
}
666
667
static void add_album(struct album *album)
668
{
669
	struct rb_node **new = &(album->artist->album_root.rb_node), *parent = NULL;
670
	struct album *found;
671
672
	/*
673
	 * Sort regular albums by date, but sort compilations
674
	 * alphabetically.
675
	 */
676
	found = do_find_album(album,
677
			      album->artist->is_compilation ? special_album_cmp
678
							    : special_album_cmp_date,
679
			      &new, &parent);
680
	if (!found) {
681
		rb_link_node(&album->tree_node, parent, new);
682
		rb_insert_color(&album->tree_node, &album->artist->album_root);
683
	}
684
}
685
686
static void album_add_track(struct album *album, struct tree_track *track)
687
{
688
	/*
689
	 * NOTE: This is not perfect.  You should ignore track numbers if
690
	 *       either is unset and use filename instead, but usually you
691
	 *       have all track numbers set or all unset (within one album
692
	 *       of course).
693
	 */
694
	static const sort_key_t album_track_sort_keys[] = {
695
		SORT_DISCNUMBER, SORT_TRACKNUMBER, SORT_FILENAME, SORT_INVALID
696
	};
697
	struct rb_node **new = &(album->track_root.rb_node), *parent = NULL;
698
699
	track->album = album;
700
	while (*new) {
701
		const struct simple_track *a = (const struct simple_track *) track;
702
		const struct simple_track *b = (const struct simple_track *) to_tree_track(*new);
703
		int result = track_info_cmp(a->info, b->info, album_track_sort_keys);
704
705
		parent = *new;
706
		if (result < 0)
707
			new = &((*new)->rb_left);
708
		else if (result > 0)
709
			new = &((*new)->rb_right);
710
		else
711
			/* only add to tree if not there already */
712
			return;
713
	}
714
715
	rb_link_node(&track->tree_node, parent, new);
716
	rb_insert_color(&track->tree_node, &album->track_root);
717
}
718
719
static const char *tree_artist_name(const struct track_info* ti)
720
{
721
	const char *val = ti->albumartist;
722
723
	if (ti->is_va_compilation)
724
		val = "<Various Artists>";
725
	if (!val || strcmp(val, "") == 0)
726
		val = "<No Name>";
727
728
	return val;
729
}
730
731
static const char *tree_album_name(const struct track_info* ti)
732
{
733
	const char *val = ti->album;
734
735
	if (!val || strcmp(val, "") == 0)
736
		val = "<No Name>";
737
738
	return val;
739
}
740
741
static void remove_album(struct album *album)
742
{
743
	if (album->artist->expanded) {
744
		struct iter iter;
745
746
		album_to_iter(album, &iter);
747
		window_row_vanishes(lib_tree_win, &iter);
748
	}
749
	rb_erase(&album->tree_node, &album->artist->album_root);
750
}
751
752
static void remove_artist(struct artist *artist)
753
{
754
	struct iter iter;
755
756
	artist_to_iter(artist, &iter);
757
	window_row_vanishes(lib_tree_win, &iter);
758
	rb_erase(&artist->tree_node, &lib_artist_root);
759
}
760
761
void tree_add_track(struct tree_track *track)
762
{
763
	const struct track_info *ti = tree_track_info(track);
764
	const char *album_name, *artist_name, *artistsort_name = NULL;
765
	const char *albumsort_name = NULL;
766
	struct artist *artist, *new_artist;
767
	struct album *album, *new_album;
768
	int date;
769
	int is_va_compilation = 0;
770
771
	date = ti->originaldate;
772
	if (date < 0)
773
		date = ti->date;
774
775
	if (is_http_url(ti->filename)) {
776
		artist_name = "<Stream>";
777
		album_name = "<Stream>";
778
	} else {
779
		album_name	= tree_album_name(ti);
780
		artist_name	= tree_artist_name(ti);
781
		artistsort_name	= ti->artistsort;
782
		albumsort_name	= ti->albumsort;
783
784
		is_va_compilation = ti->is_va_compilation;
785
	}
786
787
	new_artist = artist_new(artist_name, artistsort_name, is_va_compilation);
788
	album = NULL;
789
790
	artist = find_artist(new_artist);
791
	if (artist) {
792
		artist_free(new_artist);
793
		new_album = album_new(artist, album_name, albumsort_name, date);
794
		album = find_album(new_album);
795
		if (album)
796
			album_free(new_album);
797
	} else
798
		new_album = album_new(new_artist, album_name, albumsort_name, date);
799
800
	if (artist) {
801
		int changed = 0;
802
		/* If it makes sense to update sort_name, do it */
803
		if (!artist->sort_name && artistsort_name) {
804
			artist->sort_name = xstrdup(artistsort_name);
805
			artist->collkey_sort_name = u_strcasecoll_key(artistsort_name);
806
			changed = 1;
807
		}
808
		/* If names differ, update */
809
		if (!artist->auto_sort_name) {
810
			char *auto_sort_name = auto_artist_sort_name(artist_name);
811
			if (auto_sort_name) {
812
				free(artist->name);
813
				free(artist->collkey_name);
814
				artist->name = xstrdup(artist_name);
815
				artist->collkey_name = u_strcasecoll_key(artist_name);
816
				artist->auto_sort_name = auto_sort_name;
817
				artist->collkey_auto_sort_name = u_strcasecoll_key(auto_sort_name);
818
				changed = 1;
819
			}
820
		}
821
		if (changed) {
822
			remove_artist(artist);
823
			add_artist(artist);
824
			window_changed(lib_tree_win);
825
		}
826
	}
827
828
	if (album) {
829
		album_add_track(album, track);
830
831
		/* If it makes sense to update album date, do it */
832
		if (album->date < date) {
833
			album->date = date;
834
835
			remove_album(album);
836
			add_album(album);
837
			if (artist->expanded)
838
				window_changed(lib_tree_win);
839
		}
840
841
		if (album_selected(album))
842
			window_changed(lib_track_win);
843
	} else if (artist) {
844
		add_album(new_album);
845
		album_add_track(new_album, track);
846
847
		if (artist->expanded)
848
			window_changed(lib_tree_win);
849
	} else {
850
		add_artist(new_artist);
851
		add_album(new_album);
852
		album_add_track(new_album, track);
853
854
		window_changed(lib_tree_win);
855
	}
856
}
857
858
static void remove_sel_artist(struct artist *artist)
859
{
860
	struct rb_node *a_node, *a_tmp;
861
862
	rb_for_each_safe(a_node, a_tmp, &artist->album_root) {
863
		struct rb_node *t_node, *t_tmp;
864
		struct album *album = to_album(a_node);
865
866
		rb_for_each_safe(t_node, t_tmp, &album->track_root) {
867
			struct tree_track *track = to_tree_track(t_node);
868
869
			editable_remove_track(&lib_editable, (struct simple_track *)track);
870
		}
871
		/* all tracks removed => album removed
872
		 * if the last album was removed then the artist was removed too
873
		 */
874
	}
875
}
876
877
static void remove_sel_album(struct album *album)
878
{
879
	struct rb_node *node, *tmp;
880
881
	rb_for_each_safe(node, tmp, &album->track_root) {
882
		struct tree_track *track = to_tree_track(node);
883
884
		editable_remove_track(&lib_editable, (struct simple_track *)track);
885
	}
886
}
887
888
static void tree_win_remove_sel(void)
889
{
890
	struct artist *artist;
891
	struct album *album;
892
893
	tree_win_get_selected(&artist, &album);
894
	if (album) {
895
		remove_sel_album(album);
896
	} else if (artist) {
897
		remove_sel_artist(artist);
898
	}
899
}
900
901
static void track_win_remove_sel(void)
902
{
903
	struct iter sel;
904
	struct tree_track *track;
905
906
	if (window_get_sel(lib_track_win, &sel)) {
907
		track = iter_to_tree_track(&sel);
908
		BUG_ON(track == NULL);
909
		editable_remove_track(&lib_editable, (struct simple_track *)track);
910
	}
911
}
912
913
void tree_toggle_active_window(void)
914
{
915
	if (lib_cur_win == lib_tree_win) {
916
		struct artist *artist;
917
		struct album *album;
918
919
		tree_win_get_selected(&artist, &album);
920
		if (album) {
921
			lib_cur_win = lib_track_win;
922
			lib_tree_win->changed = 1;
923
			lib_track_win->changed = 1;
924
		}
925
	} else if (lib_cur_win == lib_track_win) {
926
		lib_cur_win = lib_tree_win;
927
		lib_tree_win->changed = 1;
928
		lib_track_win->changed = 1;
929
	}
930
}
931
932
void tree_toggle_expand_artist(void)
933
{
934
	struct iter sel;
935
	struct artist *artist;
936
937
	window_get_sel(lib_tree_win, &sel);
938
	artist = iter_to_artist(&sel);
939
	if (artist)
940
		tree_set_expand_artist(artist, !artist->expanded);
941
}
942
943
void tree_expand_matching(const char *text)
944
{
945
	struct artist *artist;
946
	struct rb_node *tmp1;
947
	int have_track_selected = 0;
948
949
	rb_for_each_entry(artist, tmp1, &lib_artist_root, tree_node) {
950
		struct album *album = NULL;
951
		struct rb_node *tmp2;
952
		int album_matched = 0;
953
954
		rb_for_each_entry(album, tmp2, &artist->album_root, tree_node) {
955
			struct tree_track *tree_track = to_tree_track(rb_first(&album->track_root));
956
			struct track_info *ti = ((struct simple_track *) tree_track)->info;
957
			album_matched = track_info_matches_full(ti, text, TI_MATCH_ALBUM, TI_MATCH_ARTIST | TI_MATCH_ALBUMARTIST, 0);
958
			if (album_matched)
959
				break;
960
		}
961
		artist->expanded = album_matched;
962
		if (!have_track_selected) {
963
			struct tree_track *tree_track;
964
			int track_matched = 0;
965
966
			if (!album)
967
				album = to_album(rb_first(&artist->album_root));
968
969
			rb_for_each_entry(tree_track, tmp2, &album->track_root, tree_node) {
970
				struct track_info *ti = ((struct simple_track *) tree_track)->info;
971
				track_matched = track_info_matches_full(ti, text, TI_MATCH_TITLE, 0, 0);
972
				if (track_matched)
973
					break;
974
			}
975
			if (album_matched || track_matched) {
976
				if (!tree_track)
977
					tree_track = to_tree_track(rb_first(&album->track_root));
978
				tree_sel_track(tree_track);
979
				have_track_selected = 1;
980
			}
981
		}
982
	}
983
	window_changed(lib_tree_win);
984
}
985
986
void tree_expand_all(void)
987
{
988
	struct artist *artist;
989
	struct rb_node *tmp;
990
991
	rb_for_each_entry(artist, tmp, &lib_artist_root, tree_node) {
992
		artist->expanded = 1;
993
	}
994
	window_changed(lib_tree_win);
995
}
996
997
static void remove_track(struct tree_track *track)
998
{
999
	if (album_selected(track->album)) {
1000
		struct iter iter;
1001
1002
		tree_track_to_iter(track, &iter);
1003
		window_row_vanishes(lib_track_win, &iter);
1004
	}
1005
	rb_erase(&track->tree_node, &track->album->track_root);
1006
}
1007
1008
void tree_remove(struct tree_track *track)
1009
{
1010
	struct album *album = track->album;
1011
	struct artist *sel_artist;
1012
	struct album *sel_album;
1013
1014
	tree_win_get_selected(&sel_artist, &sel_album);
1015
1016
	remove_track(track);
1017
	/* don't free the track */
1018
1019
	if (rb_root_empty(&album->track_root)) {
1020
		struct artist *artist = album->artist;
1021
1022
		if (sel_album == album)
1023
			lib_cur_win = lib_tree_win;
1024
1025
		remove_album(album);
1026
		album_free(album);
1027
1028
		if (rb_root_empty(&artist->album_root)) {
1029
			artist->expanded = 0;
1030
			remove_artist(artist);
1031
			artist_free(artist);
1032
		}
1033
	}
1034
}
1035
1036
void tree_remove_sel(void)
1037
{
1038
	if (lib_cur_win == lib_tree_win) {
1039
		tree_win_remove_sel();
1040
	} else {
1041
		track_win_remove_sel();
1042
	}
1043
}
1044
1045
void tree_sort_artists(void)
1046
{
1047
	struct rb_node *a_node, *a_tmp;
1048
1049
	rb_for_each_safe(a_node, a_tmp, &lib_artist_root) {
1050
		struct rb_node *l_node, *l_tmp;
1051
		struct artist *artist = to_artist(a_node);
1052
1053
		rb_for_each_safe(l_node, l_tmp, &artist->album_root) {
1054
			struct rb_node *t_node, *t_tmp;
1055
			struct album *album = to_album(l_node);
1056
1057
			rb_for_each_safe(t_node, t_tmp, &album->track_root) {
1058
				struct tree_track *track = to_tree_track(t_node);
1059
1060
				tree_remove(track);
1061
				tree_add_track(track);
1062
			}
1063
		}
1064
	}
1065
}
1066
1067
void tree_sel_current(void)
1068
{
1069
	tree_sel_track(lib_cur_track);
1070
}
1071
1072
void tree_sel_first(void)
1073
{
1074
	if (!rb_root_empty(&lib_artist_root)) {
1075
		struct artist *artist = to_artist(rb_first(&lib_artist_root));
1076
		struct album *album = to_album(rb_first(&artist->album_root));
1077
		struct tree_track *tree_track = to_tree_track(rb_first(&album->track_root));
1078
		tree_sel_track(tree_track);
1079
	}
1080
}
1081
1082
void tree_sel_track(struct tree_track *t)
1083
{
1084
	if (t) {
1085
		struct iter iter;
1086
1087
		t->album->artist->expanded = 1;
1088
1089
		if (lib_cur_win == lib_tree_win) {
1090
			lib_cur_win = lib_track_win;
1091
			lib_tree_win->changed = 1;
1092
			lib_track_win->changed = 1;
1093
		}
1094
1095
		album_to_iter(t->album, &iter);
1096
		window_set_sel(lib_tree_win, &iter);
1097
1098
		tree_track_to_iter(t, &iter);
1099
		window_set_sel(lib_track_win, &iter);
1100
	}
1101
}
1102
1103
static int album_for_each_track(struct album *album, int (*cb)(void *data, struct track_info *ti),
1104
		void *data, int reverse)
1105
{
1106
	struct tree_track *track;
1107
	struct rb_node *tmp;
1108
	int rc = 0;
1109
1110
	if (reverse) {
1111
		rb_for_each_entry_reverse(track, tmp, &album->track_root, tree_node) {
1112
			rc = cb(data, tree_track_info(track));
1113
			if (rc)
1114
				break;
1115
		}
1116
	} else {
1117
		rb_for_each_entry(track, tmp, &album->track_root, tree_node) {
1118
			rc = cb(data, tree_track_info(track));
1119
			if (rc)
1120
				break;
1121
		}
1122
	}
1123
	return rc;
1124
}
1125
1126
static int artist_for_each_track(struct artist *artist, int (*cb)(void *data, struct track_info *ti),
1127
		void *data, int reverse)
1128
{
1129
	struct album *album;
1130
	struct rb_node *tmp;
1131
	int rc = 0;
1132
1133
	if (reverse) {
1134
		rb_for_each_entry_reverse(album, tmp, &artist->album_root, tree_node) {
1135
			rc = album_for_each_track(album, cb, data, 1);
1136
			if (rc)
1137
				break;
1138
		}
1139
	} else {
1140
		rb_for_each_entry(album, tmp, &artist->album_root, tree_node) {
1141
			rc = album_for_each_track(album, cb, data, 0);
1142
			if (rc)
1143
				break;
1144
		}
1145
	}
1146
	return rc;
1147
}
1148
1149
int __tree_for_each_sel(int (*cb)(void *data, struct track_info *ti), void *data, int reverse)
1150
{
1151
	int rc = 0;
1152
1153
	if (lib_cur_win == lib_tree_win) {
1154
		struct artist *artist;
1155
		struct album *album;
1156
1157
		tree_win_get_selected(&artist, &album);
1158
		if (artist) {
1159
			if (album == NULL) {
1160
				rc = artist_for_each_track(artist, cb, data, reverse);
1161
			} else {
1162
				rc = album_for_each_track(album, cb, data, reverse);
1163
			}
1164
		}
1165
	} else {
1166
		struct iter sel;
1167
		struct tree_track *track;
1168
1169
		if (window_get_sel(lib_track_win, &sel)) {
1170
			track = iter_to_tree_track(&sel);
1171
			rc = cb(data, tree_track_info(track));
1172
		}
1173
	}
1174
	return rc;
1175
}
1176
1177
int tree_for_each_sel(int (*cb)(void *data, struct track_info *ti), void *data, int reverse)
1178
{
1179
	int rc = __tree_for_each_sel(cb, data, reverse);
1180
1181
	window_down(lib_cur_win, 1);
1182
	return rc;
1183
}