aboutsummaryrefslogtreecommitdiff
path: root/src/output/raop_output_plugin.h
blob: 6672cf8a0a18911c13519cb1cdfab66bfea3ca9c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
 * Copyright (C) 2003-2010 The Music Player Daemon Project
 * http://www.musicpd.org
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef MPD_OUTPUT_RAOP_PLUGIN_H
#define MPD_OUTPUT_RAOP_PLUGIN_H

#include <pthread.h>
#include <stdbool.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <openssl/aes.h>

struct key_data {
	unsigned char *key;
	unsigned char *data;
	struct key_data *next;
};

struct play_state {
	bool playing;
	unsigned short seq_num;
	unsigned int rtptime;
	unsigned int sync_src;
	unsigned int start_rtptime;
	struct timeval start_time;
	struct timeval last_send;
};

/*********************************************************************/

struct rtspcl_data {
	int fd;
	char url[128];
	int cseq;
	struct key_data *kd;
	struct key_data *exthds;
	char *session;
	char *transport;
	unsigned short server_port;
	unsigned short control_port;
	struct in_addr host_addr;
	struct in_addr local_addr;
	const char *useragent;

};

enum pause_state {
	NO_PAUSE = 0,
	OP_PAUSE,
	NODATA_PAUSE,
};

#define MINIMUM_SAMPLE_SIZE 32

#define RAOP_FD_READ (1<<0)
#define RAOP_FD_WRITE (1<<1)

/*********************************************************************/

struct encrypt_data {
	AES_KEY ctx;
	unsigned char iv[16]; // initialization vector for aes-cbc
	unsigned char nv[16]; // next vector for aes-cbc
	unsigned char key[16]; // key for aes-cbc
};

/*********************************************************************/

struct ntp_data {
	unsigned short port;
	int fd;
};

/*********************************************************************/

struct raop_data {
	struct rtspcl_data *rtspcl;
	const char *addr; // target host address
	short rtsp_port;
	struct sockaddr_in ctrl_addr;
	struct sockaddr_in data_addr;

	bool is_master;
	struct raop_data *next;

	unsigned volume;

	pthread_mutex_t control_mutex;

	bool started;
	bool paused;
};

/*********************************************************************/

struct control_data {
	unsigned short port;
	int fd;
};

bool
send_control_command(struct control_data *ctrl, struct raop_data *rd, struct play_state *state);

/*********************************************************************/

#define NUMSAMPLES 352
#define RAOP_BUFFER_SIZE NUMSAMPLES * 4
#define RAOP_HEADER_SIZE 12
#define ALAC_MAX_HEADER_SIZE 8
#define RAOP_MAX_PACKET_SIZE RAOP_BUFFER_SIZE + RAOP_HEADER_SIZE + ALAC_MAX_HEADER_SIZE

// session
struct raop_session_data {
	struct raop_data *raop_list;
	struct ntp_data ntp;
	struct control_data ctrl;
	struct encrypt_data encrypt;
	struct play_state play_state;

	int data_fd;

	unsigned char buffer[RAOP_BUFFER_SIZE];
	size_t bufferSize;

	unsigned char data[RAOP_MAX_PACKET_SIZE];
	int wblk_wsize;
	int wblk_remsize;

	pthread_mutex_t data_mutex;
	pthread_mutex_t list_mutex;
};

//static struct raop_session_data *raop_session;

/*********************************************************************/

bool
raop_set_volume(struct raop_data *rd, unsigned volume);

int
raop_get_volume(struct raop_data *rd);

#endif