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