Subversion Repositories mdb

Rev

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