1 /*
2  *  Copyright (C) 2009-2012  Christian Heckendorf <heckendorfc@gmail.com>
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "tree.h"
19 #include "defs.h"
20 #include "dbact.h"
21 
dbnodeAdd(struct dbnode * node)22 struct dbnode *dbnodeAdd(struct dbnode *node){
23 	struct dbnode *new;
24 	if(!(new=malloc(sizeof(struct dbnode)))){
25 		debug(2,"Malloc failed (dbnode).");
26 		return NULL;
27 	}
28 	dbiInit(&new->dbi);
29 	new->prev=node;
30 	if(node){
31 		if(node->next){
32 			new->next=node->next;
33 			node->next=new;
34 		}
35 		new->depth=node->depth+1;
36 	}
37 	else{
38 		new->next=NULL;
39 		new->depth=0;
40 	}
41 
42 	return new;
43 }
44 
dbnodeClean(struct dbnode * node)45 struct dbnode *dbnodeClean(struct dbnode *node){
46 	struct dbnode *ret=node->prev;
47 	dbiClean(&node->dbi);
48 
49 //	if(node->next)
50 //		node->next->prev=node->prev;
51 
52 	if(node->prev)
53 		node->prev->next=node->next;
54 
55 	free(node);
56 	return ret;
57 }
58 
59 // head -> parent -> ... -> 0
getGenreHeadPath(int head)60 int *getGenreHeadPath(int head){
61 	int x=0;
62 	int *path;
63 	if(!(path=malloc(sizeof(int)*2))){
64 		debug(2,"Malloc failed (path).");
65 		return NULL;
66 	}
67 	char query[100],*qptr;
68 	struct dbitem dbi;
69 	dbiInit(&dbi);
70 
71 	sprintf(query,"SELECT ParentID FROM Category WHERE CategoryID=%d",head);
72 	qptr=&query[47];
73 
74 	path[0]=head;
75 	while(doQuery(query,&dbi)>0 && fetch_row(&dbi)){
76 		if(!(path=realloc(path,sizeof(int)*((++x)*2)))){
77 			debug(2,"Realloc failed (path).");
78 			dbiClean(&dbi);
79 			return NULL;
80 		}
81 		path[x]=(int)strtol(dbi.row[0],NULL,10);
82 		path[x+1]=0;
83 		sprintf(qptr,"%d",path[x]);
84 	}
85 	dbiClean(&dbi);
86 	return path;
87 }
88 
printGenreHeadPath(int * path)89 void printGenreHeadPath(int *path){
90 	int x;
91 	char query[100],*qptr;
92 	struct dbitem dbi;
93 	dbiInit(&dbi);
94 
95 	sprintf(query,"SELECT Name FROM Category WHERE CategoryID=");
96 	qptr=&query[43];
97 	for(x=0;path[x];x++);
98 	for(x--;x>=0;x--){
99 		sprintf(qptr,"%d",path[x]);
100 		if(doQuery(query,&dbi) && fetch_row(&dbi))
101 			printf("%s -> ",dbi.row[0]);
102 	}
103 	dbiClean(&dbi);
104 }
105 
printGenreChildren(struct dbnode * cur,int curid,void * action (struct dbnode *))106 void printGenreChildren(struct dbnode *cur, int curid, void *action(struct dbnode*)){
107 	if(!cur)return;
108 
109 	char query[100];
110 	sprintf(query,"SELECT CategoryID,Name FROM Category WHERE CategoryID=%d",curid);
111 	if(doQuery(query,&cur->dbi) && fetch_row(&cur->dbi))
112 		action(cur); // Do self
113 
114 	sprintf(query,"SELECT CategoryID FROM Category WHERE ParentID=%d",curid);
115 	doQuery(query,&cur->dbi);
116 
117 	int nextid;
118 	struct dbnode *child;
119 	while(fetch_row(&cur->dbi)){
120 		if(!(child=dbnodeAdd(cur)))return;
121 		nextid=(int)strtol(cur->dbi.row[0],NULL,10);
122 		if(nextid)
123 			printGenreChildren(child,nextid,action);
124 		else
125 			dbnodeClean(child);
126 	}
127 	dbnodeClean(cur);
128 }
129 
tierChildPrint(struct dbnode * cur)130 void tierChildPrint(struct dbnode *cur){
131 	int x;
132 	if(!cur->dbi.row_count)return;
133 	if(cur->depth>0){
134 		char *prefix;
135 		if(!(prefix=malloc(sizeof(char)*((cur->depth*2)+1)))){
136 			debug(2,"Malloc failed (prefix).");
137 			return;
138 		}
139 		for(x=0;x<cur->depth;x++)sprintf(prefix+x,"\t");
140 		printf("\n%s[%s] %s\n%s- - - - - - -\n",prefix,cur->dbi.row[0],cur->dbi.row[1],prefix);
141 		free(prefix);
142 	}
143 	else
144 		printf("\n[%s] %s\n- - - - - - -\n",cur->dbi.row[0],cur->dbi.row[1]);
145 
146 	char query[200];
147 	sprintf(query,"SELECT SongID,SongTitle,AlbumTitle,ArtistName FROM SongCategory NATURAL JOIN SongPubInfo WHERE CategoryID=%s ORDER BY ArtistName,AlbumTitle",cur->dbi.row[0]);
148 	doTitleQuery(query,NULL,listconf.maxwidth);
149 }
150 
tierCatPrint(struct dbnode * cur)151 void tierCatPrint(struct dbnode *cur){
152 	int x;
153 	if(!cur->dbi.row_count)return;
154 	if(cur->depth>0){
155 		char *prefix;
156 		if(!(prefix=malloc(sizeof(char)*((cur->depth*2)+1)))){
157 			debug(2,"Malloc failed (prefix).");
158 			return;
159 		}
160 		for(x=0;x<cur->depth;x++)sprintf(prefix+x,"\t");
161 		printf("%s[%s] %s\n",prefix,cur->dbi.row[0],cur->dbi.row[1]);
162 		free(prefix);
163 	}
164 	else
165 		printf("[%s] %s\n",cur->dbi.row[0],cur->dbi.row[1]);
166 }
167 
printGenreTree(int head,void * action (struct dbnode *))168 void printGenreTree(int head, void *action(struct dbnode *)){
169 	int x,depth,*headpath;
170 	struct dbitem dbi;
171 	dbiInit(&dbi);
172 
173 	if(!(headpath=getGenreHeadPath(head))){
174 		fprintf(stderr,"Error in getGenreHeadPath");
175 		return;
176 	}
177 
178 	for(x=0;headpath[x];x++);
179 	depth=x-1;
180 	printGenreHeadPath(headpath);
181 	if(headpath[0])printf("\n");
182 	free(headpath);
183 
184 	struct dbnode *cur;
185 	if(!(cur=dbnodeAdd(NULL)))return;
186 	cur->depth=depth;
187 	printGenreChildren(cur,head,action);
188 	printf("\n");
189 }
190 
191