Subversion Repositories mdb

Rev

Rev 55 | Rev 57 | 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
 
56 andreas 392
		if (strlen(cover) != 0)
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
 
56 andreas 878
/*	strcpy (hv0, "PLAYER:PLAY;");
879
	write(s1, hv0, strlen(hv0)); */
880
	handleWrite("PLAYER:PLAY;");
28 andreas 881
	act_sec = 0.0;
882
	flag = FALSE;
54 andreas 883
	current_seconds = seconds_left = 0;
884
	current_frame = frames_left = 0;
885
	nextCommand = PLAY_NONE;			/* Reset commands to be sure there is no lost command left */
28 andreas 886
	frame = mpg123_tellframe(mh);
54 andreas 887
 
7 andreas 888
	/* decode and play */
53 andreas 889
	while ((rc = mpg123_read(mh, buffer, buffer_size, &done)) == MPG123_OK)
7 andreas 890
	{
891
		int todo;
892
		char hv1[32], hv2[32], hv3[32];
893
 
894
		todo = check_command(s1);
895
 
896
		if (todo == PLAY_STATUS_STOP)
897
			break;
898
		else if (todo == PLAY_STATUS_FWD)
899
		{
900
			mpg123_seek_frame(mh, 100, SEEK_CUR);
50 andreas 901
 
902
			if (playStatus != PLAY_STATUS_STPLAY)
903
				playStatus = PLAY_STATUS_PLAY;
904
 
7 andreas 905
			continue;
906
		}
907
		else if (todo == PLAY_STATUS_REW)
908
		{
909
			off_t fr;
910
 
911
			fr =  mpg123_tellframe(mh);
912
 
913
			if (fr > 100)
914
				fr -= 100;
915
			else
916
				fr = 0;
917
 
918
			mpg123_seek_frame(mh, fr, SEEK_SET);
50 andreas 919
 
920
			if (playStatus != PLAY_STATUS_STPLAY)
921
				playStatus = PLAY_STATUS_PLAY;
922
 
7 andreas 923
			continue;
924
		}
925
 
926
		/* get position */
28 andreas 927
		if (!flag)
928
		{
929
			mpg123_position(mh, mpg123_tellframe(mh), done, &current_frame, &frames_left, &current_seconds, &seconds_left);
930
			act_sec = current_seconds;
931
			flag = TRUE;
932
		}
54 andreas 933
		else if (flag && frame != 0)
28 andreas 934
		{
935
			double cs, sl;
936
			mpg123_position(mh, frame, done, &current_frame, &frames_left, &cs, &sl);
29 andreas 937
			frame = mpg123_tellframe(mh) / 100;
28 andreas 938
			act_sec = cs;
939
		}
54 andreas 940
		else if (frame == 0)
941
			frame = mpg123_tellframe(mh) / 100;
28 andreas 942
 
55 andreas 943
		if (!playQuiet)
944
		{
945
			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 946
/*			write(s1, hv0, strlen(hv0)); */
947
			handleWrite(hv0);
55 andreas 948
		}
949
 
7 andreas 950
		ao_play(dev, (char *)buffer, done);
951
	}
53 andreas 952
 
953
	if (configs.debug && rc != MPG123_OK)
54 andreas 954
		syslog(LOG_DEBUG, "MPG123 Error: %s", mpg123_plain_strerror(rc));
53 andreas 955
 
7 andreas 956
	/* clean up */
56 andreas 957
/*	strcpy(hv0, "PLAYER:STOP;");
958
	write (s1, hv0, strlen(hv0)); */
959
	handleWrite("PLAYER:STOP;");
7 andreas 960
 
961
	free(buffer);
962
	ao_close(dev);
963
	mpg123_close(mh);
964
	mpg123_delete(mh);
965
	mpg123_exit();
54 andreas 966
 
967
	if (configs.debug)
968
		syslog(LOG_DEBUG, "MPG123 closed");
969
 
7 andreas 970
	ao_shutdown();
34 andreas 971
 
972
	if (configs.debug)
973
	{
974
		free(ao_opts.key);
975
		free(ao_opts.value);
54 andreas 976
		syslog(LOG_DEBUG, "AO library closed.");
34 andreas 977
	}
6 andreas 978
}
979
 
7 andreas 980
int check_command(int s1)
6 andreas 981
{
56 andreas 982
/*	char hv0[64]; */
6 andreas 983
 
8 andreas 984
	if (nextCommand == PLAY_STOP_NOW)
985
	{
986
		playStatus = PLAY_STATUS_STOP;
987
		return playStatus;
988
	}
989
 
50 andreas 990
	if (nextCommand == PLAY_STACK)
991
	{
992
		playStatus = PLAY_STATUS_STACK;
993
		return PLAY_STATUS_STOP;
994
	}
995
 
7 andreas 996
	if (nextCommand == PLAY_PLAY && (playStatus == PLAY_STATUS_FWD || playStatus == PLAY_STATUS_REW))
997
	{
998
		playStatus = PLAY_STATUS_PLAY;
999
		return playStatus;
1000
	}
6 andreas 1001
 
7 andreas 1002
	if (nextCommand == PLAY_STOP && (playStatus == PLAY_STATUS_PLAY || playStatus == PLAY_STATUS_PAUSE))
1003
	{
1004
		nextCommand = PLAY_NONE;
1005
		playStatus = PLAY_STATUS_STOP;
1006
		return playStatus;
1007
	}
50 andreas 1008
	else if (nextCommand == PLAY_STOP && playStatus == PLAY_STATUS_STPLAY)
1009
	{
1010
		nextCommand = PLAY_NONE;
1011
		playStatus = PLAY_STATUS_PLAY;
1012
		return PLAY_STATUS_STOP;
1013
	}
6 andreas 1014
 
7 andreas 1015
	if ((nextCommand == PLAY_PAUSE || nextCommand == PLAY_PLAYPAUSE) && playStatus == PLAY_STATUS_PLAY)
6 andreas 1016
	{
7 andreas 1017
		nextCommand = PLAY_NONE;
1018
		playStatus = PLAY_STATUS_PAUSE;
56 andreas 1019
		handleWrite ("PLAYER:PAUSE;");
1020
/*		write (s1, hv0, strlen(hv0)); */
6 andreas 1021
 
7 andreas 1022
		while (nextCommand != PLAY_PLAY && nextCommand != PLAY_PLAYPAUSE)
1023
			sleep(1);
1024
 
1025
		playStatus = PLAY_STATUS_PLAY;
56 andreas 1026
		handleWrite ("PLAYER:PLAY;");
1027
/*		write (s1, hv0, strlen(hv0)); */
7 andreas 1028
		nextCommand = PLAY_NONE;
6 andreas 1029
	}
1030
 
7 andreas 1031
	if (nextCommand == PLAY_FWD)
1032
	{
1033
		nextCommand = PLAY_NONE;
1034
		playStatus = PLAY_STATUS_FWD;
1035
		return PLAY_STATUS_FWD;
1036
	}
1037
 
1038
	if (nextCommand == PLAY_REW)
1039
	{
1040
		nextCommand = PLAY_NONE;
1041
		playStatus = PLAY_STATUS_REW;
1042
		return PLAY_STATUS_REW;
1043
	}
1044
 
1045
	if (nextCommand == PLAY_SKIP_FWD)
1046
	{
1047
		nextCommand = PLAY_NONE;
1048
		playStatus = PLAY_STATUS_SKIPF;
1049
		return PLAY_STATUS_STOP;
1050
	}
1051
 
1052
	if (nextCommand == PLAY_SKIP_REW)
1053
	{
1054
		nextCommand = PLAY_NONE;
1055
		playStatus = PLAY_STATUS_SKIPR;
1056
		return PLAY_STATUS_STOP;
1057
	}
1058
 
1059
	return 0;
6 andreas 1060
}
1061
 
11 andreas 1062
int checkQueueDouble(int id)
6 andreas 1063
{
11 andreas 1064
	QUEUE *act;
7 andreas 1065
 
11 andreas 1066
	act = pqueue;
1067
 
1068
	while (act)
7 andreas 1069
	{
11 andreas 1070
		if (act->id == id)
1071
			return TRUE;
7 andreas 1072
 
11 andreas 1073
		act = act->next;
7 andreas 1074
	}
11 andreas 1075
 
7 andreas 1076
	return FALSE;
1077
}
1078
 
1079
void appendToQueue(int s1, char *type, char *what)
1080
{
1081
	char fname[256], query[1024];
1082
	int rc;
1083
	sqlite3 *db;
1084
	char *zErrMsg = 0;
6 andreas 1085
 
7 andreas 1086
	/* retrieve the data from the database */
1087
	strcpy(fname, configs.home);
9 andreas 1088
	strcat(fname, MUSICDB);
6 andreas 1089
 
7 andreas 1090
	rc = sqlite3_open(fname, &db);
6 andreas 1091
 
7 andreas 1092
	if (rc)
6 andreas 1093
	{
7 andreas 1094
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1095
		strcpy(query, "ERROR:PLAY:Error opening database;");
1096
		write (s1, query, strlen(query));
1097
		playerActive = FALSE;
1098
		return;
6 andreas 1099
	}
1100
 
40 andreas 1101
	strcpy (query, "select id, path, type, title, interpret, album, genre, cover from \"main\".\"musicdb\" where ");
6 andreas 1102
 
7 andreas 1103
	if (strcasecmp(type, "ID") == 0)
1104
	{
1105
		strcat(query, "id = ");
1106
		strcat(query, what);
1107
	}
1108
	else if (strcasecmp(type, "TITLE") == 0)
1109
	{
1110
		strcat(query, "title = \"");
1111
		strcat(query, what);
1112
		strcat(query, "\" order by title");
1113
	}
1114
	else if (strcasecmp(type, "ARTIST") == 0)
1115
	{
1116
		strcat(query, "interpret = \"");
1117
		strcat(query, what);
1118
		strcat(query, "\" order by interpret");
1119
	}
1120
	else if (strcasecmp(type, "ALBUM") == 0)
1121
	{
1122
		strcat(query, "album = \"");
1123
		strcat(query, what);
1124
		strcat(query, "\" order by album");
1125
	}
1126
	else if (strcasecmp(type, "GENRE") == 0)
1127
	{
1128
		strcat(query, "genre = \"");
1129
		strcat(query, what);
1130
		strcat(query, "\" order by genre");
1131
	}
8 andreas 1132
	else if (strcasecmp(type, "PLAYLIST") == 0)
1133
	{
1134
		USERS *act;
6 andreas 1135
 
8 andreas 1136
		sqlite3_close(db);
1137
		act = userchain;
1138
 
1139
		while (act)
1140
		{
1141
			if (strcmp(act->playlist, what) == 0)
1142
			{
1143
				playlistToQueue(act->id, FALSE);
1144
				break;
1145
			}
1146
 
1147
			act = act->next;
1148
		}
1149
 
1150
		if (act == NULL)
1151
		{
1152
			strcpy(query, "ERROR:PLAY:Error transfering playlist entries to queue;");
1153
			write (s1, query, strlen(query));
1154
		}
1155
 
1156
		return;
1157
	}
1158
 
7 andreas 1159
	if ((rc = sqlite3_exec(db, query, playCallback, (void *)what, &zErrMsg)) != SQLITE_OK)
6 andreas 1160
	{
7 andreas 1161
		syslog(LOG_WARNING, "SQL error [%s]: %s", query, zErrMsg);
1162
		sqlite3_free(zErrMsg);
1163
		sqlite3_close(db);
1164
		strcpy(query, "ERROR:PLAY:SQL error;");
1165
		write (s1, query, strlen(query));
6 andreas 1166
	}
18 andreas 1167
 
28 andreas 1168
	readQueue();
8 andreas 1169
}
1170
 
32 andreas 1171
QUEUE *addToQueue(int id, char *path, int fType, char *title, char *artist, char *album, char *genre, char *cover)
11 andreas 1172
{
1173
	QUEUE *act, *neu;
1174
	/* find the end of the chain */
1175
	act = pqueue;
1176
 
1177
	while (act && act->next)
1178
	{
1179
		if (act->id == id)			/* If the ID is already in the chain, return the pointer to it */
1180
			return act;
1181
 
1182
		act = act->next;
1183
	}
1184
	/* Allocate memory for a new element in the chain */
1185
	if ((neu = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1186
	{
1187
		syslog(LOG_DAEMON, "Error allocating %lu bytes for an entry in the queue: %s", sizeof(QUEUE), strerror(errno));
1188
		return NULL;
1189
	}
1190
 
1191
	memset(neu, 0, sizeof(QUEUE));
1192
	/* Copy the data into the new element */
1193
	neu->id = id;
32 andreas 1194
	neu->fType = fType;
11 andreas 1195
 
1196
	if (path)
1197
		strncpy (neu->path, path, sizeof(neu->path)-1);
1198
 
1199
	if (title)
1200
		strncpy (neu->title, title, sizeof(neu->title)-1);
1201
 
1202
	if (artist)
1203
		strncpy (neu->artist, artist, sizeof(neu->artist)-1);
1204
 
1205
	if (album)
1206
		strncpy (neu->album, album, sizeof(neu->album)-1);
1207
 
1208
	if (genre)
1209
		strncpy (neu->genre, genre, sizeof(neu->genre)-1);
1210
 
1211
	if (cover)
1212
		strncpy (neu->cover, cover, sizeof(neu->cover)-1);
1213
	/* Append the element to the end of the chain */
1214
	if (act == NULL)
1215
		act = pqueue = neu;
1216
	else
1217
		act->next = neu;
1218
 
1219
	return neu;
1220
}
1221
 
8 andreas 1222
/*
1223
 * This function copies the content of a playlist into the queue.
1224
 * The parameter defines whether the current queue should be deleted or not.
1225
 * If the queue should not be deleted, the playlist will be appended.
1226
 */
1227
int playlistToQueue(int uid, int del)
1228
{
1229
	char fname[256], query[1024], hv0[256], buffer[8192];
1230
	int rc;
1231
	sqlite3 *db;
1232
	sqlite3_stmt *res;
1233
	char path[512], id3_title[256], id3_artist[256], id3_album[256], id3_genre[256];
32 andreas 1234
	int id, fd, fType;
8 andreas 1235
	unsigned int mode;
1236
 
1237
	strcpy(fname, configs.home);
9 andreas 1238
	strcat(fname, MUSICDB);
8 andreas 1239
 
1240
	rc = sqlite3_open(fname, &db);
1241
 
1242
	if (rc)
1243
	{
1244
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1245
		return FALSE;
1246
	}
1247
 
32 andreas 1248
	strcpy (query, "select id, path, type, title, interpret, album, genre from \"main\".\"musicdb\" as a where ");
8 andreas 1249
	strcat (query, "(select musicid from \"main\".\"playlists\"  as b where a.id = b.musicid and b.userid = ");
1250
	sprintf(hv0, "%d", uid);
1251
	strcat (query, hv0);
1252
	strcat (query, ")");
1253
 
1254
	if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
1255
	{
1256
		syslog(LOG_DAEMON, "Error preparing SQL statement [%s]: %s", query, sqlite3_errmsg(db));
1257
		sqlite3_close(db);
1258
		return FALSE;
1259
	}
1260
 
1261
	/* Open the queue */
1262
	strcpy(fname, configs.home);
1263
	strcat(fname, NOWPLAY);
1264
 
1265
	if (!del)
1266
		mode = O_RDWR | O_APPEND | O_CREAT;
1267
	else
48 andreas 1268
	{
8 andreas 1269
		mode = O_RDWR | O_TRUNC | O_CREAT;
1270
 
48 andreas 1271
		if (playerActive)
1272
			nextCommand = PLAY_STOP_NOW;
1273
	}
1274
 
8 andreas 1275
	if ((fd = open(fname, mode, S_IWUSR | S_IRUSR | S_IRGRP)) <= 0)
1276
	{
1277
		syslog(LOG_WARNING, "Error opening file %s: %s", fname, strerror(errno));
9 andreas 1278
		sqlite3_finalize(res);
8 andreas 1279
		sqlite3_close(db);
1280
		return FALSE;
1281
	}
1282
 
1283
	while ((rc = sqlite3_step(res)) == SQLITE_ROW)
1284
	{
1285
		memset(path, 0, sizeof(path));
1286
		memset(id3_title, 0, sizeof(id3_title));
1287
		memset(id3_artist, 0, sizeof(id3_artist));
1288
		memset(id3_album, 0, sizeof(id3_album));
1289
		memset(id3_genre, 0, sizeof(id3_genre));
1290
		id = sqlite3_column_int(res, 0);
1291
		strncpy(path, (const char *)sqlite3_column_text(res, 1), sizeof(path));
32 andreas 1292
		fType = sqlite3_column_int(res, 2);
1293
		strncpy(id3_title, (const char *)sqlite3_column_text(res, 3), sizeof(id3_title));
1294
		strncpy(id3_artist, (const char *)sqlite3_column_text(res, 4), sizeof(id3_artist));
1295
		strncpy(id3_album, (const char *)sqlite3_column_text(res, 5), sizeof(id3_album));
1296
		strncpy(id3_genre, (const char *)sqlite3_column_text(res, 6), sizeof(id3_genre));
39 andreas 1297
		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 1298
		write (fd, buffer, strlen(buffer));
1299
	}
1300
 
11 andreas 1301
	scanQueue(fd);
8 andreas 1302
	close(fd);
9 andreas 1303
	sqlite3_finalize(res);
8 andreas 1304
	sqlite3_close(db);
1305
	return TRUE;
1306
}
1307
 
1308
int QueueToPlaylist(int s1, char *user, char *playlist)
1309
{
11 andreas 1310
	char fname[256], query[1024], hv0[256];
8 andreas 1311
	int rc;
1312
	sqlite3 *db;
1313
	char *zErrMsg = 0;
1314
	sqlite3_stmt *res;
29 andreas 1315
	int num;
8 andreas 1316
	USERS *usp;
11 andreas 1317
	QUEUE *act;
29 andreas 1318
 
8 andreas 1319
	strcpy(fname, configs.home);
9 andreas 1320
	strcat(fname, MUSICDB);
8 andreas 1321
 
1322
	rc = sqlite3_open(fname, &db);
1323
 
1324
	if (rc)
1325
	{
1326
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1327
		return FALSE;
1328
	}
1329
 
14 andreas 1330
	if ((usp = findPlaylist(user, playlist)) != NULL)
8 andreas 1331
	{
1332
		sprintf(query, "delete from playlists where userid = %d", usp->id);
1333
 
1334
		if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
1335
		{
1336
			syslog(LOG_DAEMON, "Error preparing SQL statement [%s]: %s", query, sqlite3_errmsg(db));
1337
			sqlite3_close(db);
1338
			return FALSE;
1339
		}
1340
 
1341
		sqlite3_step(res);
1342
	}
29 andreas 1343
	else if (createUser(s1, user, playlist))
8 andreas 1344
	{
29 andreas 1345
		if ((usp = findPlaylist(user, playlist)) == NULL)
1346
			return FALSE;
1347
	}
1348
	else
8 andreas 1349
		return FALSE;
29 andreas 1350
 
1351
	/* Update the queue in case there is none in memory*/
11 andreas 1352
	if (pqueue == NULL)
29 andreas 1353
		readQueue();
11 andreas 1354
 
1355
	act = pqueue;
8 andreas 1356
	num = 0;
1357
 
11 andreas 1358
	while (act)
8 andreas 1359
	{
1360
		strcpy (query, "insert into playlists (userid, musicid) values (");
29 andreas 1361
		sprintf(hv0, "%d", usp->id);
8 andreas 1362
		strcat (query, hv0);
1363
		strcat (query, ",");
11 andreas 1364
		sprintf(hv0, "%d", act->id);
8 andreas 1365
		strcat (query, hv0);
1366
		strcat (query, ")");
1367
 
1368
		if ((rc = sqlite3_exec(db, query, NULL, NULL, &zErrMsg)) != SQLITE_OK)
1369
		{
1370
			syslog(LOG_WARNING, "SQL error [%s]: %s", query, zErrMsg);
1371
			sqlite3_free(zErrMsg);
1372
			sqlite3_close(db);
1373
			return FALSE;
1374
		}
11 andreas 1375
 
1376
		num++;
1377
		act = act->next;
8 andreas 1378
	}
11 andreas 1379
 
8 andreas 1380
	sqlite3_close(db);
1381
	sprintf(hv0, "TRANSFERED:%d;", num);
1382
	write (s1, hv0, strlen(hv0));
1383
	return TRUE;
1384
}
11 andreas 1385
 
1386
void freeQueue()
1387
{
1388
	QUEUE *act;
1389
 
1390
	act = pqueue;
1391
 
1392
	while (act)
1393
	{
1394
		pqueue = act->next;
1395
		free (act);
1396
		act = pqueue;
1397
	}
1398
 
1399
	pqueue = NULL;
1400
	queueTotal = 0;
1401
}
1402
 
25 andreas 1403
int readQueue()
1404
{
1405
	int fd;
1406
	char fname[256];
1407
 
1408
	strcpy (fname, configs.home);
1409
	strcat (fname, NOWPLAY);
1410
	/* start the player and play the file(s) */
1411
	if (!access(fname, R_OK))
1412
	{
1413
		if ((fd = open(fname, O_RDONLY)) < 0)
1414
		{
1415
			syslog(LOG_WARNING, "Error opening file %s: %s", fname, strerror(errno));
1416
			return FALSE;
1417
		}
1418
 
1419
		scanQueue(fd);
1420
		close(fd);
1421
	}
1422
	else
1423
		return FALSE;
1424
 
1425
	return TRUE;
1426
}
1427
 
11 andreas 1428
int scanQueue(int fd)
1429
{
1430
	QUEUE *act;
1431
	int count, x;
1432
	char buffer[8192], *t;
1433
 
1434
	if (pqueue != NULL)
1435
		freeQueue();
1436
 
1437
	count = 0;
1438
	lseek (fd, 0L, SEEK_SET);
1439
 
1440
	while (readLine (fd, buffer, sizeof(buffer)) != NULL)
1441
	{
1442
		QUEUE *new;
1443
 
1444
		if ((new = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1445
		{
1446
			syslog(LOG_DAEMON, "Error allocating %lu bytes of memory: %s", sizeof(QUEUE), strerror(errno));
1447
			lseek(fd, 0L, SEEK_SET);
1448
			return -1;
1449
		}
1450
 
1451
		memset(new, 0, sizeof(QUEUE));
1452
 
1453
		if (count > 0)
1454
			act->next = new;
1455
		else
1456
			pqueue = new;
1457
 
1458
		act = new;
1459
		x = 0;
30 andreas 1460
		t = strsplitt(buffer, '\t');
11 andreas 1461
 
1462
		while (t)
1463
		{
1464
			switch (x)
1465
			{
30 andreas 1466
				case 0: strncpy(act->path, t, sizeof(act->path)-1); break;
32 andreas 1467
				case 1: act->fType = atoi(t); break;
1468
				case 2: act->id = atoi(t); break;
1469
				case 3: strncpy(act->title, t, sizeof(act->title)-1); break;
1470
				case 4: strncpy(act->artist, t, sizeof(act->artist)-1); break;
1471
				case 5: strncpy(act->album, t, sizeof(act->album)-1); break;
1472
				case 6: strncpy(act->genre, t, sizeof(act->genre)-1); break;
1473
				case 7: strncpy(act->cover, t, sizeof(act->cover)-1); break;
11 andreas 1474
			}
1475
 
30 andreas 1476
			t = strsplitt(NULL, '\t');
11 andreas 1477
			x++;
1478
		}
1479
 
1480
		count++;
1481
	}
1482
 
1483
	queueTotal = count;
1484
	return count;
1485
}
1486
 
1487
void setCurrentQueue(QUEUE *q)
1488
{
1489
	if (q == NULL)
1490
		return;
1491
 
1492
	memset(&playCurrent, 0, sizeof(ST_PLAYING));
1493
	playCurrent.id = q->id;
1494
	strncpy (playCurrent.title, q->title, sizeof(playCurrent.title));
1495
	strncpy (playCurrent.artist, q->artist, sizeof(playCurrent.artist));
1496
	strncpy (playCurrent.album, q->album, sizeof(playCurrent.album));
1497
	strncpy (playCurrent.genre, q->genre, sizeof(playCurrent.genre));
1498
	strncpy (playCurrent.cover, q->cover, sizeof(playCurrent.cover));
1499
}
1500
 
1501
QUEUE *getQueue(int idx)
1502
{
1503
	QUEUE *act;
1504
	int pos;
1505
 
1506
	act = pqueue;
1507
	pos = 0;
1508
 
1509
	while (act)
1510
	{
1511
		if (pos == idx)
1512
			return act;
1513
 
1514
		pos++;
1515
		act = act->next;
1516
	}
1517
 
1518
	return NULL;
1519
}
1520
 
1521
QUEUE *getRandomQueue()
1522
{
1523
	QUEUE *act;
1524
	int pos;
1525
	long r;
1526
 
1527
	if (pqueue == NULL)
1528
		return NULL;
1529
 
1530
	if (queueTotal > 1)
1531
		r = random_at_most((long)queueTotal-1);
1532
	else
1533
	{
1534
		if (pqueue->played)
1535
			return pqueue->next;
1536
		else
1537
			return pqueue;
1538
	}
1539
 
1540
	pos = 0;
1541
	act = pqueue;
1542
	/* Scan queue and check wheter all entries are allready played */
1543
	while (act)
1544
	{
1545
		if (!act->played)
1546
			break;
1547
 
1548
		act = act->next;
1549
	}
1550
 
1551
	if (act == NULL)		/* If all is played, we reset the status and start again */
1552
	{
1553
		act = pqueue;
1554
 
1555
		while (act)
1556
		{
1557
			act->played = FALSE;
1558
			act = act->next;
1559
		}
1560
	}
1561
 
1562
	act = pqueue;
1563
 
1564
	while (act)
1565
	{
1566
		if (pos == r)				/* have we reached the random position? */
1567
		{							/* Yes, then check if this entry was already played. */
1568
			if (act->played)		/* Was it played? */
1569
			{						/* Yes, then reset and try again */
1570
				r = random_at_most((long)queueTotal - 1);
1571
				act = pqueue;
1572
				pos = 0;
1573
				continue;
1574
			}
1575
			else					/* It was not played before so */
1576
				return act;			/* return the pointer to it */
1577
		}
1578
 
1579
		pos++;
1580
		act = act->next;
1581
	}
1582
 
1583
	return NULL;
50 andreas 1584
}
1585
 
1586
/*
1587
 * The following functions manage the STACK.
1588
 * The stack contains one or more files to play immediately. Even if a file
1589
 * of the normal queue is playing, the song is interrupted and the stack
1590
 * takes precedence. After the stack has been played or stopped by the user,
1591
 * the queue continues to play.
1592
 * 
1593
 * Adding a file to the stack does not alter the queue in any way. The stack
1594
 * is a kind of second queue but with higher priority.
1595
 */
1596
QUEUE* qstackAdd(int ID)
1597
{
1598
QUEUE *q;
1599
char query[1024], hv0[64], fname[512];
1600
char *p;
1601
sqlite3_stmt *res;
1602
sqlite3 *db;
1603
int rc;
1604
 
1605
	if (ID < 0)
1606
		return NULL;
1607
 
1608
	if ((q = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1609
	{
1610
		syslog(LOG_DAEMON, "Error allocating memory for a stack entry: %s", strerror(errno));
1611
		return NULL;
1612
	}
1613
 
1614
	memset(q, 0, sizeof(QUEUE));
1615
	q->id = ID;
1616
 
1617
	if (qstack)
1618
	{
1619
		QUEUE *act;
1620
 
1621
		act = qstack;
1622
 
1623
		while (act->next)
1624
			act = act->next;
1625
 
1626
		act->next = q;
1627
	}
1628
	else
1629
		qstack = q;
1630
 
1631
	/* retrieve the data from the database */
1632
	strcpy(fname, configs.home);			/* Base file name */
1633
	strcat(fname, MUSICDB);					/* File name of database */
1634
	rc = sqlite3_open(fname, &db);
1635
 
1636
	if (rc)
1637
	{
1638
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1639
		qstackDelete(ID);
1640
		return NULL;
1641
	}
1642
 
1643
	strcpy (query, "select id, path, type, title, interpret, album, genre, cover from \"main\".\"musicdb\" where ");
1644
	strcat(query, "id = ");
1645
	sprintf(hv0, "%d", ID);
1646
	strcat(query, hv0);
1647
 
1648
	if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
1649
	{
1650
		syslog(LOG_WARNING, "SQL error [%s]: %s", query, sqlite3_errmsg(db));
1651
		sqlite3_close(db);
1652
		qstackDelete(ID);
1653
		return NULL;
1654
	}
1655
 
1656
	rc = sqlite3_step(res);
1657
 
1658
	if ((p = (char *)sqlite3_column_text(res, 1)) == NULL)
1659
	{
1660
		syslog(LOG_WARNING, "Error getting path from database!");
1661
		sqlite3_finalize(res);
1662
		sqlite3_close(db);
1663
		qstackDelete(ID);
1664
		return NULL;
1665
	}
1666
	else
1667
		strncpy(q->path, p, sizeof(q->path));
1668
 
1669
	q->fType = sqlite3_column_int(res, 2);
1670
 
1671
	if ((p = (char *)sqlite3_column_text(res, 3)) == NULL)
1672
	{
1673
		syslog(LOG_WARNING, "Error getting title from database!");
1674
		sqlite3_finalize(res);
1675
		sqlite3_close(db);
1676
		qstackDelete(ID);
1677
		return NULL;
1678
	}
1679
	else
1680
		strncpy(q->title, p, sizeof(q->title));
1681
 
1682
	if ((p = (char *)sqlite3_column_text(res, 4)) == NULL)
1683
	{
1684
		syslog(LOG_WARNING, "Error getting artist from database!");
1685
		sqlite3_finalize(res);
1686
		sqlite3_close(db);
1687
		qstackDelete(ID);
1688
		return NULL;
1689
	}
1690
	else
1691
		strncpy(q->artist, p, sizeof(q->artist));
1692
 
1693
	if ((p = (char *)sqlite3_column_text(res, 5)) == NULL)
1694
	{
1695
		syslog(LOG_WARNING, "Error getting album from database!");
1696
		sqlite3_finalize(res);
1697
		sqlite3_close(db);
1698
		qstackDelete(ID);
1699
		return NULL;
1700
	}
1701
	else
1702
		strncpy(q->album, p, sizeof(q->album));
1703
 
1704
	if ((p = (char *)sqlite3_column_text(res, 6)) == NULL)
1705
	{
1706
		syslog(LOG_WARNING, "Error getting genre from database!");
1707
		sqlite3_finalize(res);
1708
		sqlite3_close(db);
1709
		qstackDelete(ID);
1710
		return NULL;
1711
	}
1712
	else
1713
		strncpy(q->genre, p, sizeof(q->genre));
1714
 
1715
	if ((p = (char *)sqlite3_column_text(res, 7)) != NULL)
1716
		strncpy(q->cover, p, sizeof(q->cover));
1717
 
1718
	sqlite3_finalize(res);
1719
	sqlite3_close(db);
1720
 
1721
	if (configs.debug)
1722
		syslog(LOG_DEBUG, "qstackAdd(): Added file >>%d:%s<< to stack.", q->id, q->path);
1723
 
1724
	return q;
1725
}
1726
 
1727
void qstackDelete(int ID)
1728
{
1729
QUEUE *q, *p;
1730
int flag;
1731
 
1732
	if (qstack == NULL)
1733
		return;
1734
 
1735
	q = p = qstack;
1736
	flag = 0;
1737
 
1738
	while (q)
1739
	{
1740
		QUEUE *act;
1741
 
1742
		if (q->id == ID)
1743
		{
1744
			act = q;
1745
			q = q->next;
1746
 
1747
			if (p != act)
1748
				p->next = q;
1749
			else
1750
				qstack = q;			/* if the the first entry is to delete, let qstack point to the second entry, if there is one. */
1751
 
1752
			free(q);
1753
 
1754
			if (configs.debug)
1755
				syslog(LOG_DEBUG, "qstackDelete(): Deleted ID %d from stack.", ID);
1756
 
1757
			return;
1758
		}
1759
 
1760
		q = q->next;
1761
 
1762
		if (flag)
1763
			p = p->next;
1764
		else
1765
			flag = 1;
1766
	}
1767
}
1768
 
1769
void qstackClear()
1770
{
1771
QUEUE *act, *q;
1772
 
1773
	act = qstack;
1774
 
1775
	while (act)
1776
	{
1777
		q = act->next;
1778
		free(act);
1779
		act = q;
1780
	}
1781
 
1782
	qstack = NULL;
1783
}
1784
 
1785
QUEUE* qstackNext()
1786
{
1787
QUEUE *act, *p;
1788
int flag;
1789
 
1790
	if (qstack == NULL)
1791
		return NULL;
1792
 
1793
	act = p = qstack;
1794
	flag = 0;
1795
 
1796
	while (act->next)
1797
	{
1798
		if (flag)
1799
			p = p->next;
1800
		else
1801
			flag = 1;
1802
 
1803
		act = act->next;
1804
	}
1805
 
1806
	if (act != p)
1807
		p->next = NULL;
1808
	else
1809
		qstack = NULL;
1810
 
1811
	if ((p = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1812
	{
1813
		syslog(LOG_DAEMON, "Error allocating memory to get a stack entry: %s", strerror(errno));
1814
		free(act);
1815
		return NULL;
1816
	}
1817
 
1818
	if (configs.debug)
1819
		syslog(LOG_DEBUG, "qstackNext(): Pulled file >>%d:%s<< from stack.", act->id, act->path);
1820
 
1821
	memmove(p, act, sizeof(QUEUE));
1822
	free(act);
1823
	return p;
1824
}