Subversion Repositories mdb

Rev

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