1 /*
2 * Copyright (C) 2014-2015 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 "edit_shell.h"
19 #include "dbact.h"
20 #include "insert.h"
21
22 int yyparse();
23 TokenList *tlist;
24 extern commandline_t *fullcmd;
25 typedef int(*seltypefun)(commandline_t*);
26 typedef int(*acttypefun)(command_t*,command_t*);
27
28 static char *seltypes[]={
29 "song",
30 "album",
31 "artist",
32 "playlist",
33 "tag",
34 NULL
35 };
printEditSelect(int id,int type)36 void printEditSelect(int id, int type){
37 char query[100];
38 fprintf(stderr,"type: %d %s\n",type,seltypes[type]);
39 sprintf(query,"select SelectID from TempSelect where TempID=%d",id);
40 doTitleQuery(query,NULL,20);
41 }
42
43 struct selgroup{
44 acttypefun func;
45 char *name;
46 };
47
runGenericEditAction(commandline_t * cmd,struct selgroup * selactlist)48 static int runGenericEditAction(commandline_t *cmd,struct selgroup *selactlist){
49 int i;
50 command_t *act;
51
52 for(act=cmd->actions;act;act=act->next){
53 for(i=0;selactlist[i].name;i++){
54 if(strcmp(selactlist[i].name,act->cmd->word)==0){
55 selactlist[i].func(cmd->selector,act);
56 break;
57 }
58 }
59 }
60
61 return HARP_RET_ERR;
62 }
63
listSongs(command_t * sel,command_t * act)64 static int listSongs(command_t *sel, command_t *act){
65 char query[300];
66 int exception[10];
67 int i;
68
69 for(i=0;i<10;i++)exception[i]=i<5?1:listconf.exception;
70 sprintf(query,"SELECT SongID, SongTitle, SongTrack, Location, AlbumTitle AS Album, ArtistName AS Artist FROM SongPubInfo WHERE SongID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
71 doTitleQuery(query,exception,listconf.maxwidth);
72
73 return HARP_RET_OK;
74 }
75
editSongTitle(command_t * sel,command_t * act)76 static int editSongTitle(command_t *sel, command_t *act){
77 char query[300];
78
79 sprintf(query,"UPDATE Song SET Title='%s' WHERE SongID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->words->word,sel->tlid);
80 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
81
82 return HARP_RET_OK;
83 }
84
deleteSong(command_t * sel,command_t * act)85 static int deleteSong(command_t *sel, command_t *act){
86 char query[300];
87
88 sprintf(query,"DELETE FROM Song WHERE SongID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
89 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
90
91 return HARP_RET_OK;
92 }
93
editSongAlbumArtist(command_t * sel,command_t * act)94 static int editSongAlbumArtist(command_t *sel, command_t *act){
95 char query[300];
96 int artistid,albumid;
97 struct dbitem dbi;
98 dbiInit(&dbi);
99
100 if(act->args->next==NULL){
101 fprintf(stderr,"albumartist: Two arguments required for this action.\n");
102 return HARP_RET_ERR;
103 }
104
105 if(act->args->next->words->flag==WORD_DEFAULT)
106 artistid=strtol(act->args->next->words->word,NULL,10);
107 else
108 artistid=getArtist(act->args->next->words->word);
109
110 if(act->args->words->flag==WORD_DEFAULT)
111 albumid=strtol(act->args->words->word,NULL,10);
112 else
113 albumid=getAlbum(act->args->words->word,artistid);
114
115 sprintf(query,"UPDATE Song SET AlbumID=%d WHERE SongID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",albumid,sel->tlid);
116 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
117
118 return HARP_RET_OK;
119 }
120
songActivation(command_t * sel,command_t * act)121 static int songActivation(command_t *sel, command_t *act){
122 char query[300];
123
124 /*TODO: test argument to disable toggle */
125 sprintf(query,"UPDATE Song SET Active=NOT(Active) WHERE SongID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
126 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
127
128 return HARP_RET_OK;
129 }
130
editSongLocation(command_t * sel,command_t * act)131 static int editSongLocation(command_t *sel, command_t *act){
132 char query[300];
133
134 sprintf(query,"UPDATE Song SET Location='%s' WHERE SongID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->words->word,sel->tlid);
135 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
136
137 return HARP_RET_OK;
138 }
139
editSongTrack(command_t * sel,command_t * act)140 static int editSongTrack(command_t *sel, command_t *act){
141 char query[300];
142
143 sprintf(query,"UPDATE Song SET Track=%s WHERE SongID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->words->word,sel->tlid);
144 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
145
146 return HARP_RET_OK;
147 }
148
149 static struct selgroup selsongacts[]={
150 {listSongs,"list"},
151 {editSongTitle,"title"},
152 {editSongTrack,"track"},
153 {editSongLocation,"location"},
154 {editSongAlbumArtist,"albumArtist"},
155 {deleteSong,"delete"},
156 {songActivation,"activate"},
157 {NULL,NULL}
158 };
runSongEditAction(commandline_t * cmd)159 static int runSongEditAction(commandline_t *cmd){
160 return runGenericEditAction(cmd,selsongacts);
161 }
162
listAlbums(command_t * sel,command_t * act)163 static int listAlbums(command_t *sel, command_t *act){
164 char query[300];
165 int exception[10];
166 int i;
167
168 for(i=0;i<10;i++)exception[i]=i<5?1:listconf.exception;
169 sprintf(query,"SELECT AlbumID, Title, \"Date\" FROM Album WHERE AlbumID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
170 doTitleQuery(query,exception,listconf.maxwidth);
171
172 return HARP_RET_OK;
173 }
editAlbumDate(command_t * sel,command_t * act)174 static int editAlbumDate(command_t *sel, command_t *act){
175 char query[300];
176
177 sprintf(query,"UPDATE Album SET Date=%s WHERE AlbumID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->words->word,sel->tlid);
178 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
179
180 return HARP_RET_OK;
181 }
182
editAlbumTitle(command_t * sel,command_t * act)183 static int editAlbumTitle(command_t *sel, command_t *act){
184 char query[300];
185
186 sprintf(query,"UPDATE Album SET Title='%s' WHERE AlbumID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->words->word,sel->tlid);
187 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
188
189 return HARP_RET_OK;
190 }
191
editAlbumArtist(command_t * sel,command_t * act)192 static int editAlbumArtist(command_t *sel, command_t *act){
193 char query[300];
194 int artistid;
195
196 if(act->args->words->flag==WORD_DEFAULT)
197 artistid=strtol(act->args->words->word,NULL,10);
198 else
199 artistid=getArtist(act->args->words->word);
200
201 sprintf(query,"UPDATE AlbumArtist SET ArtistID=%d WHERE AlbumID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",artistid,sel->tlid);
202 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
203
204 return HARP_RET_OK;
205 }
206
207 static struct selgroup selalbumacts[]={
208 {listAlbums,"list"},
209 {editAlbumTitle,"title"},
210 {editAlbumArtist,"artist"},
211 {editAlbumDate,"date"},
212 {NULL,NULL}
213 };
runAlbumEditAction(commandline_t * cmd)214 static int runAlbumEditAction(commandline_t *cmd){
215 return runGenericEditAction(cmd,selalbumacts);
216 }
217
listArtists(command_t * sel,command_t * act)218 static int listArtists(command_t *sel, command_t *act){
219 char query[300];
220 int exception[10];
221 int i;
222
223 for(i=0;i<10;i++)exception[i]=i<5?1:listconf.exception;
224 sprintf(query,"SELECT ArtistID, Name FROM Artist WHERE ArtistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
225 doTitleQuery(query,exception,listconf.maxwidth);
226
227 return HARP_RET_OK;
228 }
229
editArtistName(command_t * sel,command_t * act)230 static int editArtistName(command_t *sel, command_t *act){
231 char query[300];
232
233 sprintf(query,"UPDATE Artist SET Name='%s' WHERE ArtistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->words->word,sel->tlid);
234 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
235
236 return HARP_RET_OK;
237 }
238
239 static struct selgroup selartistacts[]={
240 {listArtists,"list"},
241 {editArtistName,"name"},
242 {NULL,NULL}
243 };
runArtistEditAction(commandline_t * cmd)244 static int runArtistEditAction(commandline_t *cmd){
245 return runGenericEditAction(cmd,selartistacts);
246 }
247
listPlaylists(command_t * sel,command_t * act)248 static int listPlaylists(command_t *sel, command_t *act){
249 char query[300];
250 int exception[10];
251 int i;
252
253 for(i=0;i<10;i++)exception[i]=i<5?1:listconf.exception;
254 sprintf(query,"SELECT PlaylistID, Title FROM Playlist WHERE PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
255 doTitleQuery(query,exception,listconf.maxwidth);
256
257 return HARP_RET_OK;
258 }
259
listPlaylistContents(command_t * sel,command_t * act)260 static int listPlaylistContents(command_t *sel, command_t *act){
261 char query[300];
262 int exception[10];
263 int i;
264
265 for(i=0;i<10;i++)exception[i]=i<5?1:listconf.exception;
266 sprintf(query,"SELECT PlaylistID, \"Order\" AS \"#\", SongID,SongTitle,AlbumTitle,ArtistName FROM PlaylistSong NATURAL JOIN SongPubInfo WHERE PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d) ORDER BY PlaylistID,\"Order\"",sel->tlid);
267 doTitleQuery(query,exception,listconf.maxwidth);
268
269 return HARP_RET_OK;
270 }
271
editPlaylistName(command_t * sel,command_t * act)272 static int editPlaylistName(command_t *sel, command_t *act){
273 char query[300];
274
275 sprintf(query,"UPDATE Playlist SET Name='%s' WHERE PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->words->word,sel->tlid);
276 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
277
278 return HARP_RET_OK;
279 }
280
deletePlaylist(command_t * sel,command_t * act)281 static int deletePlaylist(command_t *sel, command_t *act){
282 char query[300];
283
284 sprintf(query,"DELETE FROM PlaylistSong WHERE PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
285 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
286 sprintf(query,"DELETE FROM Playlist WHERE PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
287 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
288
289 return HARP_RET_OK;
290 }
291
editPlaylistOrder(command_t * sel,command_t * act)292 static int editPlaylistOrder(command_t *sel, command_t *act){
293 char query[300];
294 int oldO,newO;
295
296 if(act->args->next==NULL){
297 fprintf(stderr,"order: Two arguments required for this action.\n");
298 return HARP_RET_ERR;
299 }
300
301 oldO=strtol(act->args->words->word,NULL,10);
302 newO=strtol(act->args->next->words->word,NULL,10);
303
304 if(oldO<newO)
305 harp_sqlite3_exec(conn,"CREATE TEMPORARY TRIGGER PLIMv AFTER UPDATE ON PlaylistSong BEGIN "
306 "UPDATE PlaylistSong SET \"Order\"=\"Order\"-1 WHERE PlaylistID=OLD.PlaylistID AND \"Order\" BETWEEN OLD.\"Order\" AND NEW.\"Order\" AND PlaylistSongID!=OLD.PlaylistSongID;"
307 "END",NULL,NULL,NULL);
308 else
309 harp_sqlite3_exec(conn,"CREATE TEMPORARY TRIGGER PLIMv AFTER UPDATE ON PlaylistSong BEGIN "
310 "UPDATE PlaylistSong SET \"Order\"=\"Order\"+1 WHERE PlaylistID=OLD.PlaylistID AND \"Order\" BETWEEN NEW.\"Order\" AND OLD.\"Order\" AND PlaylistSongID!=OLD.PlaylistSongID;"
311 "END",NULL,NULL,NULL);
312
313 sprintf(query,"UPDATE PlaylistSong SET \"Order\"=%d WHERE \"Order\"=%d AND PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",newO,oldO,sel->tlid);
314 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
315
316 harp_sqlite3_exec(conn,"DROP TRIGGER PLIMv",NULL,NULL,NULL);
317
318 return HARP_RET_OK;
319 }
320
editPlaylistAdd(command_t * sel,command_t * act)321 static int editPlaylistAdd(command_t *sel, command_t *act){
322 char query[300];
323 char *songs_start,*songs_end;
324
325 if(act->args->next==NULL){
326 fprintf(stderr,"add: Two arguments required for this action.\n");
327 return HARP_RET_ERR;
328 }
329
330 if(act->args->words->flag==WORD_DEFAULT){
331 songs_start="SongID=";
332 songs_end="";
333 }
334 else{
335 songs_start="Song.Title LIKE '%%";
336 songs_end="%%'";
337 }
338
339 sprintf(query,"UPDATE PlaylistSong SET \"Order\"=\"Order\"+1 WHERE \"Order\">=%s AND PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d AND SelectID IN (SELECT PlaylistID FROM PlaylistSong WHERE \"Order\"=%s))",act->args->next->words->word,sel->tlid,act->args->next->words->word);
340 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
341
342 sprintf(query,"INSERT INTO PlaylistSong (SongID,PlaylistID,\"Order\") SELECT SongID,PlaylistID,%s FROM Song,Playlist WHERE %s%s%s AND PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->next->words->word,songs_start,act->args->words->word,songs_end,sel->tlid);
343 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
344
345 return HARP_RET_OK;
346 }
347
editPlaylistRemove(command_t * sel,command_t * act)348 static int editPlaylistRemove(command_t *sel, command_t *act){
349 char query[300];
350 char *songs_start,*songs_end;
351
352 if(strcmp(act->cmd->word,"removeOrder")==0){
353 songs_start="\"Order\"=";
354 songs_end="";
355 }
356 else{
357 if(act->args->words->flag==WORD_DEFAULT){
358 songs_start="SongID=";
359 songs_end="";
360 }
361 else{
362 songs_start="Song.Title LIKE '%%";
363 songs_end="%%'";
364 }
365 }
366
367 harp_sqlite3_exec(conn,"CREATE TEMPORARY TRIGGER PLIDel AFTER DELETE ON PlaylistSong BEGIN "
368 "UPDATE PlaylistSong SET \"Order\"=\"Order\"-1 WHERE PlaylistID=OLD.PlaylistID AND \"Order\">OLD.\"Order\";"
369 "END",NULL,NULL,NULL);
370
371 //sprintf(query,"DELETE FROM PlaylistSong (SongID,PlaylistID,\"Order\") SELECT SongID,PlaylistID,%s FROM Song,Playlist WHERE %s%s%s AND PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->next->words->word,songs_start,act->args->words->word,songs_end,sel->tlid);
372 sprintf(query,"DELETE FROM PlaylistSong WHERE PlaylistSongID IN (SELECT PlaylistSongID FROM PlaylistSong NATURAL JOIN Song WHERE %s%s%s AND PlaylistID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d))",songs_start,act->args->words->word,songs_end,sel->tlid);
373 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
374
375 harp_sqlite3_exec(conn,"DROP TRIGGER PLIDel",NULL,NULL,NULL);
376
377 return HARP_RET_OK;
378 }
379
380 static struct selgroup selplaylistacts[]={
381 {listPlaylists,"list"},
382 {listPlaylistContents,"contents"},
383 {editPlaylistName,"name"},
384 {deletePlaylist,"delete"},
385 {editPlaylistOrder,"order"},
386 {editPlaylistAdd,"add"},
387 {editPlaylistRemove,"removeOrder"},
388 {editPlaylistRemove,"removeSong"},
389 {NULL,NULL}
390 };
runPlaylistEditAction(commandline_t * cmd)391 static int runPlaylistEditAction(commandline_t *cmd){
392 char query[200];
393 sprintf(query,"DELETE FROM TempSelect WHERE SelectID=1 AND TempID=%d",cmd->selector->tlid);
394 harp_sqlite3_exec(conn,query,NULL,NULL,NULL); // Failsafe, disable editing of library directly
395 return runGenericEditAction(cmd,selplaylistacts);
396 }
397
listTags(command_t * sel,command_t * act)398 static int listTags(command_t *sel, command_t *act){
399 char query[300];
400 int exception[10];
401 int i;
402
403 for(i=0;i<10;i++)exception[i]=i<5?1:listconf.exception;
404 sprintf(query,"SELECT TagID, Name FROM Tag WHERE TagID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
405 doTitleQuery(query,exception,listconf.maxwidth);
406
407 return HARP_RET_OK;
408 }
409
listTagContents(command_t * sel,command_t * act)410 static int listTagContents(command_t *sel, command_t *act){
411 char query[300];
412 int exception[10];
413 int i;
414
415 for(i=0;i<10;i++)exception[i]=i<5?1:listconf.exception;
416 sprintf(query,"SELECT TagID,SongID,SongTitle,AlbumTitle,ArtistName FROM SongTag NATURAL JOIN SongPubInfo WHERE TagID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d) ORDER BY TagID",sel->tlid);
417 doTitleQuery(query,exception,listconf.maxwidth);
418
419 return HARP_RET_OK;
420 }
421
editTagName(command_t * sel,command_t * act)422 static int editTagName(command_t *sel, command_t *act){
423 char query[300];
424
425 sprintf(query,"UPDATE Tag SET Name='%s' WHERE TagID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->args->words->word,sel->tlid);
426 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
427
428 return HARP_RET_OK;
429 }
430
deleteTag(command_t * sel,command_t * act)431 static int deleteTag(command_t *sel, command_t *act){
432 char query[300];
433
434 sprintf(query,"DELETE FROM SongTag WHERE TagID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
435 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
436 sprintf(query,"DELETE FROM Tag WHERE TagID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",sel->tlid);
437 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
438
439 return HARP_RET_OK;
440 }
441
editTagAdd(command_t * sel,command_t * act)442 static int editTagAdd(command_t *sel, command_t *act){
443 char query[300];
444 char *songs_start,*songs_end;
445
446 if(act->tlid>=0){
447 sprintf(query,"INSERT INTO SongTag (SongID,TagID) SELECT SongID,TagID FROM Song,Tag WHERE Song.SongID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d) AND TagID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",act->tlid,sel->tlid);
448 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
449 return HARP_RET_OK;
450 }
451 if(act->args->words->flag==WORD_DEFAULT){
452 songs_start="SongID=";
453 songs_end="";
454 }
455 else{
456 songs_start="Song.Title LIKE '%%";
457 songs_end="%%'";
458 }
459
460 sprintf(query,"INSERT INTO SongTag (SongID,TagID) SELECT SongID,TagID FROM Song,Tag WHERE %s%s%s AND TagID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",songs_start,act->args->words->word,songs_end,sel->tlid);
461 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
462
463 return HARP_RET_OK;
464 }
465
editTagRemove(command_t * sel,command_t * act)466 static int editTagRemove(command_t *sel, command_t *act){
467 char query[300];
468 char *songs_start,*songs_end;
469
470 if(act->args->words->flag==WORD_DEFAULT){
471 songs_start="SongID=";
472 songs_end="";
473 }
474 else{
475 songs_start="Song.Title LIKE '%%";
476 songs_end="%%'";
477 }
478
479 sprintf(query,"DELETE FROM SongTag WHERE %s%s%s AND TagID IN (SELECT SelectID FROM TempSelect WHERE TempID=%d)",songs_start,act->args->words->word,songs_end,sel->tlid);
480 harp_sqlite3_exec(conn,query,NULL,NULL,NULL);
481
482 return HARP_RET_OK;
483 }
484
485 static struct selgroup seltagacts[]={
486 {listTags,"list"},
487 {listTagContents,"contents"},
488 {editTagName,"name"},
489 {deleteTag,"delete"},
490 {editTagAdd,"add"},
491 {editTagRemove,"remove"},
492 {NULL,NULL}
493 };
runTagEditAction(commandline_t * cmd)494 static int runTagEditAction(commandline_t *cmd){
495 return runGenericEditAction(cmd,seltagacts);
496 }
497
498 static seltypefun selacts[]={
499 runSongEditAction,
500 runAlbumEditAction,
501 runArtistEditAction,
502 runPlaylistEditAction,
503 runTagEditAction,
504 NULL
505 };
runEditAction(commandline_t * cmd)506 static int runEditAction(commandline_t *cmd){
507 if(cmd->selector->tltype>=0 && cmd->selector->tltype<SEL_NULL){
508 return selacts[cmd->selector->tltype](cmd);
509 }
510 return HARP_RET_ERR;
511 }
512
cleanOrphans()513 static void cleanOrphans(){
514 // Clean orphaned albums
515 harp_sqlite3_exec(conn,"DELETE FROM Album WHERE AlbumID NOT IN (SELECT AlbumID FROM Song)",NULL,NULL,NULL);
516 // Clean orphaned albumartists
517 harp_sqlite3_exec(conn,"DELETE FROM AlbumArtist WHERE AlbumID NOT IN (SELECT AlbumID FROM Song)",NULL,NULL,NULL);
518 // Clean orphaned artists
519 harp_sqlite3_exec(conn,"DELETE FROM Artist WHERE ArtistID NOT IN (SELECT ArtistID FROM AlbumArtist)",NULL,NULL,NULL);
520 }
521
editShell()522 int editShell(){
523 char src[512];
524 int ret;
525
526 if(!arglist[AEDIT].subarg){
527 printf("Edit> ");
528 while(fgets(src,512,stdin)){
529 tlist = lex(src);
530 fullcmd=NULL;
531 ret=yyparse();
532
533 if(!ret)
534 ret=runEditAction(fullcmd);
535 else
536 ret=HARP_RET_ERR;
537
538 printf("Edit> ");
539 }
540 }
541 else{
542 tlist = lex(arglist[AEDIT].subarg);
543 fullcmd=NULL;
544 ret=yyparse();
545
546 if(!ret)
547 ret=runEditAction(fullcmd);
548 else
549 ret=HARP_RET_ERR;
550 }
551
552 cleanOrphans();
553
554 return ret;
555 }
556