Subversion Repositories mdb

Rev

Rev 58 | 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
 
61 andreas 457
		sqlite3_close(db);
49 andreas 458
		playerActive = FALSE;
57 andreas 459
		pthread_exit(NULL);
49 andreas 460
		return NULL;
461
	}
462
	else if (flag && (rc = sqlite3_exec(db, query, playCallback, (void *)_playPars->what, &zErrMsg)) != SQLITE_OK)
463
	{
6 andreas 464
		syslog(LOG_WARNING, "SQL error [%s]: %s", query, zErrMsg);
465
		sqlite3_free(zErrMsg);
466
		sqlite3_close(db);
467
		strcpy(query, "ERROR:PLAY:SQL error;");
468
		write (_playPars->s1, query, strlen(query));
7 andreas 469
		playerActive = FALSE;
57 andreas 470
		pthread_exit(NULL);
14 andreas 471
		return NULL;
6 andreas 472
	}
473
 
61 andreas 474
	sqlite3_close(db);
475
 
49 andreas 476
	if (configs.debug)
477
		syslog(LOG_DEBUG, "Playing from current queue starting at entry %d", start);
478
 
11 andreas 479
	strcpy (fname, configs.home);
480
	strcat (fname, NOWPLAY);
6 andreas 481
	/* start the player and play the file(s) */
7 andreas 482
	if (!access(fname, R_OK))
6 andreas 483
	{
36 andreas 484
		int fd, iflag, num, nextNum;
11 andreas 485
		QUEUE *act;
6 andreas 486
 
487
		if ((fd = open(fname, O_RDONLY)) < 0)
488
		{
489
			syslog(LOG_WARNING, "Error opening file %s: %s", fname, strerror(errno));
7 andreas 490
			playerActive = FALSE;
57 andreas 491
			pthread_exit(NULL);
14 andreas 492
			return NULL;
6 andreas 493
		}
494
 
36 andreas 495
		iflag = FALSE;
7 andreas 496
		num = 0;
497
		nextNum = -1;
498
 
11 andreas 499
		if (start > 0 && start <= queueTotal)
500
			num = start - 1;
501
 
502
		scanQueue(fd);
503
		close(fd);
504
 
36 andreas 505
		if (playerRandom && !flag && start <= 0)
11 andreas 506
			act = getRandomQueue();
507
		else
508
			act = getQueue(num);
509
 
510
		while (act)
6 andreas 511
		{
11 andreas 512
			char *title, *artist, *album, *cover;
6 andreas 513
 
7 andreas 514
			if (nextNum >= 0)
515
			{
516
				if (num == nextNum)
517
					nextNum = -1;
518
				else
519
				{
520
					num++;
11 andreas 521
					act = getQueue(num);
7 andreas 522
					continue;
523
				}
524
			}
525
 
36 andreas 526
			iflag = TRUE;
11 andreas 527
			title = urlencode(act->title);
528
			artist = urlencode(act->artist);
529
			album = urlencode(act->album);
530
			cover = urlencode(act->cover);
531
			sprintf(query, "PLAYING:%d:", act->id);
6 andreas 532
 
7 andreas 533
			if (title != NULL)
6 andreas 534
			{
7 andreas 535
				strcat(query, title);
536
				free(title);
537
			}
538
			else
11 andreas 539
				strcat(query, act->title);
6 andreas 540
 
7 andreas 541
			strcat(query, ":");
6 andreas 542
 
7 andreas 543
			if (artist != NULL)
544
			{
545
				strcat(query, artist);
546
				free(artist);
547
			}
548
			else
11 andreas 549
				strcat(query, act->artist);
6 andreas 550
 
7 andreas 551
			strcat(query, ":");
6 andreas 552
 
7 andreas 553
			if (album != NULL)
554
			{
555
				strcat(query, album);
556
				free(album);
557
			}
558
			else
11 andreas 559
				strcat(query, act->album);
6 andreas 560
 
7 andreas 561
			strcat(query, ":");
11 andreas 562
			strcat(query, act->genre);
563
			strcat(query, ":");
564
 
565
			if (cover != NULL)
566
			{
567
				strcat(query, cover);
568
				free(cover);
569
			}
570
			else
571
				strcat(query, act->cover);
572
 
7 andreas 573
			strcat(query, ";");
574
			write(_playPars->s1, query, strlen(query));
11 andreas 575
			setCurrentQueue(act);
576
			act->played = TRUE;
40 andreas 577
 
32 andreas 578
			if (act->fType == FILE_TYPE_MP3)
579
				playMP3(_playPars->s1, act->path);
580
			else
581
				playFlac(_playPars->s1, act->path);
6 andreas 582
 
54 andreas 583
			if (configs.debug)
584
				syslog(LOG_DEBUG, "Current play status: %d", playStatus);
585
 
7 andreas 586
			if (playStatus == PLAY_STATUS_SKIPF)
587
				playStatus = PLAY_STATUS_STOP;
11 andreas 588
			else if (playStatus == PLAY_STATUS_SKIPR && !playerRandom)
7 andreas 589
			{
590
				if (num > 0)
591
				{
592
					nextNum = num - 1;
593
					num = 0;
11 andreas 594
					act = pqueue;
7 andreas 595
					continue;
596
				}
6 andreas 597
 
7 andreas 598
				playStatus = PLAY_STATUS_STOP;
599
			}
50 andreas 600
			else if (playStatus == PLAY_STATUS_STACK || playStatus == PLAY_STATUS_STPLAY)
601
			{
602
				act = qstackNext();
603
 
604
				if (act)
605
				{
606
					playStatus = PLAY_STATUS_STPLAY;
607
					nextCommand = PLAY_NONE;
608
					continue;
609
				}
610
				else
611
				{
612
					nextCommand = PLAY_NONE;
613
					playStatus = PLAY_STATUS_PLAY;
614
				}
615
			}
7 andreas 616
			else if (playStatus == PLAY_STATUS_STOP)
617
				break;
6 andreas 618
 
7 andreas 619
			num++;
11 andreas 620
 
621
			if (playerRandom)
622
				act = getRandomQueue();
623
			else
624
				act = getQueue(num);
625
 
626
			if (playerRepeat && act == NULL)
627
			{
628
				num = 0;
629
				act = pqueue;
630
			}
54 andreas 631
 
632
			if (configs.debug)
633
				syslog(LOG_DEBUG, "Do we have a next file to play? >>%s<<", (act == NULL) ? "NO" : "YES");
7 andreas 634
		}
6 andreas 635
 
36 andreas 636
		if (!iflag)
7 andreas 637
			syslog(LOG_WARNING, "Found no files to play!");
6 andreas 638
 
7 andreas 639
		close (fd);
6 andreas 640
	}
7 andreas 641
	else
642
		syslog(LOG_WARNING, "Error accessing file %s: %s", fname, strerror(errno));
6 andreas 643
 
7 andreas 644
	playerActive = FALSE;
57 andreas 645
	pthread_exit(NULL);
14 andreas 646
	return NULL;
6 andreas 647
}
648
 
649
static int playCallback(void *hint, int argc, char **argv, char **azColName)
650
{
32 andreas 651
	int i, id, fd, fType;
11 andreas 652
	char path[512], id3_title[256], id3_artist[256], id3_album[256], id3_genre[256], id3_cover[512];
6 andreas 653
	char buffer[8192], *what;
654
 
655
	what = (char *)hint;
656
	memset(path, 0, sizeof(path));
657
	memset(id3_title, 0, sizeof(id3_title));
658
	memset(id3_artist, 0, sizeof(id3_artist));
659
	memset(id3_album, 0, sizeof(id3_album));
660
	memset(id3_genre, 0, sizeof(id3_genre));
11 andreas 661
	memset(id3_cover, 0, sizeof(id3_cover));
6 andreas 662
	id = -1;
663
 
664
	for(i = 0; i < argc; i++)
665
	{
666
		if (strcasecmp(azColName[i], "id") == 0)
667
			if (argv[i])
668
				id = atoi(argv[i]);
669
 
670
		if (strcasecmp(azColName[i], "path") == 0)
671
			if (argv[i])
672
				strncpy(path, argv[i], sizeof(path));
673
 
32 andreas 674
		if (strcasecmp(azColName[i], "type") == 0)
675
			if (argv[i])
676
				fType = atoi(argv[i]);
677
 
6 andreas 678
		if (strcasecmp(azColName[i], "title") == 0)
679
			if (argv[i])
680
				strncpy(id3_title, argv[i], sizeof(id3_title));
681
 
682
		if (strcasecmp(azColName[i], "interpret") == 0)
683
			if (argv[i])
684
				strncpy(id3_artist, argv[i], sizeof(id3_artist));
685
 
686
		if (strcasecmp(azColName[i], "album") == 0)
687
			if (argv[i])
688
				strncpy(id3_album, argv[i], sizeof(id3_album));
689
 
690
		if (strcasecmp(azColName[i], "genre") == 0)
691
			if (argv[i])
692
				strncpy(id3_genre, argv[i], sizeof(id3_genre));
11 andreas 693
 
694
			if (strcasecmp(azColName[i], "cover") == 0)
695
				if (argv[i])
696
					strncpy(id3_cover, argv[i], sizeof(id3_cover));
6 andreas 697
	}
698
 
699
	if (id != -1 && strlen(path) > 0)
700
	{
701
		char fname[512];
702
 
703
		strcpy(fname, configs.home);
704
		strcat(fname, NOWPLAY);
705
 
11 andreas 706
		if (checkQueueDouble(id) == TRUE)	/* Make sure every ID in the queue is unique */
7 andreas 707
			return 0;
708
 
709
		if ((fd = open(fname, O_RDWR | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP)) < 0)
6 andreas 710
		{
8 andreas 711
			syslog(LOG_WARNING, "Error creating or writing to file %s: %s", fname, strerror(errno));
6 andreas 712
			return 1;
713
		}
7 andreas 714
 
32 andreas 715
		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 716
		write (fd, buffer, strlen(buffer));
32 andreas 717
		addToQueue(id, path, fType, id3_title, id3_artist, id3_album, id3_genre, id3_cover);
6 andreas 718
		close (fd);
719
	}
720
	else
7 andreas 721
		syslog(LOG_WARNING, "Found no data to play");
6 andreas 722
 
723
	return 0;
724
}
725
 
7 andreas 726
void playMP3(int s1, char *file)
6 andreas 727
{
34 andreas 728
mpg123_handle *mh;
729
unsigned char *buffer;
730
size_t buffer_size;
731
size_t done;
732
off_t frame;
53 andreas 733
int err, i, rc, flag;
34 andreas 734
char hv0[128];
735
 
736
int driver;
737
ao_device *dev;
738
ao_option ao_opts;
739
 
54 andreas 740
ao_sample_format format;
741
int channels, encoding;
742
long rate;
743
double current_seconds, seconds_left, act_sec;
744
off_t current_frame, frames_left;
6 andreas 745
 
7 andreas 746
	if(file == NULL || strlen(file) == 0)
6 andreas 747
	{
7 andreas 748
		syslog(LOG_DAEMON, "No or invalid file was passed to player!");
749
		return;
6 andreas 750
	}
751
 
28 andreas 752
	/* Check if we've a valid sound driver defined */
753
	flag = FALSE;
754
	i = 0;
755
 
756
	while (aoOutPlayers[i][0])
757
	{
758
		if (!strcasecmp(aoOutPlayers[i], configs.player))
759
		{
760
			flag = TRUE;
34 andreas 761
 
762
			if (configs.debug)
763
				syslog(LOG_DEBUG, "Found sound driver %s to use for playback.", aoOutPlayers[i]);
764
 
28 andreas 765
			break;
766
		}
767
 
768
		i++;
769
	}
770
 
50 andreas 771
	if (configs.debug)
772
		syslog(LOG_DEBUG, "playMP3: Try to play file >>%s<<", file);
773
 
7 andreas 774
	/* initializations */
775
	ao_initialize();
28 andreas 776
 
777
	if (flag)
6 andreas 778
	{
28 andreas 779
		if ((driver = ao_driver_id(configs.player)) == -1)
780
		{
781
			syslog(LOG_DAEMON, "Error finding the audio out driver %s!", configs.player);
782
			ao_shutdown();
783
			return;
784
		}
785
	}
786
	else if ((driver = ao_default_driver_id()) == -1)
787
	{
7 andreas 788
		syslog(LOG_DAEMON, "Error finding a default audio driver!");
789
		ao_shutdown();
790
		return;
6 andreas 791
	}
7 andreas 792
 
793
	mpg123_init();
54 andreas 794
 
795
	if (configs.debug)
796
		syslog(LOG_DEBUG, "MPG123 initialized.");
797
 
7 andreas 798
	if ((mh = mpg123_new(NULL, &err)) == NULL)
799
	{
800
		syslog(LOG_DAEMON, "Error creating new MP3 handle: %s", mpg123_plain_strerror(err));
801
		ao_shutdown();
802
		return;
803
	}
804
 
54 andreas 805
	if (configs.debug)
806
		syslog(LOG_DEBUG, "MPG123 opened.");
807
 
7 andreas 808
	buffer_size = mpg123_outblock(mh);
809
 
810
	if ((buffer = (unsigned char*)malloc(buffer_size * sizeof(unsigned char))) == NULL)
811
	{
812
		syslog(LOG_DAEMON, "Error allocating memory for MP3 player: %s", strerror(errno));
813
		mpg123_close(mh);
814
		mpg123_delete(mh);
815
		mpg123_exit();
816
		ao_shutdown();
817
		return;
818
	}
819
 
820
	/* open the file and get the decoding format */
821
	if (mpg123_open(mh, file) != MPG123_OK)
822
	{
11 andreas 823
		syslog(LOG_DAEMON, "Error opening MP3 file %s: %s", file, mpg123_strerror(mh));
7 andreas 824
		free(buffer);
825
		mpg123_close(mh);
826
		mpg123_delete(mh);
827
		mpg123_exit();
828
		ao_shutdown();
829
		return;
830
	}
831
 
11 andreas 832
	if (mpg123_scan(mh) != MPG123_OK)
833
		syslog(LOG_WARNING, "Error scanning MP3 file %s: %s", file, mpg123_strerror(mh));
7 andreas 834
 
11 andreas 835
	if (mpg123_getformat(mh, &rate, &channels, &encoding) != MPG123_OK)
836
	{
837
		syslog(LOG_DAEMON, "Error getting the format of MP3 file %s: %s", file, mpg123_strerror(mh));
838
		free(buffer);
839
		mpg123_close(mh);
840
		mpg123_delete(mh);
841
		mpg123_exit();
842
		ao_shutdown();
843
		return;
844
	}
845
 
7 andreas 846
	/* set the output format and open the output device */
847
	format.bits = mpg123_encsize(encoding) * BITS;
848
	format.rate = rate;
849
	format.channels = channels;
850
	format.byte_format = AO_FMT_NATIVE;
851
	format.matrix = 0;
35 andreas 852
 
853
	if (configs.debug)
854
	{
855
		syslog(LOG_DEBUG, "Format: Bits:     %d", format.bits);
856
		syslog(LOG_DEBUG, "Format: Rate:     %ld", rate);
857
		syslog(LOG_DEBUG, "Format: Channels: %d", channels);
858
	}
859
 
34 andreas 860
	memset(&ao_opts, 0, sizeof(ao_option));
861
 
862
	if (configs.debug)
7 andreas 863
	{
58 andreas 864
		syslog(LOG_DEBUG, "Switching on debugging for AO library.");
34 andreas 865
		strcpy(hv0, "debug");
866
		ao_opts.key = strdup(hv0);
867
		strcpy(hv0, "1");
868
		ao_opts.value = strdup(hv0);
869
		dev = ao_open_live(driver, &format, &ao_opts);
54 andreas 870
		syslog(LOG_DEBUG, "AO library opened.");
34 andreas 871
	}
872
	else
873
		dev = ao_open_live(driver, &format, NULL);
874
 
875
	if (dev == NULL)
876
	{
35 andreas 877
		switch (errno)
878
		{
879
			case AO_ENODRIVER:	sprintf(hv0, "No driver corresponds to \"driver_id\"."); break;
880
			case AO_ENOTLIVE:	sprintf(hv0, "This driver (%s) is not a live output device.", configs.player); break;
881
			case AO_EBADOPTION:	sprintf(hv0, "A valid option key has an invalid value."); break;
882
			case AO_EOPENDEVICE:sprintf(hv0, "Cannot open the device."); break;
883
			default:
884
				sprintf(hv0, "%s", strerror(errno));
885
		}
886
 
887
		syslog(LOG_DAEMON, "Error opening live playback device: %s", hv0);
7 andreas 888
		free(buffer);
889
		mpg123_close(mh);
890
		mpg123_delete(mh);
891
		mpg123_exit();
892
		ao_shutdown();
34 andreas 893
 
894
		if (configs.debug)
895
		{
896
			free(ao_opts.key);
897
			free(ao_opts.value);
898
		}
899
 
7 andreas 900
		return;
901
	}
902
 
50 andreas 903
	if (playStatus != PLAY_STATUS_STPLAY)
904
		playStatus = PLAY_STATUS_PLAY;
905
 
56 andreas 906
/*	strcpy (hv0, "PLAYER:PLAY;");
907
	write(s1, hv0, strlen(hv0)); */
908
	handleWrite("PLAYER:PLAY;");
28 andreas 909
	act_sec = 0.0;
910
	flag = FALSE;
54 andreas 911
	current_seconds = seconds_left = 0;
912
	current_frame = frames_left = 0;
913
	nextCommand = PLAY_NONE;			/* Reset commands to be sure there is no lost command left */
28 andreas 914
	frame = mpg123_tellframe(mh);
54 andreas 915
 
7 andreas 916
	/* decode and play */
53 andreas 917
	while ((rc = mpg123_read(mh, buffer, buffer_size, &done)) == MPG123_OK)
7 andreas 918
	{
919
		int todo;
920
		char hv1[32], hv2[32], hv3[32];
921
 
922
		todo = check_command(s1);
923
 
924
		if (todo == PLAY_STATUS_STOP)
925
			break;
926
		else if (todo == PLAY_STATUS_FWD)
927
		{
928
			mpg123_seek_frame(mh, 100, SEEK_CUR);
50 andreas 929
 
930
			if (playStatus != PLAY_STATUS_STPLAY)
931
				playStatus = PLAY_STATUS_PLAY;
932
 
7 andreas 933
			continue;
934
		}
935
		else if (todo == PLAY_STATUS_REW)
936
		{
937
			off_t fr;
938
 
939
			fr =  mpg123_tellframe(mh);
940
 
941
			if (fr > 100)
942
				fr -= 100;
943
			else
944
				fr = 0;
945
 
946
			mpg123_seek_frame(mh, fr, SEEK_SET);
50 andreas 947
 
948
			if (playStatus != PLAY_STATUS_STPLAY)
949
				playStatus = PLAY_STATUS_PLAY;
950
 
7 andreas 951
			continue;
952
		}
953
 
954
		/* get position */
28 andreas 955
		if (!flag)
956
		{
957
			mpg123_position(mh, mpg123_tellframe(mh), done, &current_frame, &frames_left, &current_seconds, &seconds_left);
958
			act_sec = current_seconds;
959
			flag = TRUE;
960
		}
54 andreas 961
		else if (flag && frame != 0)
28 andreas 962
		{
963
			double cs, sl;
964
			mpg123_position(mh, frame, done, &current_frame, &frames_left, &cs, &sl);
29 andreas 965
			frame = mpg123_tellframe(mh) / 100;
28 andreas 966
			act_sec = cs;
967
		}
54 andreas 968
		else if (frame == 0)
969
			frame = mpg123_tellframe(mh) / 100;
28 andreas 970
 
55 andreas 971
		if (!playQuiet)
972
		{
973
			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 974
/*			write(s1, hv0, strlen(hv0)); */
975
			handleWrite(hv0);
55 andreas 976
		}
977
 
7 andreas 978
		ao_play(dev, (char *)buffer, done);
979
	}
53 andreas 980
 
981
	if (configs.debug && rc != MPG123_OK)
54 andreas 982
		syslog(LOG_DEBUG, "MPG123 Error: %s", mpg123_plain_strerror(rc));
53 andreas 983
 
7 andreas 984
	/* clean up */
56 andreas 985
/*	strcpy(hv0, "PLAYER:STOP;");
986
	write (s1, hv0, strlen(hv0)); */
987
	handleWrite("PLAYER:STOP;");
7 andreas 988
 
989
	free(buffer);
990
	ao_close(dev);
991
	mpg123_close(mh);
992
	mpg123_delete(mh);
993
	mpg123_exit();
54 andreas 994
 
995
	if (configs.debug)
996
		syslog(LOG_DEBUG, "MPG123 closed");
997
 
7 andreas 998
	ao_shutdown();
34 andreas 999
 
1000
	if (configs.debug)
1001
	{
1002
		free(ao_opts.key);
1003
		free(ao_opts.value);
54 andreas 1004
		syslog(LOG_DEBUG, "AO library closed.");
34 andreas 1005
	}
6 andreas 1006
}
1007
 
7 andreas 1008
int check_command(int s1)
6 andreas 1009
{
56 andreas 1010
/*	char hv0[64]; */
6 andreas 1011
 
8 andreas 1012
	if (nextCommand == PLAY_STOP_NOW)
1013
	{
1014
		playStatus = PLAY_STATUS_STOP;
1015
		return playStatus;
1016
	}
1017
 
50 andreas 1018
	if (nextCommand == PLAY_STACK)
1019
	{
1020
		playStatus = PLAY_STATUS_STACK;
1021
		return PLAY_STATUS_STOP;
1022
	}
1023
 
7 andreas 1024
	if (nextCommand == PLAY_PLAY && (playStatus == PLAY_STATUS_FWD || playStatus == PLAY_STATUS_REW))
1025
	{
1026
		playStatus = PLAY_STATUS_PLAY;
1027
		return playStatus;
1028
	}
6 andreas 1029
 
7 andreas 1030
	if (nextCommand == PLAY_STOP && (playStatus == PLAY_STATUS_PLAY || playStatus == PLAY_STATUS_PAUSE))
1031
	{
1032
		nextCommand = PLAY_NONE;
1033
		playStatus = PLAY_STATUS_STOP;
1034
		return playStatus;
1035
	}
50 andreas 1036
	else if (nextCommand == PLAY_STOP && playStatus == PLAY_STATUS_STPLAY)
1037
	{
1038
		nextCommand = PLAY_NONE;
1039
		playStatus = PLAY_STATUS_PLAY;
1040
		return PLAY_STATUS_STOP;
1041
	}
6 andreas 1042
 
7 andreas 1043
	if ((nextCommand == PLAY_PAUSE || nextCommand == PLAY_PLAYPAUSE) && playStatus == PLAY_STATUS_PLAY)
6 andreas 1044
	{
7 andreas 1045
		nextCommand = PLAY_NONE;
1046
		playStatus = PLAY_STATUS_PAUSE;
56 andreas 1047
		handleWrite ("PLAYER:PAUSE;");
1048
/*		write (s1, hv0, strlen(hv0)); */
6 andreas 1049
 
7 andreas 1050
		while (nextCommand != PLAY_PLAY && nextCommand != PLAY_PLAYPAUSE)
1051
			sleep(1);
1052
 
1053
		playStatus = PLAY_STATUS_PLAY;
56 andreas 1054
		handleWrite ("PLAYER:PLAY;");
1055
/*		write (s1, hv0, strlen(hv0)); */
7 andreas 1056
		nextCommand = PLAY_NONE;
6 andreas 1057
	}
1058
 
7 andreas 1059
	if (nextCommand == PLAY_FWD)
1060
	{
1061
		nextCommand = PLAY_NONE;
1062
		playStatus = PLAY_STATUS_FWD;
1063
		return PLAY_STATUS_FWD;
1064
	}
1065
 
1066
	if (nextCommand == PLAY_REW)
1067
	{
1068
		nextCommand = PLAY_NONE;
1069
		playStatus = PLAY_STATUS_REW;
1070
		return PLAY_STATUS_REW;
1071
	}
1072
 
1073
	if (nextCommand == PLAY_SKIP_FWD)
1074
	{
1075
		nextCommand = PLAY_NONE;
1076
		playStatus = PLAY_STATUS_SKIPF;
1077
		return PLAY_STATUS_STOP;
1078
	}
1079
 
1080
	if (nextCommand == PLAY_SKIP_REW)
1081
	{
1082
		nextCommand = PLAY_NONE;
1083
		playStatus = PLAY_STATUS_SKIPR;
1084
		return PLAY_STATUS_STOP;
1085
	}
1086
 
1087
	return 0;
6 andreas 1088
}
1089
 
11 andreas 1090
int checkQueueDouble(int id)
6 andreas 1091
{
11 andreas 1092
	QUEUE *act;
7 andreas 1093
 
11 andreas 1094
	act = pqueue;
1095
 
1096
	while (act)
7 andreas 1097
	{
11 andreas 1098
		if (act->id == id)
1099
			return TRUE;
7 andreas 1100
 
11 andreas 1101
		act = act->next;
7 andreas 1102
	}
11 andreas 1103
 
7 andreas 1104
	return FALSE;
1105
}
1106
 
1107
void appendToQueue(int s1, char *type, char *what)
1108
{
1109
	char fname[256], query[1024];
1110
	int rc;
1111
	sqlite3 *db;
1112
	char *zErrMsg = 0;
6 andreas 1113
 
7 andreas 1114
	/* retrieve the data from the database */
1115
	strcpy(fname, configs.home);
9 andreas 1116
	strcat(fname, MUSICDB);
6 andreas 1117
 
7 andreas 1118
	rc = sqlite3_open(fname, &db);
6 andreas 1119
 
7 andreas 1120
	if (rc)
6 andreas 1121
	{
7 andreas 1122
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1123
		strcpy(query, "ERROR:PLAY:Error opening database;");
1124
		write (s1, query, strlen(query));
1125
		playerActive = FALSE;
1126
		return;
6 andreas 1127
	}
1128
 
40 andreas 1129
	strcpy (query, "select id, path, type, title, interpret, album, genre, cover from \"main\".\"musicdb\" where ");
6 andreas 1130
 
7 andreas 1131
	if (strcasecmp(type, "ID") == 0)
1132
	{
1133
		strcat(query, "id = ");
1134
		strcat(query, what);
1135
	}
1136
	else if (strcasecmp(type, "TITLE") == 0)
1137
	{
1138
		strcat(query, "title = \"");
1139
		strcat(query, what);
1140
		strcat(query, "\" order by title");
1141
	}
1142
	else if (strcasecmp(type, "ARTIST") == 0)
1143
	{
1144
		strcat(query, "interpret = \"");
1145
		strcat(query, what);
1146
		strcat(query, "\" order by interpret");
1147
	}
1148
	else if (strcasecmp(type, "ALBUM") == 0)
1149
	{
1150
		strcat(query, "album = \"");
1151
		strcat(query, what);
1152
		strcat(query, "\" order by album");
1153
	}
1154
	else if (strcasecmp(type, "GENRE") == 0)
1155
	{
1156
		strcat(query, "genre = \"");
1157
		strcat(query, what);
1158
		strcat(query, "\" order by genre");
1159
	}
8 andreas 1160
	else if (strcasecmp(type, "PLAYLIST") == 0)
1161
	{
1162
		USERS *act;
6 andreas 1163
 
8 andreas 1164
		sqlite3_close(db);
1165
		act = userchain;
1166
 
1167
		while (act)
1168
		{
1169
			if (strcmp(act->playlist, what) == 0)
1170
			{
1171
				playlistToQueue(act->id, FALSE);
1172
				break;
1173
			}
1174
 
1175
			act = act->next;
1176
		}
1177
 
1178
		if (act == NULL)
1179
		{
1180
			strcpy(query, "ERROR:PLAY:Error transfering playlist entries to queue;");
1181
			write (s1, query, strlen(query));
1182
		}
1183
 
1184
		return;
1185
	}
1186
 
7 andreas 1187
	if ((rc = sqlite3_exec(db, query, playCallback, (void *)what, &zErrMsg)) != SQLITE_OK)
6 andreas 1188
	{
7 andreas 1189
		syslog(LOG_WARNING, "SQL error [%s]: %s", query, zErrMsg);
1190
		sqlite3_free(zErrMsg);
1191
		sqlite3_close(db);
1192
		strcpy(query, "ERROR:PLAY:SQL error;");
1193
		write (s1, query, strlen(query));
6 andreas 1194
	}
18 andreas 1195
 
28 andreas 1196
	readQueue();
8 andreas 1197
}
1198
 
32 andreas 1199
QUEUE *addToQueue(int id, char *path, int fType, char *title, char *artist, char *album, char *genre, char *cover)
11 andreas 1200
{
1201
	QUEUE *act, *neu;
1202
	/* find the end of the chain */
1203
	act = pqueue;
1204
 
1205
	while (act && act->next)
1206
	{
1207
		if (act->id == id)			/* If the ID is already in the chain, return the pointer to it */
1208
			return act;
1209
 
1210
		act = act->next;
1211
	}
1212
	/* Allocate memory for a new element in the chain */
1213
	if ((neu = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1214
	{
1215
		syslog(LOG_DAEMON, "Error allocating %lu bytes for an entry in the queue: %s", sizeof(QUEUE), strerror(errno));
1216
		return NULL;
1217
	}
1218
 
1219
	memset(neu, 0, sizeof(QUEUE));
1220
	/* Copy the data into the new element */
1221
	neu->id = id;
32 andreas 1222
	neu->fType = fType;
11 andreas 1223
 
1224
	if (path)
1225
		strncpy (neu->path, path, sizeof(neu->path)-1);
1226
 
1227
	if (title)
1228
		strncpy (neu->title, title, sizeof(neu->title)-1);
1229
 
1230
	if (artist)
1231
		strncpy (neu->artist, artist, sizeof(neu->artist)-1);
1232
 
1233
	if (album)
1234
		strncpy (neu->album, album, sizeof(neu->album)-1);
1235
 
1236
	if (genre)
1237
		strncpy (neu->genre, genre, sizeof(neu->genre)-1);
1238
 
1239
	if (cover)
1240
		strncpy (neu->cover, cover, sizeof(neu->cover)-1);
1241
	/* Append the element to the end of the chain */
1242
	if (act == NULL)
1243
		act = pqueue = neu;
1244
	else
1245
		act->next = neu;
1246
 
1247
	return neu;
1248
}
1249
 
8 andreas 1250
/*
1251
 * This function copies the content of a playlist into the queue.
1252
 * The parameter defines whether the current queue should be deleted or not.
1253
 * If the queue should not be deleted, the playlist will be appended.
1254
 */
1255
int playlistToQueue(int uid, int del)
1256
{
1257
	char fname[256], query[1024], hv0[256], buffer[8192];
1258
	int rc;
1259
	sqlite3 *db;
1260
	sqlite3_stmt *res;
1261
	char path[512], id3_title[256], id3_artist[256], id3_album[256], id3_genre[256];
32 andreas 1262
	int id, fd, fType;
8 andreas 1263
	unsigned int mode;
1264
 
1265
	strcpy(fname, configs.home);
9 andreas 1266
	strcat(fname, MUSICDB);
8 andreas 1267
 
1268
	rc = sqlite3_open(fname, &db);
1269
 
1270
	if (rc)
1271
	{
1272
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1273
		return FALSE;
1274
	}
1275
 
32 andreas 1276
	strcpy (query, "select id, path, type, title, interpret, album, genre from \"main\".\"musicdb\" as a where ");
8 andreas 1277
	strcat (query, "(select musicid from \"main\".\"playlists\"  as b where a.id = b.musicid and b.userid = ");
1278
	sprintf(hv0, "%d", uid);
1279
	strcat (query, hv0);
1280
	strcat (query, ")");
1281
 
1282
	if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
1283
	{
1284
		syslog(LOG_DAEMON, "Error preparing SQL statement [%s]: %s", query, sqlite3_errmsg(db));
1285
		sqlite3_close(db);
1286
		return FALSE;
1287
	}
1288
 
1289
	/* Open the queue */
1290
	strcpy(fname, configs.home);
1291
	strcat(fname, NOWPLAY);
1292
 
1293
	if (!del)
1294
		mode = O_RDWR | O_APPEND | O_CREAT;
1295
	else
48 andreas 1296
	{
8 andreas 1297
		mode = O_RDWR | O_TRUNC | O_CREAT;
1298
 
48 andreas 1299
		if (playerActive)
1300
			nextCommand = PLAY_STOP_NOW;
1301
	}
1302
 
8 andreas 1303
	if ((fd = open(fname, mode, S_IWUSR | S_IRUSR | S_IRGRP)) <= 0)
1304
	{
1305
		syslog(LOG_WARNING, "Error opening file %s: %s", fname, strerror(errno));
9 andreas 1306
		sqlite3_finalize(res);
8 andreas 1307
		sqlite3_close(db);
1308
		return FALSE;
1309
	}
1310
 
1311
	while ((rc = sqlite3_step(res)) == SQLITE_ROW)
1312
	{
1313
		memset(path, 0, sizeof(path));
1314
		memset(id3_title, 0, sizeof(id3_title));
1315
		memset(id3_artist, 0, sizeof(id3_artist));
1316
		memset(id3_album, 0, sizeof(id3_album));
1317
		memset(id3_genre, 0, sizeof(id3_genre));
1318
		id = sqlite3_column_int(res, 0);
1319
		strncpy(path, (const char *)sqlite3_column_text(res, 1), sizeof(path));
32 andreas 1320
		fType = sqlite3_column_int(res, 2);
1321
		strncpy(id3_title, (const char *)sqlite3_column_text(res, 3), sizeof(id3_title));
1322
		strncpy(id3_artist, (const char *)sqlite3_column_text(res, 4), sizeof(id3_artist));
1323
		strncpy(id3_album, (const char *)sqlite3_column_text(res, 5), sizeof(id3_album));
1324
		strncpy(id3_genre, (const char *)sqlite3_column_text(res, 6), sizeof(id3_genre));
39 andreas 1325
		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 1326
		write (fd, buffer, strlen(buffer));
1327
	}
1328
 
11 andreas 1329
	scanQueue(fd);
8 andreas 1330
	close(fd);
9 andreas 1331
	sqlite3_finalize(res);
8 andreas 1332
	sqlite3_close(db);
1333
	return TRUE;
1334
}
1335
 
1336
int QueueToPlaylist(int s1, char *user, char *playlist)
1337
{
11 andreas 1338
	char fname[256], query[1024], hv0[256];
8 andreas 1339
	int rc;
1340
	sqlite3 *db;
1341
	char *zErrMsg = 0;
1342
	sqlite3_stmt *res;
29 andreas 1343
	int num;
8 andreas 1344
	USERS *usp;
11 andreas 1345
	QUEUE *act;
29 andreas 1346
 
8 andreas 1347
	strcpy(fname, configs.home);
9 andreas 1348
	strcat(fname, MUSICDB);
8 andreas 1349
 
1350
	rc = sqlite3_open(fname, &db);
1351
 
1352
	if (rc)
1353
	{
1354
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1355
		return FALSE;
1356
	}
1357
 
14 andreas 1358
	if ((usp = findPlaylist(user, playlist)) != NULL)
8 andreas 1359
	{
1360
		sprintf(query, "delete from playlists where userid = %d", usp->id);
1361
 
1362
		if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
1363
		{
1364
			syslog(LOG_DAEMON, "Error preparing SQL statement [%s]: %s", query, sqlite3_errmsg(db));
1365
			sqlite3_close(db);
1366
			return FALSE;
1367
		}
1368
 
1369
		sqlite3_step(res);
1370
	}
29 andreas 1371
	else if (createUser(s1, user, playlist))
8 andreas 1372
	{
29 andreas 1373
		if ((usp = findPlaylist(user, playlist)) == NULL)
1374
			return FALSE;
1375
	}
1376
	else
8 andreas 1377
		return FALSE;
29 andreas 1378
 
1379
	/* Update the queue in case there is none in memory*/
11 andreas 1380
	if (pqueue == NULL)
29 andreas 1381
		readQueue();
11 andreas 1382
 
1383
	act = pqueue;
8 andreas 1384
	num = 0;
1385
 
11 andreas 1386
	while (act)
8 andreas 1387
	{
1388
		strcpy (query, "insert into playlists (userid, musicid) values (");
29 andreas 1389
		sprintf(hv0, "%d", usp->id);
8 andreas 1390
		strcat (query, hv0);
1391
		strcat (query, ",");
11 andreas 1392
		sprintf(hv0, "%d", act->id);
8 andreas 1393
		strcat (query, hv0);
1394
		strcat (query, ")");
1395
 
1396
		if ((rc = sqlite3_exec(db, query, NULL, NULL, &zErrMsg)) != SQLITE_OK)
1397
		{
1398
			syslog(LOG_WARNING, "SQL error [%s]: %s", query, zErrMsg);
1399
			sqlite3_free(zErrMsg);
1400
			sqlite3_close(db);
1401
			return FALSE;
1402
		}
11 andreas 1403
 
1404
		num++;
1405
		act = act->next;
8 andreas 1406
	}
11 andreas 1407
 
8 andreas 1408
	sqlite3_close(db);
1409
	sprintf(hv0, "TRANSFERED:%d;", num);
1410
	write (s1, hv0, strlen(hv0));
1411
	return TRUE;
1412
}
11 andreas 1413
 
1414
void freeQueue()
1415
{
1416
	QUEUE *act;
1417
 
1418
	act = pqueue;
1419
 
1420
	while (act)
1421
	{
1422
		pqueue = act->next;
1423
		free (act);
1424
		act = pqueue;
1425
	}
1426
 
1427
	pqueue = NULL;
1428
	queueTotal = 0;
1429
}
1430
 
25 andreas 1431
int readQueue()
1432
{
1433
	int fd;
1434
	char fname[256];
1435
 
1436
	strcpy (fname, configs.home);
1437
	strcat (fname, NOWPLAY);
1438
	/* start the player and play the file(s) */
1439
	if (!access(fname, R_OK))
1440
	{
1441
		if ((fd = open(fname, O_RDONLY)) < 0)
1442
		{
1443
			syslog(LOG_WARNING, "Error opening file %s: %s", fname, strerror(errno));
1444
			return FALSE;
1445
		}
1446
 
1447
		scanQueue(fd);
1448
		close(fd);
1449
	}
1450
	else
1451
		return FALSE;
1452
 
1453
	return TRUE;
1454
}
1455
 
11 andreas 1456
int scanQueue(int fd)
1457
{
1458
	QUEUE *act;
1459
	int count, x;
1460
	char buffer[8192], *t;
1461
 
1462
	if (pqueue != NULL)
1463
		freeQueue();
1464
 
1465
	count = 0;
1466
	lseek (fd, 0L, SEEK_SET);
1467
 
1468
	while (readLine (fd, buffer, sizeof(buffer)) != NULL)
1469
	{
1470
		QUEUE *new;
1471
 
1472
		if ((new = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1473
		{
1474
			syslog(LOG_DAEMON, "Error allocating %lu bytes of memory: %s", sizeof(QUEUE), strerror(errno));
1475
			lseek(fd, 0L, SEEK_SET);
1476
			return -1;
1477
		}
1478
 
1479
		memset(new, 0, sizeof(QUEUE));
1480
 
1481
		if (count > 0)
1482
			act->next = new;
1483
		else
1484
			pqueue = new;
1485
 
1486
		act = new;
1487
		x = 0;
30 andreas 1488
		t = strsplitt(buffer, '\t');
11 andreas 1489
 
1490
		while (t)
1491
		{
1492
			switch (x)
1493
			{
30 andreas 1494
				case 0: strncpy(act->path, t, sizeof(act->path)-1); break;
32 andreas 1495
				case 1: act->fType = atoi(t); break;
1496
				case 2: act->id = atoi(t); break;
1497
				case 3: strncpy(act->title, t, sizeof(act->title)-1); break;
1498
				case 4: strncpy(act->artist, t, sizeof(act->artist)-1); break;
1499
				case 5: strncpy(act->album, t, sizeof(act->album)-1); break;
1500
				case 6: strncpy(act->genre, t, sizeof(act->genre)-1); break;
1501
				case 7: strncpy(act->cover, t, sizeof(act->cover)-1); break;
11 andreas 1502
			}
1503
 
30 andreas 1504
			t = strsplitt(NULL, '\t');
11 andreas 1505
			x++;
1506
		}
1507
 
1508
		count++;
1509
	}
1510
 
1511
	queueTotal = count;
1512
	return count;
1513
}
1514
 
1515
void setCurrentQueue(QUEUE *q)
1516
{
1517
	if (q == NULL)
1518
		return;
1519
 
1520
	memset(&playCurrent, 0, sizeof(ST_PLAYING));
1521
	playCurrent.id = q->id;
1522
	strncpy (playCurrent.title, q->title, sizeof(playCurrent.title));
1523
	strncpy (playCurrent.artist, q->artist, sizeof(playCurrent.artist));
1524
	strncpy (playCurrent.album, q->album, sizeof(playCurrent.album));
1525
	strncpy (playCurrent.genre, q->genre, sizeof(playCurrent.genre));
1526
	strncpy (playCurrent.cover, q->cover, sizeof(playCurrent.cover));
1527
}
1528
 
1529
QUEUE *getQueue(int idx)
1530
{
1531
	QUEUE *act;
1532
	int pos;
1533
 
1534
	act = pqueue;
1535
	pos = 0;
1536
 
1537
	while (act)
1538
	{
1539
		if (pos == idx)
1540
			return act;
1541
 
1542
		pos++;
1543
		act = act->next;
1544
	}
1545
 
1546
	return NULL;
1547
}
1548
 
1549
QUEUE *getRandomQueue()
1550
{
1551
	QUEUE *act;
1552
	int pos;
1553
	long r;
1554
 
1555
	if (pqueue == NULL)
1556
		return NULL;
1557
 
1558
	if (queueTotal > 1)
1559
		r = random_at_most((long)queueTotal-1);
1560
	else
1561
	{
1562
		if (pqueue->played)
1563
			return pqueue->next;
1564
		else
1565
			return pqueue;
1566
	}
1567
 
1568
	pos = 0;
1569
	act = pqueue;
1570
	/* Scan queue and check wheter all entries are allready played */
1571
	while (act)
1572
	{
1573
		if (!act->played)
1574
			break;
1575
 
1576
		act = act->next;
1577
	}
1578
 
1579
	if (act == NULL)		/* If all is played, we reset the status and start again */
1580
	{
1581
		act = pqueue;
1582
 
1583
		while (act)
1584
		{
1585
			act->played = FALSE;
1586
			act = act->next;
1587
		}
1588
	}
1589
 
1590
	act = pqueue;
1591
 
1592
	while (act)
1593
	{
1594
		if (pos == r)				/* have we reached the random position? */
1595
		{							/* Yes, then check if this entry was already played. */
1596
			if (act->played)		/* Was it played? */
1597
			{						/* Yes, then reset and try again */
1598
				r = random_at_most((long)queueTotal - 1);
1599
				act = pqueue;
1600
				pos = 0;
1601
				continue;
1602
			}
1603
			else					/* It was not played before so */
1604
				return act;			/* return the pointer to it */
1605
		}
1606
 
1607
		pos++;
1608
		act = act->next;
1609
	}
1610
 
1611
	return NULL;
50 andreas 1612
}
1613
 
1614
/*
1615
 * The following functions manage the STACK.
1616
 * The stack contains one or more files to play immediately. Even if a file
1617
 * of the normal queue is playing, the song is interrupted and the stack
1618
 * takes precedence. After the stack has been played or stopped by the user,
1619
 * the queue continues to play.
1620
 * 
1621
 * Adding a file to the stack does not alter the queue in any way. The stack
1622
 * is a kind of second queue but with higher priority.
1623
 */
1624
QUEUE* qstackAdd(int ID)
1625
{
1626
QUEUE *q;
1627
char query[1024], hv0[64], fname[512];
1628
char *p;
1629
sqlite3_stmt *res;
1630
sqlite3 *db;
1631
int rc;
1632
 
1633
	if (ID < 0)
1634
		return NULL;
1635
 
1636
	if ((q = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1637
	{
1638
		syslog(LOG_DAEMON, "Error allocating memory for a stack entry: %s", strerror(errno));
1639
		return NULL;
1640
	}
1641
 
1642
	memset(q, 0, sizeof(QUEUE));
1643
	q->id = ID;
1644
 
1645
	if (qstack)
1646
	{
1647
		QUEUE *act;
1648
 
1649
		act = qstack;
1650
 
1651
		while (act->next)
1652
			act = act->next;
1653
 
1654
		act->next = q;
1655
	}
1656
	else
1657
		qstack = q;
1658
 
1659
	/* retrieve the data from the database */
1660
	strcpy(fname, configs.home);			/* Base file name */
1661
	strcat(fname, MUSICDB);					/* File name of database */
1662
	rc = sqlite3_open(fname, &db);
1663
 
1664
	if (rc)
1665
	{
1666
		syslog(LOG_WARNING, "Error opening database %s: %s", fname, sqlite3_errmsg(db));
1667
		qstackDelete(ID);
1668
		return NULL;
1669
	}
1670
 
1671
	strcpy (query, "select id, path, type, title, interpret, album, genre, cover from \"main\".\"musicdb\" where ");
1672
	strcat(query, "id = ");
1673
	sprintf(hv0, "%d", ID);
1674
	strcat(query, hv0);
1675
 
1676
	if (sqlite3_prepare(db, query, -1, &res, NULL) != SQLITE_OK)
1677
	{
1678
		syslog(LOG_WARNING, "SQL error [%s]: %s", query, sqlite3_errmsg(db));
1679
		sqlite3_close(db);
1680
		qstackDelete(ID);
1681
		return NULL;
1682
	}
1683
 
1684
	rc = sqlite3_step(res);
1685
 
1686
	if ((p = (char *)sqlite3_column_text(res, 1)) == NULL)
1687
	{
1688
		syslog(LOG_WARNING, "Error getting path from database!");
1689
		sqlite3_finalize(res);
1690
		sqlite3_close(db);
1691
		qstackDelete(ID);
1692
		return NULL;
1693
	}
1694
	else
1695
		strncpy(q->path, p, sizeof(q->path));
1696
 
1697
	q->fType = sqlite3_column_int(res, 2);
1698
 
1699
	if ((p = (char *)sqlite3_column_text(res, 3)) == NULL)
1700
	{
1701
		syslog(LOG_WARNING, "Error getting title from database!");
1702
		sqlite3_finalize(res);
1703
		sqlite3_close(db);
1704
		qstackDelete(ID);
1705
		return NULL;
1706
	}
1707
	else
1708
		strncpy(q->title, p, sizeof(q->title));
1709
 
1710
	if ((p = (char *)sqlite3_column_text(res, 4)) == NULL)
1711
	{
1712
		syslog(LOG_WARNING, "Error getting artist from database!");
1713
		sqlite3_finalize(res);
1714
		sqlite3_close(db);
1715
		qstackDelete(ID);
1716
		return NULL;
1717
	}
1718
	else
1719
		strncpy(q->artist, p, sizeof(q->artist));
1720
 
1721
	if ((p = (char *)sqlite3_column_text(res, 5)) == NULL)
1722
	{
1723
		syslog(LOG_WARNING, "Error getting album from database!");
1724
		sqlite3_finalize(res);
1725
		sqlite3_close(db);
1726
		qstackDelete(ID);
1727
		return NULL;
1728
	}
1729
	else
1730
		strncpy(q->album, p, sizeof(q->album));
1731
 
1732
	if ((p = (char *)sqlite3_column_text(res, 6)) == NULL)
1733
	{
1734
		syslog(LOG_WARNING, "Error getting genre from database!");
1735
		sqlite3_finalize(res);
1736
		sqlite3_close(db);
1737
		qstackDelete(ID);
1738
		return NULL;
1739
	}
1740
	else
1741
		strncpy(q->genre, p, sizeof(q->genre));
1742
 
1743
	if ((p = (char *)sqlite3_column_text(res, 7)) != NULL)
1744
		strncpy(q->cover, p, sizeof(q->cover));
1745
 
1746
	sqlite3_finalize(res);
1747
	sqlite3_close(db);
1748
 
1749
	if (configs.debug)
1750
		syslog(LOG_DEBUG, "qstackAdd(): Added file >>%d:%s<< to stack.", q->id, q->path);
1751
 
1752
	return q;
1753
}
1754
 
1755
void qstackDelete(int ID)
1756
{
1757
QUEUE *q, *p;
1758
int flag;
1759
 
1760
	if (qstack == NULL)
1761
		return;
1762
 
1763
	q = p = qstack;
1764
	flag = 0;
1765
 
1766
	while (q)
1767
	{
1768
		QUEUE *act;
1769
 
1770
		if (q->id == ID)
1771
		{
1772
			act = q;
1773
			q = q->next;
1774
 
1775
			if (p != act)
1776
				p->next = q;
1777
			else
1778
				qstack = q;			/* if the the first entry is to delete, let qstack point to the second entry, if there is one. */
1779
 
1780
			free(q);
1781
 
1782
			if (configs.debug)
1783
				syslog(LOG_DEBUG, "qstackDelete(): Deleted ID %d from stack.", ID);
1784
 
1785
			return;
1786
		}
1787
 
1788
		q = q->next;
1789
 
1790
		if (flag)
1791
			p = p->next;
1792
		else
1793
			flag = 1;
1794
	}
1795
}
1796
 
1797
void qstackClear()
1798
{
1799
QUEUE *act, *q;
1800
 
1801
	act = qstack;
1802
 
1803
	while (act)
1804
	{
1805
		q = act->next;
1806
		free(act);
1807
		act = q;
1808
	}
1809
 
1810
	qstack = NULL;
1811
}
1812
 
1813
QUEUE* qstackNext()
1814
{
1815
QUEUE *act, *p;
1816
int flag;
1817
 
1818
	if (qstack == NULL)
1819
		return NULL;
1820
 
1821
	act = p = qstack;
1822
	flag = 0;
1823
 
1824
	while (act->next)
1825
	{
1826
		if (flag)
1827
			p = p->next;
1828
		else
1829
			flag = 1;
1830
 
1831
		act = act->next;
1832
	}
1833
 
1834
	if (act != p)
1835
		p->next = NULL;
1836
	else
1837
		qstack = NULL;
1838
 
1839
	if ((p = (QUEUE *)malloc(sizeof(QUEUE))) == NULL)
1840
	{
1841
		syslog(LOG_DAEMON, "Error allocating memory to get a stack entry: %s", strerror(errno));
1842
		free(act);
1843
		return NULL;
1844
	}
1845
 
1846
	if (configs.debug)
1847
		syslog(LOG_DEBUG, "qstackNext(): Pulled file >>%d:%s<< from stack.", act->id, act->path);
1848
 
1849
	memmove(p, act, sizeof(QUEUE));
1850
	free(act);
1851
	return p;
1852
}