summaryrefslogtreecommitdiff
path: root/music.c
blob: 09ee7d89227ae932d725c72da0ccb4b5fc5ec89b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "music.h"

#include <glib/gstdio.h>

struct directory *music_root = NULL;

gboolean music_init(const gchar *path) {
	music_root = g_new0(struct directory, 1);
	music_root->path = g_strdup(path);

	g_debug("added music root %s", path);

	return 1;
}

gboolean music_scan(struct directory *directory) {
	GError *error = NULL;
	GDir *dir = g_dir_open(directory->path, 0, &error);

	if(dir == NULL) {
		g_error("%s", error->message);
		g_error_free(error);
		return 0;
	}

	const gchar *entry;
	while((entry = g_dir_read_name(dir)) != NULL) {
		struct stat st;
		gchar *fullpath = g_build_filename(directory->path, entry, NULL);
		if(fullpath == NULL) {
			g_error("g_build_filename returned NULL");
		}

		if(g_stat(fullpath, &st) < 0) {
			g_warning("g_stat failed on %s", fullpath);
		}

		if(S_ISREG(st.st_mode)) {
			struct file *f = g_new0(struct file, 1);
			f->name = g_strdup(entry);

			if(directory->files == NULL) {
				directory->files = f;
			} else {
				struct file *last = directory->files;
				while(last->next) last = last->next;
				last->next = f;
			}

			g_debug("added file %s to %s", entry, directory->path);
		} else if(S_ISDIR(st.st_mode)) {
			struct directory *d = g_new0(struct directory, 1);
			d->path = g_build_filename(directory->path, entry, NULL);

			if(directory->sub == NULL) {
				directory->sub = d;
			} else {
				struct directory *last = directory->sub;
				while(last->next) last = last->next;
				last->next = d;
			}

			g_debug("added subdir %s to %s", entry, directory->path);

			g_debug("recursing into %s", entry);
			music_scan(d);
		}
	}

	g_dir_close(dir);

	return 1;
}

gboolean music_scan_root() {
	g_assert(music_root != NULL);

	return music_scan(music_root);
}

static struct directory *music_find_dir_rec(struct directory *root, const gchar *path) {
	if(g_strcmp0(root->path, path) == 0)
		return root;

	/* TODO: implement this */
	g_error("not implemented");

	return NULL;
}

struct directory *music_find_dir(const gchar *path) {
	return music_find_dir_rec(music_root, path);
}

static void music_do_free(struct directory *root) {
	struct directory *node;

	g_assert(root != NULL);

	for(node = root->sub; node; node = node->next) {
		music_do_free(node);
	}

	for(node = root->next; node; node = node->next) {
		music_do_free(node);
	}

	for(struct file *f = root->files; f; f = f->next) {
		g_free(f->name);
		g_free(f);
	}

	g_free(root->path);
	g_free(root);
}

void music_free() {
	g_assert(music_root != NULL);

	music_do_free(music_root);
	music_root = NULL;
}