Subversion Repositories mdb

Rev

Rev 56 | Rev 58 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6 andreas 1
/*
2
 * Copyright (C) 2015 by Andreas Theofilu <andreas@theosys.at>
3
 *
4
 * All rights reserved. No warranty, explicit or implicit, provided.
5
 *
6
 * NOTICE:  All information contained herein is, and remains
7
 * the property of Andreas Theofilu and his suppliers, if any.
8
 * The intellectual and technical concepts contained
9
 * herein are proprietary to Andreas Theofilu and its suppliers and
10
 * may be covered by European and Foreign Patents, patents in process,
11
 * and are protected by trade secret or copyright law.
12
 * Dissemination of this information or reproduction of this material
13
 * is strictly forbidden unless prior written permission is obtained
14
 * from Andreas Theofilu.
15
 */
16
#include <stdio.h>
17
#include <string.h>
18
#include <strings.h>
19
#include <unistd.h>
20
#include <stdlib.h>
21
#include <libgen.h>
22
#include <ctype.h>
23
#include <math.h>
24
#include <syslog.h>
25
#include <errno.h>
26
#include <sys/stat.h>
27
#include <sys/types.h>
28
#include <fcntl.h>
28 andreas 29
#include <time.h>
57 andreas 30
#include <pthread.h>
6 andreas 31
#include <sqlite3.h>
7 andreas 32
#include <ao/ao.h>
33
#include <mpg123.h>
6 andreas 34
#include "config.h"
32 andreas 35
#include "mdb.h"
6 andreas 36
#include "helplib.h"
37
#include "play.h"
32 andreas 38
#include "play_flac.h"
8 andreas 39
#include "user.h"
6 andreas 40
 
41
#define CMD_SET_NONE	0
42
#define CMD_SET1		1
43
#define CMD_SET2		2
44
 
45
#define NOWPLAY			"/nowplaying.list"
7 andreas 46
#define BITS			8
6 andreas 47
 
7 andreas 48
int nextCommand = PLAY_NONE;
49
int playStatus;
50
int playerActive = FALSE;
11 andreas 51
int playerRepeat = FALSE;
52
int playerRandom = FALSE;
55 andreas 53
int playQuiet = FALSE;
11 andreas 54
ST_PLAYING playCurrent;
55
QUEUE *pqueue = NULL;
50 andreas 56
QUEUE *qstack = NULL;
11 andreas 57
int queueTotal = 0;
58
 
28 andreas 59
char aoOutPlayers[15][16] =
60
{
61
	"aixs",
62
	"alsa",
63
	"arts",
64
	"esd",
65
	"irix",
66
	"macosx",
67
	"nas",
68
	"null",
69
	"oss",
70
	"pulse",
71
	"roar",
72
	"sndio",
73
	"sun",
74
	"wmm",
75
	"\0"
76
};
77
 
6 andreas 78
/* Prototypes */
79
static int playCallback(void *hint, int argc, char **argv, char **azColName);
7 andreas 80
void playMP3(int s1, char *file);
11 andreas 81
int checkQueueDouble(int id);
82
void freeQueue();
83
void setCurrentQueue(QUEUE *q);
84
QUEUE *getRandomQueue();
85
QUEUE *getQueue(int idx);
86
void setCurrentQueue(QUEUE *q);
32 andreas 87
QUEUE *addToQueue(int id, char *path, int fType, char *title, char *artist, char *album, char *genre, char *cover);
6 andreas 88
 
89
/*
90
 * This function is called as a thread.
7 andreas 91
 * It uses the libmpg123 library to decode a MP3 file and the library libao
92
 * to play the decoded samples.
36 andreas 93
 * TODO: Implement a player for the formats OGG and WAV
49 andreas 94
 * TODO: Implement an internet radio
6 andreas 95
 */
96
void *pthr_playfile(void *pV_data)
97
{
49 andreas 98
char fname[256], query[8192], hv0[256];
99
int rc, flag, start;
100
sqlite3 *db;
101
char *zErrMsg = 0;
102
struct ST_PlayPars *_playPars;
103
sqlite3_stmt *res;
6 andreas 104
 
7 andreas 105
	playerActive = TRUE;				/* Kind of locking :-) */
6 andreas 106
	_playPars = (struct ST_PlayPars *)pV_data;
11 andreas 107
	start = 0;
52 andreas 108
	nextCommand = PLAY_NONE;			/* Make sure that there is no command left */
9 andreas 109
 
110
	if (_playPars == NULL)
111
	{
112
		syslog(LOG_DAEMON, "Internal error: Invalid or no parameters for thread \"pthr_playfile\"!");
113
		playerActive = FALSE;
57 andreas 114
		pthread_exit(NULL);
14 andreas 115
		return NULL;
9 andreas 116
	}
117
 
6 andreas 118
	/* retrieve the data from the database */
40 andreas 119
	strcpy(fname, configs.home);			/* Base file name */
120
	strcat(fname, MUSICDB);					/* File name of database */
6 andreas 121
 
122
	rc = sqlite3_open(fname, &db);
123
 
124
	if (rc)
125
	{
126
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
127
		strcpy(query, "ERROR:PLAY:Error opening database;");
128
		write (_playPars->s1, query, strlen(query));
7 andreas 129
		playerActive = FALSE;
57 andreas 130
		pthread_exit(NULL);
14 andreas 131
		return NULL;
6 andreas 132
	}
133
 
32 andreas 134
	strcpy (query, "select id, path, type, title, interpret, album, genre, cover from \"main\".\"musicdb\" where ");
11 andreas 135
	flag = FALSE;
6 andreas 136
 
137
	if (strcasecmp(_playPars->type, "ID") == 0)
138
	{
139
		strcat(query, "id = ");
140
		strcat(query, _playPars->what);
141
		strcpy(fname, configs.home);
142
		strcat(fname, NOWPLAY);
143
		unlink(fname);
11 andreas 144
		freeQueue();
145
		flag = TRUE;
6 andreas 146
	}
49 andreas 147
	else if (strcasecmp(_playPars->type, "DIRECT") == 0)
148
	{
50 andreas 149
		if (configs.debug)
150
			syslog(LOG_DEBUG, "pthr_playfile(): Playing ID %s direct.", _playPars->what);
151
 
49 andreas 152
		strcat(query, "id = ");
153
		strcat(query, _playPars->what);
154
		flag = TRUE;
155
	}
6 andreas 156
	else if (strcasecmp(_playPars->type, "TITLE") == 0)
157
	{
158
		strcat(query, "title = \"");
159
		strcat(query, _playPars->what);
160
		strcat(query, "\" order by title");
11 andreas 161
		flag = TRUE;
6 andreas 162
	}
163
	else if (strcasecmp(_playPars->type, "ARTIST") == 0)
164
	{
165
		strcat(query, "interpret = \"");
166
		strcat(query, _playPars->what);
167
		strcat(query, "\" order by interpret");
11 andreas 168
		flag = TRUE;
6 andreas 169
	}
170
	else if (strcasecmp(_playPars->type, "ALBUM") == 0)
171
	{
172
		strcat(query, "album = \"");
173
		strcat(query, _playPars->what);
174
		strcat(query, "\" order by album");
11 andreas 175
		flag = TRUE;
6 andreas 176
	}
177
	else if (strcasecmp(_playPars->type, "GENRE") == 0)
178
	{
179
		strcat(query, "genre = \"");
180
		strcat(query, _playPars->what);
181
		strcat(query, "\" order by genre");
11 andreas 182
		flag = TRUE;
6 andreas 183
	}
11 andreas 184
	else if (strcasecmp(_playPars->type, "QUEUE") == 0)
9 andreas 185
	{
40 andreas 186
		strcpy(fname, configs.home);				/* Base path */
187
		strcat(fname, NOWPLAY);						/* Append file name of queue to path */
7 andreas 188
 
40 andreas 189
		if (access(fname, R_OK))					/* In case we've no access or the file doesn't exist, quit this thread. */
7 andreas 190
		{
9 andreas 191
			strcpy (hv0, "ERROR:PLAY:No or empty queue;");
7 andreas 192
			write (_playPars->s1, hv0, strlen(hv0));
9 andreas 193
			sqlite3_close(db);
194
			playerActive = FALSE;
14 andreas 195
			return NULL;
7 andreas 196
		}
11 andreas 197
 
198
		start = atoi(_playPars->what);
6 andreas 199
	}
11 andreas 200
	else if (strcasecmp(_playPars->type, "PLAYLIST") == 0)
9 andreas 201
	{
202
		USERS *act;
203
 
204
		if (userchain == NULL)
205
		{
206
			strcpy (hv0, "ERROR:PLAY:No user selected;");
207
			write (_playPars->s1, hv0, strlen(hv0));
208
			sqlite3_close(db);
209
			playerActive = FALSE;
57 andreas 210
			pthread_exit(NULL);
14 andreas 211
			return NULL;
9 andreas 212
		}
213
 
214
		/* find uid */
14 andreas 215
		if ((act = findPlaylist(userchain->uname, _playPars->what)) != NULL)
9 andreas 216
		{
11 andreas 217
			if (!playlistToQueue(act->id, TRUE))
9 andreas 218
			{
219
				sqlite3_close(db);
220
				playerActive = FALSE;
57 andreas 221
				pthread_exit(NULL);
14 andreas 222
				return NULL;
9 andreas 223
			}
224
		}
11 andreas 225
		else if (isnumeric(_playPars->what))
226
		{
227
			int id;
228
 
229
			id = atoi(_playPars->what);
230
 
231
			if (!playlistToQueue(id, TRUE))
232
			{
233
				sqlite3_close(db);
234
				playerActive = FALSE;
57 andreas 235
				pthread_exit(NULL);
14 andreas 236
				return NULL;
11 andreas 237
			}
238
		}
9 andreas 239
		else
240
		{
241
			strcpy (hv0, "ERROR:PLAY:No playlist found;");
242
			write (_playPars->s1, hv0, strlen(hv0));
243
			sqlite3_close(db);
244
			playerActive = FALSE;
57 andreas 245
			pthread_exit(NULL);
14 andreas 246
			return NULL;
9 andreas 247
		}
248
	}
11 andreas 249
	else
6 andreas 250
	{
11 andreas 251
		strcpy(hv0, "ERROR:PLAY:Missing type of argument;");
252
		write(_playPars->s1, hv0, strlen(hv0));
253
		sqlite3_close(db);
254
		playerActive = FALSE;
57 andreas 255
		pthread_exit(NULL);
14 andreas 256
		return NULL;
11 andreas 257
	}
258
 
49 andreas 259
	if (configs.debug)
11 andreas 260
	{
49 andreas 261
		syslog(LOG_DEBUG, "Player: SQL: %s", query);
262
		syslog(LOG_DEBUG, "Player: FLAG: %d, TYPE: %s", flag, _playPars->type);
263
	}
264
 
265
	if (flag && strcasecmp(_playPars->type, "DIRECT") == 0)
266
	{
267
		char *p, path[1024], title[255], artist[255], album[255], genre[128], cover[255];
268
		int id, type, err;
269
 
270
		if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
271
		{
272
			syslog(LOG_WARNING, "SQL error [%s]: %s", query, sqlite3_errmsg(db));
273
			sqlite3_close(db);
274
			strcpy(query, "ERROR:PLAY:SQL error;");
275
			write (_playPars->s1, query, strlen(query));
276
			playerActive = FALSE;
57 andreas 277
			pthread_exit(NULL);
49 andreas 278
			return NULL;
279
		}
280
 
281
		err = 0;
282
		memset(path, 0, sizeof(path));
283
		memset(title, 0, sizeof(title));
284
		memset(artist, 0, sizeof(artist));
285
		memset(album, 0, sizeof(album));
286
		memset(genre, 0, sizeof(genre));
287
		memset(cover, 0, sizeof(cover));
288
 
289
		rc = sqlite3_step(res);
290
 
291
		id = sqlite3_column_int(res, 0);
292
 
293
		if (configs.debug)
294
			syslog(LOG_DEBUG, "Playing directly ID: %d", id);
295
 
296
		if ((p = (char *)sqlite3_column_text(res, 1)) == NULL)
297
		{
298
			syslog(LOG_WARNING, "Error getting path from database!");
299
			sqlite3_finalize(res);
300
			sqlite3_close(db);
301
			strcpy(query, "ERROR:PLAY:SQL error;");
302
			write (_playPars->s1, query, strlen(query));
303
			playerActive = FALSE;
57 andreas 304
			pthread_exit(NULL);
49 andreas 305
			return NULL;
306
		}
307
		else
308
			strncpy(path, p, sizeof(path));
309
 
310
		type = sqlite3_column_int(res, 2);
311
 
312
		if ((p = (char *)sqlite3_column_text(res, 3)) == NULL)
313
		{
314
			syslog(LOG_WARNING, "Error getting title from database!");
315
			sqlite3_finalize(res);
316
			sqlite3_close(db);
317
			strcpy(query, "ERROR:PLAY:SQL error;");
318
			write (_playPars->s1, query, strlen(query));
319
			playerActive = FALSE;
57 andreas 320
			pthread_exit(NULL);
49 andreas 321
			return NULL;
322
		}
323
		else
324
			strncpy(title, p, sizeof(title));
325
 
326
		if ((p = (char *)sqlite3_column_text(res, 4)) == NULL)
327
		{
328
			syslog(LOG_WARNING, "Error getting artist from database!");
329
			sqlite3_finalize(res);
330
			sqlite3_close(db);
331
			strcpy(query, "ERROR:PLAY:SQL error;");
332
			write (_playPars->s1, query, strlen(query));
333
			playerActive = FALSE;
57 andreas 334
			pthread_exit(NULL);
49 andreas 335
			return NULL;
336
		}
337
		else
338
			strncpy(artist, p, sizeof(artist));
339
 
340
		if ((p = (char *)sqlite3_column_text(res, 5)) == NULL)
341
		{
342
			syslog(LOG_WARNING, "Error getting album from database!");
343
			sqlite3_finalize(res);
344
			sqlite3_close(db);
345
			strcpy(query, "ERROR:PLAY:SQL error;");
346
			write (_playPars->s1, query, strlen(query));
347
			playerActive = FALSE;
57 andreas 348
			pthread_exit(NULL);
49 andreas 349
			return NULL;
350
		}
351
		else
352
			strncpy(album, p, sizeof(album));
353
 
354
		if ((p = (char *)sqlite3_column_text(res, 6)) == NULL)
355
		{
356
			syslog(LOG_WARNING, "Error getting genre from database!");
357
			sqlite3_finalize(res);
358
			sqlite3_close(db);
359
			strcpy(query, "ERROR:PLAY:SQL error;");
360
			write (_playPars->s1, query, strlen(query));
361
			playerActive = FALSE;
57 andreas 362
			pthread_exit(NULL);
49 andreas 363
			return NULL;
364
		}
365
		else
366
			strncpy(genre, p, sizeof(genre));
367
 
368
		if ((p = (char *)sqlite3_column_text(res, 7)) != NULL)
369
			strncpy(cover, p, sizeof(cover));
370
 
371
		sqlite3_finalize(res);
372
		sprintf(query, "PLAYING:%d:", id);
373
 
50 andreas 374
		if ((p = urlencode(title)) != NULL)
375
		{
376
			strcat(query, p);
377
			free(p);
378
		}
379
 
49 andreas 380
		strcat(query, ":");
50 andreas 381
 
382
		if ((p = urlencode(artist)) != NULL)
383
		{
384
			strcat(query, p);
385
			free(p);
386
		}
387
 
49 andreas 388
		strcat(query, ":");
50 andreas 389
 
390
		if ((p = urlencode(album)) != NULL)
391
		{
392
			strcat(query, p);
393
			free(p);
394
		}
395
 
49 andreas 396
		strcat(query, ":");
50 andreas 397
 
398
		if ((p = urlencode(genre)) != NULL)
399
		{
400
			strcat(query, p);
401
			free(p);
402
		}
403
 
49 andreas 404
		strcat(query, ":");
405
 
56 andreas 406
		if (strlen(cover) != 0)
50 andreas 407
		{
408
			if ((p = urlencode(cover)) != NULL)
409
			{
410
				strcat(query, p);
411
				free(p);
412
			}
413
		}
49 andreas 414
 
415
		strcat(query, ";");
416
		write(_playPars->s1, query, strlen(query));
417
 
50 andreas 418
		while (strlen(path))
419
		{
420
			QUEUE *act;
49 andreas 421
 
50 andreas 422
			if (configs.debug)
423
				syslog(LOG_DEBUG, "Player: Trying to play file: %s", path);
49 andreas 424
 
50 andreas 425
			if (type == FILE_TYPE_MP3)
426
				playMP3(_playPars->s1, path);
427
			else
428
				playFlac(_playPars->s1, path);
429
 
430
			path[0] = 0;
431
 
432
			if (playStatus == PLAY_STATUS_STACK || playStatus == PLAY_STATUS_STPLAY)
433
			{
434
				act = qstackNext();
435
 
436
				if (act)
437
				{
438
					playStatus = PLAY_STATUS_STPLAY;
439
					nextCommand = PLAY_NONE;
440
					strncpy(path, act->path, sizeof(path));
441
				}
442
				else
443
				{
444
					nextCommand = PLAY_NONE;
445
					playStatus = PLAY_STATUS_STOP;
446
				}
447
			}
448
		}
449
 
49 andreas 450
		playerActive = FALSE;
57 andreas 451
		pthread_exit(NULL);
49 andreas 452
		return NULL;
453
	}
454
	else if (flag && (rc = sqlite3_exec(db, query, playCallback, (void *)_playPars->what, &zErrMsg)) != SQLITE_OK)
455
	{
6 andreas 456
		syslog(LOG_WARNING, "SQL error [%s]: %s", query, zErrMsg);
457
		sqlite3_free(zErrMsg);
458
		sqlite3_close(db);
459
		strcpy(query, "ERROR:PLAY:SQL error;");
460
		write (_playPars->s1, query, strlen(query));
7 andreas 461
		playerActive = FALSE;
57 andreas 462
		pthread_exit(NULL);
14 andreas 463
		return NULL;
6 andreas 464
	}
465
 
49 andreas 466
	if (configs.debug)
467
		syslog(LOG_DEBUG, "Playing from current queue starting at entry %d", start);
468
 
11 andreas 469
	strcpy (fname, configs.home);
470
	strcat (fname, NOWPLAY);
6 andreas 471
	/* start the player and play the file(s) */
7 andreas 472
	if (!access(fname, R_OK))
6 andreas 473
	{
36 andreas 474
		int fd, iflag, num, nextNum;
11 andreas 475
		QUEUE *act;
6 andreas 476
 
477
		if ((fd = open(fname, O_RDONLY)) < 0)
478
		{
479
			syslog(LOG_WARNING, "Error opening file %s: %s", fname, strerror(errno));
7 andreas 480
			playerActive = FALSE;
57 andreas 481
			pthread_exit(NULL);
14 andreas 482
			return NULL;
6 andreas 483
		}
484
 
36 andreas 485
		iflag = FALSE;
7 andreas 486
		num = 0;
487
		nextNum = -1;
488
 
11 andreas 489
		if (start > 0 && start <= queueTotal)
490
			num = start - 1;
491
 
492
		scanQueue(fd);
493
		close(fd);
494
 
36 andreas 495
		if (playerRandom && !flag && start <= 0)
11 andreas 496
			act = getRandomQueue();
497
		else
498
			act = getQueue(num);
499
 
500
		while (act)
6 andreas 501
		{
11 andreas 502
			char *title, *artist, *album, *cover;
6 andreas 503
 
7 andreas 504
			if (nextNum >= 0)
505
			{
506
				if (num == nextNum)
507
					nextNum = -1;
508
				else
509
				{
510
					num++;
11 andreas 511
					act = getQueue(num);
7 andreas 512
					continue;
513
				}
514
			}
515
 
36 andreas 516
			iflag = TRUE;
11 andreas 517
			title = urlencode(act->title);
518
			artist = urlencode(act->artist);
519
			album = urlencode(act->album);
520
			cover = urlencode(act->cover);
521
			sprintf(query, "PLAYING:%d:", act->id);
6 andreas 522
 
7 andreas 523
			if (title != NULL)
6 andreas 524
			{
7 andreas 525
				strcat(query, title);
526
				free(title);
527
			}
528
			else
11 andreas 529
				strcat(query, act->title);
6 andreas 530
 
7 andreas 531
			strcat(query, ":");
6 andreas 532
 
7 andreas 533
			if (artist != NULL)
534
			{
535
				strcat(query, artist);
536
				free(artist);
537
			}
538
			else
11 andreas 539
				strcat(query, act->artist);
6 andreas 540
 
7 andreas 541
			strcat(query, ":");
6 andreas 542
 
7 andreas 543
			if (album != NULL)
544
			{
545
				strcat(query, album);
546
				free(album);
547
			}
548
			else
11 andreas 549
				strcat(query, act->album);
6 andreas 550
 
7 andreas 551
			strcat(query, ":");
11 andreas 552
			strcat(query, act->genre);
553
			strcat(query, ":");
554
 
555
			if (cover != NULL)
556
			{
557
				strcat(query, cover);
558
				free(cover);
559
			}
560
			else
561
				strcat(query, act->cover);
562
 
7 andreas 563
			strcat(query, ";");
564
			write(_playPars->s1, query, strlen(query));
11 andreas 565
			setCurrentQueue(act);
566
			act->played = TRUE;
40 andreas 567
 
32 andreas 568
			if (act->fType == FILE_TYPE_MP3)
569
				playMP3(_playPars->s1, act->path);
570
			else
571
				playFlac(_playPars->s1, act->path);
6 andreas 572
 
54 andreas 573
			if (configs.debug)
574
				syslog(LOG_DEBUG, "Current play status: %d", playStatus);
575
 
7 andreas 576
			if (playStatus == PLAY_STATUS_SKIPF)
577
				playStatus = PLAY_STATUS_STOP;
11 andreas 578
			else if (playStatus == PLAY_STATUS_SKIPR && !playerRandom)
7 andreas 579
			{
580
				if (num > 0)
581
				{
582
					nextNum = num - 1;
583
					num = 0;
11 andreas 584
					act = pqueue;
7 andreas 585
					continue;
586
				}
6 andreas 587
 
7 andreas 588
				playStatus = PLAY_STATUS_STOP;
589
			}
50 andreas 590
			else if (playStatus == PLAY_STATUS_STACK || playStatus == PLAY_STATUS_STPLAY)
591
			{
592
				act = qstackNext();
593
 
594
				if (act)
595
				{
596
					playStatus = PLAY_STATUS_STPLAY;
597
					nextCommand = PLAY_NONE;
598
					continue;
599
				}
600
				else
601
				{
602
					nextCommand = PLAY_NONE;
603
					playStatus = PLAY_STATUS_PLAY;
604
				}
605
			}
7 andreas 606
			else if (playStatus == PLAY_STATUS_STOP)
607
				break;
6 andreas 608
 
7 andreas 609
			num++;
11 andreas 610
 
611
			if (playerRandom)
612
				act = getRandomQueue();
613
			else
614
				act = getQueue(num);
615
 
616
			if (playerRepeat && act == NULL)
617
			{
618
				num = 0;
619
				act = pqueue;
620
			}
54 andreas 621
 
622
			if (configs.debug)
623
				syslog(LOG_DEBUG, "Do we have a next file to play? >>%s<<", (act == NULL) ? "NO" : "YES");
7 andreas 624
		}
6 andreas 625
 
36 andreas 626
		if (!iflag)
7 andreas 627
			syslog(LOG_WARNING, "Found no files to play!");
6 andreas 628
 
7 andreas 629
		close (fd);
6 andreas 630
	}
7 andreas 631
	else
632
		syslog(LOG_WARNING, "Error accessing file %s: %s", fname, strerror(errno));
6 andreas 633
 
7 andreas 634
	playerActive = FALSE;
57 andreas 635
	pthread_exit(NULL);
14 andreas 636
	return NULL;
6 andreas 637
}
638
 
639
static int playCallback(void *hint, int argc, char **argv, char **azColName)
640
{
32 andreas 641
	int i, id, fd, fType;
11 andreas 642
	char path[512], id3_title[256], id3_artist[256], id3_album[256], id3_genre[256], id3_cover[512];
6 andreas 643
	char buffer[8192], *what;
644
 
645
	what = (char *)hint;
646
	memset(path, 0, sizeof(path));
647
	memset(id3_title, 0, sizeof(id3_title));
648
	memset(id3_artist, 0, sizeof(id3_artist));
649
	memset(id3_album, 0, sizeof(id3_album));
650
	memset(id3_genre, 0, sizeof(id3_genre));
11 andreas 651
	memset(id3_cover, 0, sizeof(id3_cover));
6 andreas 652
	id = -1;
653
 
654
	for(i = 0; i < argc; i++)
655
	{
656
		if (strcasecmp(azColName[i], "id") == 0)
657
			if (argv[i])
658
				id = atoi(argv[i]);
659
 
660
		if (strcasecmp(azColName[i], "path") == 0)
661
			if (argv[i])
662
				strncpy(path, argv[i], sizeof(path));
663
 
32 andreas 664
		if (strcasecmp(azColName[i], "type") == 0)
665
			if (argv[i])
666
				fType = atoi(argv[i]);
667
 
6 andreas 668
		if (strcasecmp(azColName[i], "title") == 0)
669
			if (argv[i])
670
				strncpy(id3_title, argv[i], sizeof(id3_title));
671
 
672
		if (strcasecmp(azColName[i], "interpret") == 0)
673
			if (argv[i])
674
				strncpy(id3_artist, argv[i], sizeof(id3_artist));
675
 
676
		if (strcasecmp(azColName[i], "album") == 0)
677
			if (argv[i])
678
				strncpy(id3_album, argv[i], sizeof(id3_album));
679
 
680
		if (strcasecmp(azColName[i], "genre") == 0)
681
			if (argv[i])
682
				strncpy(id3_genre, argv[i], sizeof(id3_genre));
11 andreas 683
 
684
			if (strcasecmp(azColName[i], "cover") == 0)
685
				if (argv[i])
686
					strncpy(id3_cover, argv[i], sizeof(id3_cover));
6 andreas 687
	}
688
 
689
	if (id != -1 && strlen(path) > 0)
690
	{
691
		char fname[512];
692
 
693
		strcpy(fname, configs.home);
694
		strcat(fname, NOWPLAY);
695
 
11 andreas 696
		if (checkQueueDouble(id) == TRUE)	/* Make sure every ID in the queue is unique */
7 andreas 697
			return 0;
698
 
699
		if ((fd = open(fname, O_RDWR | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP)) < 0)
6 andreas 700
		{
8 andreas 701
			syslog(LOG_WARNING, "Error creating or writing to file %s: %s", fname, strerror(errno));
6 andreas 702
			return 1;
703
		}
7 andreas 704
 
32 andreas 705
		sprintf (buffer, "%s\t%d\t%d\t%s\t%s\t%s\t%s\t%s\n", path, fType, id, id3_title, id3_artist, id3_album, id3_genre, id3_cover);
6 andreas 706
		write (fd, buffer, strlen(buffer));
32 andreas 707
		addToQueue(id, path, fType, id3_title, id3_artist, id3_album, id3_genre, id3_cover);
6 andreas 708
		close (fd);
709
	}
710
	else
7 andreas 711
		syslog(LOG_WARNING, "Found no data to play");
6 andreas 712
 
713
	return 0;
714
}
715
 
7 andreas 716
void playMP3(int s1, char *file)
6 andreas 717
{
34 andreas 718
mpg123_handle *mh;
719
unsigned char *buffer;
720
size_t buffer_size;
721
size_t done;
722
off_t frame;
53 andreas 723
int err, i, rc, flag;
34 andreas 724
char hv0[128];
725
 
726
int driver;
727
ao_device *dev;
728
ao_option ao_opts;
729
 
54 andreas 730
ao_sample_format format;
731
int channels, encoding;
732
long rate;
733
double current_seconds, seconds_left, act_sec;
734
off_t current_frame, frames_left;
6 andreas 735
 
7 andreas 736
	if(file == NULL || strlen(file) == 0)
6 andreas 737
	{
7 andreas 738
		syslog(LOG_DAEMON, "No or invalid file was passed to player!");
739
		return;
6 andreas 740
	}
741
 
28 andreas 742
	/* Check if we've a valid sound driver defined */
743
	flag = FALSE;
744
	i = 0;
745
 
746
	while (aoOutPlayers[i][0])
747
	{
748
		if (!strcasecmp(aoOutPlayers[i], configs.player))
749
		{
750
			flag = TRUE;
34 andreas 751
 
752
			if (configs.debug)
753
				syslog(LOG_DEBUG, "Found sound driver %s to use for playback.", aoOutPlayers[i]);
754
 
28 andreas 755
			break;
756
		}
757
 
758
		i++;
759
	}
760
 
50 andreas 761
	if (configs.debug)
762
		syslog(LOG_DEBUG, "playMP3: Try to play file >>%s<<", file);
763
 
7 andreas 764
	/* initializations */
765
	ao_initialize();
28 andreas 766
 
767
	if (flag)
6 andreas 768
	{
28 andreas 769
		if ((driver = ao_driver_id(configs.player)) == -1)
770
		{
771
			syslog(LOG_DAEMON, "Error finding the audio out driver %s!", configs.player);
772
			ao_shutdown();
773
			return;
774
		}
775
	}
776
	else if ((driver = ao_default_driver_id()) == -1)
777
	{
7 andreas 778
		syslog(LOG_DAEMON, "Error finding a default audio driver!");
779
		ao_shutdown();
780
		return;
6 andreas 781
	}
7 andreas 782
 
783
	mpg123_init();
54 andreas 784
 
785
	if (configs.debug)
786
		syslog(LOG_DEBUG, "MPG123 initialized.");
787
 
7 andreas 788
	if ((mh = mpg123_new(NULL, &err)) == NULL)
789
	{
790
		syslog(LOG_DAEMON, "Error creating new MP3 handle: %s", mpg123_plain_strerror(err));
791
		ao_shutdown();
792
		return;
793
	}
794
 
54 andreas 795
	if (configs.debug)
796
		syslog(LOG_DEBUG, "MPG123 opened.");
797
 
7 andreas 798
	buffer_size = mpg123_outblock(mh);
799
 
800
	if ((buffer = (unsigned char*)malloc(buffer_size * sizeof(unsigned char))) == NULL)
801
	{
802
		syslog(LOG_DAEMON, "Error allocating memory for MP3 player: %s", strerror(errno));
803
		mpg123_close(mh);
804
		mpg123_delete(mh);
805
		mpg123_exit();
806
		ao_shutdown();
807
		return;
808
	}
809
 
810
	/* open the file and get the decoding format */
811
	if (mpg123_open(mh, file) != MPG123_OK)
812
	{
11 andreas 813
		syslog(LOG_DAEMON, "Error opening MP3 file %s: %s", file, mpg123_strerror(mh));
7 andreas 814
		free(buffer);
815
		mpg123_close(mh);
816
		mpg123_delete(mh);
817
		mpg123_exit();
818
		ao_shutdown();
819
		return;
820
	}
821
 
11 andreas 822
	if (mpg123_scan(mh) != MPG123_OK)
823
		syslog(LOG_WARNING, "Error scanning MP3 file %s: %s", file, mpg123_strerror(mh));
7 andreas 824
 
11 andreas 825
	if (mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK)
826
	{
827
		syslog(LOG_DAEMON, "Error getting the format of MP3 file %s: %s", file, mpg123_strerror(mh));
828
		free(buffer);
829
		mpg123_close(mh);
830
		mpg123_delete(mh);
831
		mpg123_exit();
832
		ao_shutdown();
833
		return;
834
	}
835
 
7 andreas 836
	/* set the output format and open the output device */
837
	format.bits = mpg123_encsize(encoding) * BITS;
838
	format.rate = rate;
839
	format.channels = channels;
840
	format.byte_format = AO_FMT_NATIVE;
841
	format.matrix = 0;
35 andreas 842
 
843
	if (configs.debug)
844
	{
845
		syslog(LOG_DEBUG, "Format: Bits:     %d", format.bits);
846
		syslog(LOG_DEBUG, "Format: Rate:     %ld", rate);
847
		syslog(LOG_DEBUG, "Format: Channels: %d", channels);
848
	}
849
 
34 andreas 850
	memset(&ao_opts, 0, sizeof(ao_option));
851
 
852
	if (configs.debug)
7 andreas 853
	{
34 andreas 854
		strcpy(hv0, "debug");
855
		ao_opts.key = strdup(hv0);
856
		strcpy(hv0, "1");
857
		ao_opts.value = strdup(hv0);
858
		dev = ao_open_live(driver, &format, &ao_opts);
859
		syslog(LOG_DEBUG, "Switching on debugging for AO library.");
54 andreas 860
		syslog(LOG_DEBUG, "AO library opened.");
34 andreas 861
	}
862
	else
863
		dev = ao_open_live(driver, &format, NULL);
864
 
865
	if (dev == NULL)
866
	{
35 andreas 867
		switch (errno)
868
		{
869
			case AO_ENODRIVER:	sprintf(hv0, "No driver corresponds to \"driver_id\"."); break;
870
			case AO_ENOTLIVE:	sprintf(hv0, "This driver (%s) is not a live output device.", configs.player); break;
871
			case AO_EBADOPTION:	sprintf(hv0, "A valid option key has an invalid value."); break;
872
			case AO_EOPENDEVICE:sprintf(hv0, "Cannot open the device."); break;
873
			default:
874
				sprintf(hv0, "%s", strerror(errno));
875
		}
876
 
877
		syslog(LOG_DAEMON, "Error opening live playback device: %s", hv0);
7 andreas 878
		free(buffer);
879
		mpg123_close(mh);
880
		mpg123_delete(mh);
881
		mpg123_exit();
882
		ao_shutdown();
34 andreas 883
 
884
		if (configs.debug)
885
		{
886
			free(ao_opts.key);
887
			free(ao_opts.value);
888
		}
889
 
7 andreas 890
		return;
891
	}
892
 
50 andreas 893
	if (playStatus != PLAY_STATUS_STPLAY)
894
		playStatus = PLAY_STATUS_PLAY;
895
 
56 andreas 896
/*	strcpy (hv0, "PLAYER:PLAY;");
897
	write(s1, hv0, strlen(hv0)); */
898
	handleWrite("PLAYER:PLAY;");
28 andreas 899
	act_sec = 0.0;
900
	flag = FALSE;
54 andreas 901
	current_seconds = seconds_left = 0;
902
	current_frame = frames_left = 0;
903
	nextCommand = PLAY_NONE;			/* Reset commands to be sure there is no lost command left */
28 andreas 904
	frame = mpg123_tellframe(mh);
54 andreas 905
 
7 andreas 906
	/* decode and play */
53 andreas 907
	while ((rc = mpg123_read(mh, buffer, buffer_size, &done)) == MPG123_OK)
7 andreas 908
	{
909
		int todo;
910
		char hv1[32], hv2[32], hv3[32];
911
 
912
		todo = check_command(s1);
913
 
914
		if (todo == PLAY_STATUS_STOP)
915
			break;
916
		else if (todo == PLAY_STATUS_FWD)
917
		{
918
			mpg123_seek_frame(mh, 100, SEEK_CUR);
50 andreas 919
 
920
			if (playStatus != PLAY_STATUS_STPLAY)
921
				playStatus = PLAY_STATUS_PLAY;
922
 
7 andreas 923
			continue;
924
		}
925
		else if (todo == PLAY_STATUS_REW)
926
		{
927
			off_t fr;
928
 
929
			fr =  mpg123_tellframe(mh);
930
 
931
			if (fr > 100)
932
				fr -= 100;
933
			else
934
				fr = 0;
935
 
936
			mpg123_seek_frame(mh, fr, SEEK_SET);
50 andreas 937
 
938
			if (playStatus != PLAY_STATUS_STPLAY)
939
				playStatus = PLAY_STATUS_PLAY;
940
 
7 andreas 941
			continue;
942
		}
943
 
944
		/* get position */
28 andreas 945
		if (!flag)
946
		{
947
			mpg123_position(mh, mpg123_tellframe(mh), done, &current_frame, &frames_left, &current_seconds, &seconds_left);
948
			act_sec = current_seconds;
949
			flag = TRUE;
950
		}
54 andreas 951
		else if (flag && frame != 0)
28 andreas 952
		{
953
			double cs, sl;
954
			mpg123_position(mh, frame, done, &current_frame, &frames_left, &cs, &sl);
29 andreas 955
			frame = mpg123_tellframe(mh) / 100;
28 andreas 956
			act_sec = cs;
957
		}
54 andreas 958
		else if (frame == 0)
959
			frame = mpg123_tellframe(mh) / 100;
28 andreas 960
 
55 andreas 961
		if (!playQuiet)
962
		{
963
			sprintf(hv0, "POSITION:%s:%s:%s;", secondsToString(act_sec, &hv1[0]), secondsToString((current_seconds + seconds_left) - act_sec, &hv2[0]), secondsToString(current_seconds + seconds_left, &hv3[0]));
56 andreas 964
/*			write(s1, hv0, strlen(hv0)); */
965
			handleWrite(hv0);
55 andreas 966
		}
967
 
7 andreas 968
		ao_play(dev, (char *)buffer, done);
969
	}
53 andreas 970
 
971
	if (configs.debug && rc != MPG123_OK)
54 andreas 972
		syslog(LOG_DEBUG, "MPG123 Error: %s", mpg123_plain_strerror(rc));
53 andreas 973
 
7 andreas 974
	/* clean up */
56 andreas 975
/*	strcpy(hv0, "PLAYER:STOP;");
976
	write (s1, hv0, strlen(hv0)); */
977
	handleWrite("PLAYER:STOP;");
7 andreas 978
 
979
	free(buffer);
980
	ao_close(dev);
981
	mpg123_close(mh);
982
	mpg123_delete(mh);
983
	mpg123_exit();
54 andreas 984
 
985
	if (configs.debug)
986
		syslog(LOG_DEBUG, "MPG123 closed");
987
 
7 andreas 988
	ao_shutdown();
34 andreas 989
 
990
	if (configs.debug)
991
	{
992
		free(ao_opts.key);
993
		free(ao_opts.value);
54 andreas 994
		syslog(LOG_DEBUG, "AO library closed.");
34 andreas 995
	}
6 andreas 996
}
997
 
7 andreas 998
int check_command(int s1)
6 andreas 999
{
56 andreas 1000
/*	char hv0[64]; */
6 andreas 1001
 
8 andreas 1002
	if (nextCommand == PLAY_STOP_NOW)
1003
	{
1004
		playStatus = PLAY_STATUS_STOP;
1005
		return playStatus;
1006
	}
1007
 
50 andreas 1008
	if (nextCommand == PLAY_STACK)
1009
	{
1010
		playStatus = PLAY_STATUS_STACK;
1011
		return PLAY_STATUS_STOP;
1012
	}
1013
 
7 andreas 1014
	if (nextCommand == PLAY_PLAY && (playStatus == PLAY_STATUS_FWD || playStatus == PLAY_STATUS_REW))
1015
	{
1016
		playStatus = PLAY_STATUS_PLAY;
1017
		return playStatus;
1018
	}
6 andreas 1019
 
7 andreas 1020
	if (nextCommand == PLAY_STOP && (playStatus == PLAY_STATUS_PLAY || playStatus == PLAY_STATUS_PAUSE))
1021
	{
1022
		nextCommand = PLAY_NONE;
1023
		playStatus = PLAY_STATUS_STOP;
1024
		return playStatus;
1025
	}
50 andreas 1026
	else if (nextCommand == PLAY_STOP && playStatus == PLAY_STATUS_STPLAY)
1027
	{
1028
		nextCommand = PLAY_NONE;
1029
		playStatus = PLAY_STATUS_PLAY;
1030
		return PLAY_STATUS_STOP;
1031
	}
6 andreas 1032
 
7 andreas 1033
	if ((nextCommand == PLAY_PAUSE || nextCommand == PLAY_PLAYPAUSE) && playStatus == PLAY_STATUS_PLAY)
6 andreas 1034
	{
7 andreas 1035
		nextCommand = PLAY_NONE;
1036
		playStatus = PLAY_STATUS_PAUSE;
56 andreas 1037
		handleWrite ("PLAYER:PAUSE;");
1038
/*		write (s1, hv0, strlen(hv0)); */
6 andreas 1039
 
7 andreas 1040
		while (nextCommand != PLAY_PLAY && nextCommand != PLAY_PLAYPAUSE)
1041
			sleep(1);
1042
 
1043
		playStatus = PLAY_STATUS_PLAY;
56 andreas 1044
		handleWrite ("PLAYER:PLAY;");
1045
/*		write (s1, hv0, strlen(hv0)); */
7 andreas 1046
		nextCommand = PLAY_NONE;
6 andreas 1047
	}
1048
 
7 andreas 1049
	if (nextCommand == PLAY_FWD)
1050
	{
1051
		nextCommand = PLAY_NONE;
1052
		playStatus = PLAY_STATUS_FWD;
1053
		return PLAY_STATUS_FWD;
1054
	}
1055
 
1056
	if (nextCommand == PLAY_REW)
1057
	{
1058
		nextCommand = PLAY_NONE;
1059
		playStatus = PLAY_STATUS_REW;
1060
		return PLAY_STATUS_REW;
1061
	}
1062
 
1063
	if (nextCommand == PLAY_SKIP_FWD)
1064
	{
1065
		nextCommand = PLAY_NONE;
1066
		playStatus = PLAY_STATUS_SKIPF;
1067
		return PLAY_STATUS_STOP;
1068
	}
1069
 
1070
	if (nextCommand == PLAY_SKIP_REW)
1071
	{
1072
		nextCommand = PLAY_NONE;
1073
		playStatus = PLAY_STATUS_SKIPR;
1074
		return PLAY_STATUS_STOP;
1075
	}
1076
 
1077
	return 0;
6 andreas 1078
}
1079
 
11 andreas 1080
int checkQueueDouble(int id)
6 andreas 1081
{
11 andreas 1082
	QUEUE *act;
7 andreas 1083
 
11 andreas 1084
	act = pqueue;
1085
 
1086
	while (act)
7 andreas 1087
	{
11 andreas 1088
		if (act->id == id)
1089
			return TRUE;
7 andreas 1090
 
11 andreas 1091
		act = act->next;
7 andreas 1092
	}
11 andreas 1093
 
7 andreas 1094
	return FALSE;
1095
}
1096
 
1097
void appendToQueue(int s1, char *type, char *what)
1098
{
1099
	char fname[256], query[1024];
1100
	int rc;
1101
	sqlite3 *db;
1102
	char *zErrMsg = 0;
6 andreas 1103
 
7 andreas 1104
	/* retrieve the data from the database */
1105
	strcpy(fname, configs.home);
9 andreas 1106
	strcat(fname, MUSICDB);
6 andreas 1107
 
7 andreas 1108
	rc = sqlite3_open(fname, &db);
6 andreas 1109
 
7 andreas 1110
	if (rc)
6 andreas 1111
	{
7 andreas 1112
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1113
		strcpy(query, "ERROR:PLAY:Error opening database;");
1114
		write (s1, query, strlen(query));
1115
		playerActive = FALSE;
1116
		return;
6 andreas 1117
	}
1118
 
40 andreas 1119
	strcpy (query, "select id, path, type, title, interpret, album, genre, cover from \"main\".\"musicdb\" where ");
6 andreas 1120
 
7 andreas 1121
	if (strcasecmp(type, "ID") == 0)
1122
	{
1123
		strcat(query, "id = ");
1124
		strcat(query, what);
1125
	}
1126
	else if (strcasecmp(type, "TITLE") == 0)
1127
	{
1128
		strcat(query, "title = \"");
1129
		strcat(query, what);
1130
		strcat(query, "\" order by title");
1131
	}
1132
	else if (strcasecmp(type, "ARTIST") == 0)
1133
	{
1134
		strcat(query, "interpret = \"");
1135
		strcat(query, what);
1136
		strcat(query, "\" order by interpret");
1137
	}
1138
	else if (strcasecmp(type, "ALBUM") == 0)
1139
	{
1140
		strcat(query, "album = \"");
1141
		strcat(query, what);
1142
		strcat(query, "\" order by album");
1143
	}
1144
	else if (strcasecmp(type, "GENRE") == 0)
1145
	{
1146
		strcat(query, "genre = \"");
1147
		strcat(query, what);
1148
		strcat(query, "\" order by genre");
1149
	}
8 andreas 1150
	else if (strcasecmp(type, "PLAYLIST") == 0)
1151
	{
1152
		USERS *act;
6 andreas 1153
 
8 andreas 1154
		sqlite3_close(db);
1155
		act = userchain;
1156
 
1157
		while (act)
1158
		{
1159
			if (strcmp(act->playlist, what) == 0)
1160
			{
1161
				playlistToQueue(act->id, FALSE);
1162
				break;
1163
			}
1164
 
1165
			act = act->next;
1166
		}
1167
 
1168
		if (act == NULL)
1169
		{
1170
			strcpy(query, "ERROR:PLAY:Error transfering playlist entries to queue;");
1171
			write (s1, query, strlen(query));
1172
		}
1173
 
1174
		return;
1175
	}
1176
 
7 andreas 1177
	if ((rc = sqlite3_exec(db, query, playCallback, (void *)what, &zErrMsg)) != SQLITE_OK)
6 andreas 1178
	{
7 andreas 1179
		syslog(LOG_WARNING, "SQL error [%s]: %s", query, zErrMsg);
1180
		sqlite3_free(zErrMsg);
1181
		sqlite3_close(db);
1182
		strcpy(query, "ERROR:PLAY:SQL error;");
1183
		write (s1, query, strlen(query));
6 andreas 1184
	}
18 andreas 1185
 
28 andreas 1186
	readQueue();
8 andreas 1187
}
1188
 
32 andreas 1189
QUEUE *addToQueue(int id, char *path, int fType, char *title, char *artist, char *album, char *genre, char *cover)
11 andreas 1190
{
1191
	QUEUE *act, *neu;
1192
	/* find the end of the chain */
1193
	act = pqueue;
1194
 
1195
	while (act && act->next)
1196
	{
1197
		if (act->id == id)			/* If the ID is already in the chain, return the pointer to it */
1198
			return act;
1199
 
1200
		act = act->next;
1201
	}
1202
	/* Allocate memory for a new element in the chain */
1203
	if ((neu = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1204
	{
1205
		syslog(LOG_DAEMON, "Error allocating %lu bytes for an entry in the queue: %s", sizeof(QUEUE), strerror(errno));
1206
		return NULL;
1207
	}
1208
 
1209
	memset(neu, 0, sizeof(QUEUE));
1210
	/* Copy the data into the new element */
1211
	neu->id = id;
32 andreas 1212
	neu->fType = fType;
11 andreas 1213
 
1214
	if (path)
1215
		strncpy (neu->path, path, sizeof(neu->path)-1);
1216
 
1217
	if (title)
1218
		strncpy (neu->title, title, sizeof(neu->title)-1);
1219
 
1220
	if (artist)
1221
		strncpy (neu->artist, artist, sizeof(neu->artist)-1);
1222
 
1223
	if (album)
1224
		strncpy (neu->album, album, sizeof(neu->album)-1);
1225
 
1226
	if (genre)
1227
		strncpy (neu->genre, genre, sizeof(neu->genre)-1);
1228
 
1229
	if (cover)
1230
		strncpy (neu->cover, cover, sizeof(neu->cover)-1);
1231
	/* Append the element to the end of the chain */
1232
	if (act == NULL)
1233
		act = pqueue = neu;
1234
	else
1235
		act->next = neu;
1236
 
1237
	return neu;
1238
}
1239
 
8 andreas 1240
/*
1241
 * This function copies the content of a playlist into the queue.
1242
 * The parameter defines whether the current queue should be deleted or not.
1243
 * If the queue should not be deleted, the playlist will be appended.
1244
 */
1245
int playlistToQueue(int uid, int del)
1246
{
1247
	char fname[256], query[1024], hv0[256], buffer[8192];
1248
	int rc;
1249
	sqlite3 *db;
1250
	sqlite3_stmt *res;
1251
	char path[512], id3_title[256], id3_artist[256], id3_album[256], id3_genre[256];
32 andreas 1252
	int id, fd, fType;
8 andreas 1253
	unsigned int mode;
1254
 
1255
	strcpy(fname, configs.home);
9 andreas 1256
	strcat(fname, MUSICDB);
8 andreas 1257
 
1258
	rc = sqlite3_open(fname, &db);
1259
 
1260
	if (rc)
1261
	{
1262
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1263
		return FALSE;
1264
	}
1265
 
32 andreas 1266
	strcpy (query, "select id, path, type, title, interpret, album, genre from \"main\".\"musicdb\" as a where ");
8 andreas 1267
	strcat (query, "(select musicid from \"main\".\"playlists\"  as b where a.id = b.musicid and b.userid = ");
1268
	sprintf(hv0, "%d", uid);
1269
	strcat (query, hv0);
1270
	strcat (query, ")");
1271
 
1272
	if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
1273
	{
1274
		syslog(LOG_DAEMON, "Error preparing SQL statement [%s]: %s", query, sqlite3_errmsg(db));
1275
		sqlite3_close(db);
1276
		return FALSE;
1277
	}
1278
 
1279
	/* Open the queue */
1280
	strcpy(fname, configs.home);
1281
	strcat(fname, NOWPLAY);
1282
 
1283
	if (!del)
1284
		mode = O_RDWR | O_APPEND | O_CREAT;
1285
	else
48 andreas 1286
	{
8 andreas 1287
		mode = O_RDWR | O_TRUNC | O_CREAT;
1288
 
48 andreas 1289
		if (playerActive)
1290
			nextCommand = PLAY_STOP_NOW;
1291
	}
1292
 
8 andreas 1293
	if ((fd = open(fname, mode, S_IWUSR | S_IRUSR | S_IRGRP)) <= 0)
1294
	{
1295
		syslog(LOG_WARNING, "Error opening file %s: %s", fname, strerror(errno));
9 andreas 1296
		sqlite3_finalize(res);
8 andreas 1297
		sqlite3_close(db);
1298
		return FALSE;
1299
	}
1300
 
1301
	while ((rc = sqlite3_step(res)) == SQLITE_ROW)
1302
	{
1303
		memset(path, 0, sizeof(path));
1304
		memset(id3_title, 0, sizeof(id3_title));
1305
		memset(id3_artist, 0, sizeof(id3_artist));
1306
		memset(id3_album, 0, sizeof(id3_album));
1307
		memset(id3_genre, 0, sizeof(id3_genre));
1308
		id = sqlite3_column_int(res, 0);
1309
		strncpy(path, (const char *)sqlite3_column_text(res, 1), sizeof(path));
32 andreas 1310
		fType = sqlite3_column_int(res, 2);
1311
		strncpy(id3_title, (const char *)sqlite3_column_text(res, 3), sizeof(id3_title));
1312
		strncpy(id3_artist, (const char *)sqlite3_column_text(res, 4), sizeof(id3_artist));
1313
		strncpy(id3_album, (const char *)sqlite3_column_text(res, 5), sizeof(id3_album));
1314
		strncpy(id3_genre, (const char *)sqlite3_column_text(res, 6), sizeof(id3_genre));
39 andreas 1315
		sprintf (buffer, "%s\t%d\t%d\t%s\t%s\t%s\t%s\n", path, fType, id, id3_title, id3_artist, id3_album, id3_genre);
8 andreas 1316
		write (fd, buffer, strlen(buffer));
1317
	}
1318
 
11 andreas 1319
	scanQueue(fd);
8 andreas 1320
	close(fd);
9 andreas 1321
	sqlite3_finalize(res);
8 andreas 1322
	sqlite3_close(db);
1323
	return TRUE;
1324
}
1325
 
1326
int QueueToPlaylist(int s1, char *user, char *playlist)
1327
{
11 andreas 1328
	char fname[256], query[1024], hv0[256];
8 andreas 1329
	int rc;
1330
	sqlite3 *db;
1331
	char *zErrMsg = 0;
1332
	sqlite3_stmt *res;
29 andreas 1333
	int num;
8 andreas 1334
	USERS *usp;
11 andreas 1335
	QUEUE *act;
29 andreas 1336
 
8 andreas 1337
	strcpy(fname, configs.home);
9 andreas 1338
	strcat(fname, MUSICDB);
8 andreas 1339
 
1340
	rc = sqlite3_open(fname, &db);
1341
 
1342
	if (rc)
1343
	{
1344
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1345
		return FALSE;
1346
	}
1347
 
14 andreas 1348
	if ((usp = findPlaylist(user, playlist)) != NULL)
8 andreas 1349
	{
1350
		sprintf(query, "delete from playlists where userid = %d", usp->id);
1351
 
1352
		if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
1353
		{
1354
			syslog(LOG_DAEMON, "Error preparing SQL statement [%s]: %s", query, sqlite3_errmsg(db));
1355
			sqlite3_close(db);
1356
			return FALSE;
1357
		}
1358
 
1359
		sqlite3_step(res);
1360
	}
29 andreas 1361
	else if (createUser(s1, user, playlist))
8 andreas 1362
	{
29 andreas 1363
		if ((usp = findPlaylist(user, playlist)) == NULL)
1364
			return FALSE;
1365
	}
1366
	else
8 andreas 1367
		return FALSE;
29 andreas 1368
 
1369
	/* Update the queue in case there is none in memory*/
11 andreas 1370
	if (pqueue == NULL)
29 andreas 1371
		readQueue();
11 andreas 1372
 
1373
	act = pqueue;
8 andreas 1374
	num = 0;
1375
 
11 andreas 1376
	while (act)
8 andreas 1377
	{
1378
		strcpy (query, "insert into playlists (userid, musicid) values (");
29 andreas 1379
		sprintf(hv0, "%d", usp->id);
8 andreas 1380
		strcat (query, hv0);
1381
		strcat (query, ",");
11 andreas 1382
		sprintf(hv0, "%d", act->id);
8 andreas 1383
		strcat (query, hv0);
1384
		strcat (query, ")");
1385
 
1386
		if ((rc = sqlite3_exec(db, query, NULL, NULL, &zErrMsg)) != SQLITE_OK)
1387
		{
1388
			syslog(LOG_WARNING, "SQL error [%s]: %s", query, zErrMsg);
1389
			sqlite3_free(zErrMsg);
1390
			sqlite3_close(db);
1391
			return FALSE;
1392
		}
11 andreas 1393
 
1394
		num++;
1395
		act = act->next;
8 andreas 1396
	}
11 andreas 1397
 
8 andreas 1398
	sqlite3_close(db);
1399
	sprintf(hv0, "TRANSFERED:%d;", num);
1400
	write (s1, hv0, strlen(hv0));
1401
	return TRUE;
1402
}
11 andreas 1403
 
1404
void freeQueue()
1405
{
1406
	QUEUE *act;
1407
 
1408
	act = pqueue;
1409
 
1410
	while (act)
1411
	{
1412
		pqueue = act->next;
1413
		free (act);
1414
		act = pqueue;
1415
	}
1416
 
1417
	pqueue = NULL;
1418
	queueTotal = 0;
1419
}
1420
 
25 andreas 1421
int readQueue()
1422
{
1423
	int fd;
1424
	char fname[256];
1425
 
1426
	strcpy (fname, configs.home);
1427
	strcat (fname, NOWPLAY);
1428
	/* start the player and play the file(s) */
1429
	if (!access(fname, R_OK))
1430
	{
1431
		if ((fd = open(fname, O_RDONLY)) < 0)
1432
		{
1433
			syslog(LOG_WARNING, "Error opening file %s: %s", fname, strerror(errno));
1434
			return FALSE;
1435
		}
1436
 
1437
		scanQueue(fd);
1438
		close(fd);
1439
	}
1440
	else
1441
		return FALSE;
1442
 
1443
	return TRUE;
1444
}
1445
 
11 andreas 1446
int scanQueue(int fd)
1447
{
1448
	QUEUE *act;
1449
	int count, x;
1450
	char buffer[8192], *t;
1451
 
1452
	if (pqueue != NULL)
1453
		freeQueue();
1454
 
1455
	count = 0;
1456
	lseek (fd, 0L, SEEK_SET);
1457
 
1458
	while (readLine (fd, buffer, sizeof(buffer)) != NULL)
1459
	{
1460
		QUEUE *new;
1461
 
1462
		if ((new = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1463
		{
1464
			syslog(LOG_DAEMON, "Error allocating %lu bytes of memory: %s", sizeof(QUEUE), strerror(errno));
1465
			lseek(fd, 0L, SEEK_SET);
1466
			return -1;
1467
		}
1468
 
1469
		memset(new, 0, sizeof(QUEUE));
1470
 
1471
		if (count > 0)
1472
			act->next = new;
1473
		else
1474
			pqueue = new;
1475
 
1476
		act = new;
1477
		x = 0;
30 andreas 1478
		t = strsplitt(buffer, '\t');
11 andreas 1479
 
1480
		while (t)
1481
		{
1482
			switch (x)
1483
			{
30 andreas 1484
				case 0: strncpy(act->path, t, sizeof(act->path)-1); break;
32 andreas 1485
				case 1: act->fType = atoi(t); break;
1486
				case 2: act->id = atoi(t); break;
1487
				case 3: strncpy(act->title, t, sizeof(act->title)-1); break;
1488
				case 4: strncpy(act->artist, t, sizeof(act->artist)-1); break;
1489
				case 5: strncpy(act->album, t, sizeof(act->album)-1); break;
1490
				case 6: strncpy(act->genre, t, sizeof(act->genre)-1); break;
1491
				case 7: strncpy(act->cover, t, sizeof(act->cover)-1); break;
11 andreas 1492
			}
1493
 
30 andreas 1494
			t = strsplitt(NULL, '\t');
11 andreas 1495
			x++;
1496
		}
1497
 
1498
		count++;
1499
	}
1500
 
1501
	queueTotal = count;
1502
	return count;
1503
}
1504
 
1505
void setCurrentQueue(QUEUE *q)
1506
{
1507
	if (q == NULL)
1508
		return;
1509
 
1510
	memset(&playCurrent, 0, sizeof(ST_PLAYING));
1511
	playCurrent.id = q->id;
1512
	strncpy (playCurrent.title, q->title, sizeof(playCurrent.title));
1513
	strncpy (playCurrent.artist, q->artist, sizeof(playCurrent.artist));
1514
	strncpy (playCurrent.album, q->album, sizeof(playCurrent.album));
1515
	strncpy (playCurrent.genre, q->genre, sizeof(playCurrent.genre));
1516
	strncpy (playCurrent.cover, q->cover, sizeof(playCurrent.cover));
1517
}
1518
 
1519
QUEUE *getQueue(int idx)
1520
{
1521
	QUEUE *act;
1522
	int pos;
1523
 
1524
	act = pqueue;
1525
	pos = 0;
1526
 
1527
	while (act)
1528
	{
1529
		if (pos == idx)
1530
			return act;
1531
 
1532
		pos++;
1533
		act = act->next;
1534
	}
1535
 
1536
	return NULL;
1537
}
1538
 
1539
QUEUE *getRandomQueue()
1540
{
1541
	QUEUE *act;
1542
	int pos;
1543
	long r;
1544
 
1545
	if (pqueue == NULL)
1546
		return NULL;
1547
 
1548
	if (queueTotal > 1)
1549
		r = random_at_most((long)queueTotal-1);
1550
	else
1551
	{
1552
		if (pqueue->played)
1553
			return pqueue->next;
1554
		else
1555
			return pqueue;
1556
	}
1557
 
1558
	pos = 0;
1559
	act = pqueue;
1560
	/* Scan queue and check wheter all entries are allready played */
1561
	while (act)
1562
	{
1563
		if (!act->played)
1564
			break;
1565
 
1566
		act = act->next;
1567
	}
1568
 
1569
	if (act == NULL)		/* If all is played, we reset the status and start again */
1570
	{
1571
		act = pqueue;
1572
 
1573
		while (act)
1574
		{
1575
			act->played = FALSE;
1576
			act = act->next;
1577
		}
1578
	}
1579
 
1580
	act = pqueue;
1581
 
1582
	while (act)
1583
	{
1584
		if (pos == r)				/* have we reached the random position? */
1585
		{							/* Yes, then check if this entry was already played. */
1586
			if (act->played)		/* Was it played? */
1587
			{						/* Yes, then reset and try again */
1588
				r = random_at_most((long)queueTotal - 1);
1589
				act = pqueue;
1590
				pos = 0;
1591
				continue;
1592
			}
1593
			else					/* It was not played before so */
1594
				return act;			/* return the pointer to it */
1595
		}
1596
 
1597
		pos++;
1598
		act = act->next;
1599
	}
1600
 
1601
	return NULL;
50 andreas 1602
}
1603
 
1604
/*
1605
 * The following functions manage the STACK.
1606
 * The stack contains one or more files to play immediately. Even if a file
1607
 * of the normal queue is playing, the song is interrupted and the stack
1608
 * takes precedence. After the stack has been played or stopped by the user,
1609
 * the queue continues to play.
1610
 * 
1611
 * Adding a file to the stack does not alter the queue in any way. The stack
1612
 * is a kind of second queue but with higher priority.
1613
 */
1614
QUEUE* qstackAdd(int ID)
1615
{
1616
QUEUE *q;
1617
char query[1024], hv0[64], fname[512];
1618
char *p;
1619
sqlite3_stmt *res;
1620
sqlite3 *db;
1621
int rc;
1622
 
1623
	if (ID < 0)
1624
		return NULL;
1625
 
1626
	if ((q = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1627
	{
1628
		syslog(LOG_DAEMON, "Error allocating memory for a stack entry: %s", strerror(errno));
1629
		return NULL;
1630
	}
1631
 
1632
	memset(q, 0, sizeof(QUEUE));
1633
	q->id = ID;
1634
 
1635
	if (qstack)
1636
	{
1637
		QUEUE *act;
1638
 
1639
		act = qstack;
1640
 
1641
		while (act->next)
1642
			act = act->next;
1643
 
1644
		act->next = q;
1645
	}
1646
	else
1647
		qstack = q;
1648
 
1649
	/* retrieve the data from the database */
1650
	strcpy(fname, configs.home);			/* Base file name */
1651
	strcat(fname, MUSICDB);					/* File name of database */
1652
	rc = sqlite3_open(fname, &db);
1653
 
1654
	if (rc)
1655
	{
1656
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1657
		qstackDelete(ID);
1658
		return NULL;
1659
	}
1660
 
1661
	strcpy (query, "select id, path, type, title, interpret, album, genre, cover from \"main\".\"musicdb\" where ");
1662
	strcat(query, "id = ");
1663
	sprintf(hv0, "%d", ID);
1664
	strcat(query, hv0);
1665
 
1666
	if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
1667
	{
1668
		syslog(LOG_WARNING, "SQL error [%s]: %s", query, sqlite3_errmsg(db));
1669
		sqlite3_close(db);
1670
		qstackDelete(ID);
1671
		return NULL;
1672
	}
1673
 
1674
	rc = sqlite3_step(res);
1675
 
1676
	if ((p = (char *)sqlite3_column_text(res, 1)) == NULL)
1677
	{
1678
		syslog(LOG_WARNING, "Error getting path from database!");
1679
		sqlite3_finalize(res);
1680
		sqlite3_close(db);
1681
		qstackDelete(ID);
1682
		return NULL;
1683
	}
1684
	else
1685
		strncpy(q->path, p, sizeof(q->path));
1686
 
1687
	q->fType = sqlite3_column_int(res, 2);
1688
 
1689
	if ((p = (char *)sqlite3_column_text(res, 3)) == NULL)
1690
	{
1691
		syslog(LOG_WARNING, "Error getting title from database!");
1692
		sqlite3_finalize(res);
1693
		sqlite3_close(db);
1694
		qstackDelete(ID);
1695
		return NULL;
1696
	}
1697
	else
1698
		strncpy(q->title, p, sizeof(q->title));
1699
 
1700
	if ((p = (char *)sqlite3_column_text(res, 4)) == NULL)
1701
	{
1702
		syslog(LOG_WARNING, "Error getting artist from database!");
1703
		sqlite3_finalize(res);
1704
		sqlite3_close(db);
1705
		qstackDelete(ID);
1706
		return NULL;
1707
	}
1708
	else
1709
		strncpy(q->artist, p, sizeof(q->artist));
1710
 
1711
	if ((p = (char *)sqlite3_column_text(res, 5)) == NULL)
1712
	{
1713
		syslog(LOG_WARNING, "Error getting album from database!");
1714
		sqlite3_finalize(res);
1715
		sqlite3_close(db);
1716
		qstackDelete(ID);
1717
		return NULL;
1718
	}
1719
	else
1720
		strncpy(q->album, p, sizeof(q->album));
1721
 
1722
	if ((p = (char *)sqlite3_column_text(res, 6)) == NULL)
1723
	{
1724
		syslog(LOG_WARNING, "Error getting genre from database!");
1725
		sqlite3_finalize(res);
1726
		sqlite3_close(db);
1727
		qstackDelete(ID);
1728
		return NULL;
1729
	}
1730
	else
1731
		strncpy(q->genre, p, sizeof(q->genre));
1732
 
1733
	if ((p = (char *)sqlite3_column_text(res, 7)) != NULL)
1734
		strncpy(q->cover, p, sizeof(q->cover));
1735
 
1736
	sqlite3_finalize(res);
1737
	sqlite3_close(db);
1738
 
1739
	if (configs.debug)
1740
		syslog(LOG_DEBUG, "qstackAdd(): Added file >>%d:%s<< to stack.", q->id, q->path);
1741
 
1742
	return q;
1743
}
1744
 
1745
void qstackDelete(int ID)
1746
{
1747
QUEUE *q, *p;
1748
int flag;
1749
 
1750
	if (qstack == NULL)
1751
		return;
1752
 
1753
	q = p = qstack;
1754
	flag = 0;
1755
 
1756
	while (q)
1757
	{
1758
		QUEUE *act;
1759
 
1760
		if (q->id == ID)
1761
		{
1762
			act = q;
1763
			q = q->next;
1764
 
1765
			if (p != act)
1766
				p->next = q;
1767
			else
1768
				qstack = q;			/* if the the first entry is to delete, let qstack point to the second entry, if there is one. */
1769
 
1770
			free(q);
1771
 
1772
			if (configs.debug)
1773
				syslog(LOG_DEBUG, "qstackDelete(): Deleted ID %d from stack.", ID);
1774
 
1775
			return;
1776
		}
1777
 
1778
		q = q->next;
1779
 
1780
		if (flag)
1781
			p = p->next;
1782
		else
1783
			flag = 1;
1784
	}
1785
}
1786
 
1787
void qstackClear()
1788
{
1789
QUEUE *act, *q;
1790
 
1791
	act = qstack;
1792
 
1793
	while (act)
1794
	{
1795
		q = act->next;
1796
		free(act);
1797
		act = q;
1798
	}
1799
 
1800
	qstack = NULL;
1801
}
1802
 
1803
QUEUE* qstackNext()
1804
{
1805
QUEUE *act, *p;
1806
int flag;
1807
 
1808
	if (qstack == NULL)
1809
		return NULL;
1810
 
1811
	act = p = qstack;
1812
	flag = 0;
1813
 
1814
	while (act->next)
1815
	{
1816
		if (flag)
1817
			p = p->next;
1818
		else
1819
			flag = 1;
1820
 
1821
		act = act->next;
1822
	}
1823
 
1824
	if (act != p)
1825
		p->next = NULL;
1826
	else
1827
		qstack = NULL;
1828
 
1829
	if ((p = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1830
	{
1831
		syslog(LOG_DAEMON, "Error allocating memory to get a stack entry: %s", strerror(errno));
1832
		free(act);
1833
		return NULL;
1834
	}
1835
 
1836
	if (configs.debug)
1837
		syslog(LOG_DEBUG, "qstackNext(): Pulled file >>%d:%s<< from stack.", act->id, act->path);
1838
 
1839
	memmove(p, act, sizeof(QUEUE));
1840
	free(act);
1841
	return p;
1842
}