-
Notifications
You must be signed in to change notification settings - Fork 127
/
Copy pathheadless.html
213 lines (211 loc) · 15 KB
/
headless.html
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta charset="utf-8" />
<meta name="generator" content="pandoc" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<title>PyRadio Headless Operation</title>
<style>
body {padding: 2em;}
@media screen and (max-width: 770px) {
body {padding: 10px;}
}
body {max-width: 750px; margin: auto;}
h2 {margin-top: 2.5em; border-bottom:1px solid SaddleBrown; color: SaddleBrown;}
h3 {margin-top: 2em; color: SaddleBrown; text-decoration: underline SaddleBrown}
h4 {margin: 2em 0 1em 0; color: SaddleBrown; font-size: 1em;}
h4:before {content: "# "; font-weight: bold; vertical-align: middle;}
h5 {margin: 2em 0 1em 0; color: SaddleBrown; font-size: 1em;;}
h5:before {content: "## "; font-weight: bold; vertical-align: middle;}
p, table, ol, ul {margin-left: .8em;}
STRONG {color: SaddleBrown;}
dl {margin: 2em;}
dd {margin: 1em;}
dt {font-weight: bold;}
TABLE {border: 1px solid SaddleBrown; border-collapse: collapse; margin-left: auto; margin-right: auto; border-radius: 5px; -moz-border-radius: 5px; border-collapse:separate; box-shadow: 5px 5px 15px #888888;}
TH {text-align: left; vertical-align: top; padding: 5px;color: SaddleBrown;border: 1px solid SaddleBrown; background-color: SaddleBrown; color: white;}
TD {text-align: left; vertical-align: top; padding: 5px 10px;border: 1px solid SaddleBrown;}
pre { background-color: rgba(245, 245, 245, 1); color: #474747; padding: 1.5em; border: 1px solid #C7C7C7; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; overflow: auto; box-shadow: 5px 5px 15px #C7C7C7;}
.task-list {list-style-type: none; padding: 0; margin: 0 0 0 1em ;}
img{display: block; margin-left: auto; margin-right: auto; max-width: 750px; width: 100%; background:transparent; padding:3px; border:1px solid #999999; border-radius: 5px; -moz-border-radius: 5px; -webkit-border-radius: 5px; box-shadow:5px 5px 15px #888888;}
.indented {text-indent: -1.5em; padding-left: 1.5em; margin-left: 1em;}
a{ color: SaddleBrown;}
a:visited{color: SaddleBrown;}
</style>
</head>
<body>
<header id="title-block-header">
</header>
<h1 style="color: SaddleBrown" id="pyradio-headless-operation">PyRadio Headless Operation</h1>
<h2 id="table-of-contents">Table of Contents <span style="padding-left: 10px;"><sup style="font-size: 50%"><a href="#" title="Go to top of the page">Top</a></sup></span></h2>
<!-- vim-markdown-toc Marked -->
<ul>
<li><a href="#goal">Goal</a>
<ul>
<li><a href="#usage">Usage</a></li>
<li><a href="#how-it-works">How it works</a></li>
</ul></li>
<li><a href="#installation">Installation</a>
<ul>
<li><a href="#notice">Notice</a></li>
<li><a href="#using-tmux">Using tmux</a>
<ul>
<li><a href="#systemd">systemd</a></li>
</ul></li>
<li><a href="#using-screen">Using screen</a>
<ul>
<li><a href="#systemd">systemd</a></li>
</ul></li>
<li><a href="#systemd-service-file">systemd service file</a></li>
<li><a href="#notice-for-systemd-installation">Notice for systemd installation</a></li>
</ul></li>
</ul>
<!-- vim-markdown-toc -->
<p class="indented">[ <a href="index.html#installation">Return to main doc</a> ]</p>
<h2 id="goal">Goal <span style="padding-left: 10px;"><sup style="font-size: 50%"><a href="#" title="Go to top of the page">Top</a></sup></span></h2>
<p>This is a document that provides info on running <strong>PyRadio</strong> in “<em>headless</em>” mode (well, kind of), on a Linux, BSD, or Pi system.</p>
<p>Now, <strong>PyRadio</strong> is a <strong>terminal application</strong>; it actually <strong>needs</strong> a terminal to run. But there is a way to make it run on a “terminal” and at the same time run in the background, being “invisible” so to speak, or run as a weird kind of a daemon; the way to do that is run it in a <strong>tmux detached session</strong> or a <strong>screen detached session</strong>.</p>
<p><strong>tmux</strong> man page reads:</p>
<p>“<strong>tmux</strong> is a terminal multiplexer: it enables a number of terminals to be created, accessed, and controlled from a single screen. tmux may be <strong>detached from a screen</strong> and continue running in the background, then later reattached.”</p>
<p><strong>screen</strong> man page reads:</p>
<p>“<strong>Screen</strong> is a full-screen window manager that multiplexes a physical terminal between several processes (typically interactive shells)… Programs continue to run when their window is currently not visible and even when the whole screen session <strong>is detached from the user’s terminal</strong>.”</p>
<p><strong>PyRadio</strong> users <a target="_blank" href="https://github.com/Wikinaut">Wikinaut</a> and <a target="_blank" href="https://github.com/aleksandr-sabitov">aleksandr-sabitov</a> on <a target="_blank" href="https://github.com/coderholic/pyradio/issues/184">github</a> have come up with the idea to use this approach to run the application on their headless Raspberry Pi, so kudos to them!</p>
<h3 id="usage">Usage</h3>
<p>After the program is started, the only way to interact with it is through its integrated web server. Please refer to the relevant document for more info on the <a href="server.html">remote control server</a>.</p>
<p>The web server can be accessed either through a terminal (address <strong>http://ip:port</strong>) using wget or curl, or through a web browser (address <strong>http://ip:port/html</strong>).</p>
<p>The ip and port will be set using the <strong>–headless</strong> command line option.</p>
<p>The ip can either be:</p>
<ol type="1">
<li><strong>localhost</strong><br />
The server will be accessible only by programs running in the system. The ip is 127.0.0.1.</li>
<li><strong>lan</strong><br />
The server will be accessible by any system on the LAN. The ip is the one assigned to the network interface of the system.</li>
<li>An actual <strong>IP</strong><br />
This is in case when a machine has more than one network interfaces and the <strong>lan</strong> setting is ambiguous.</li>
</ol>
<p>For example:</p>
<ul>
<li><p>using <strong>–headless lan:12345</strong><br />
will make the web server listen to the network interface IP address, port 12345.</p></li>
<li><p>using <strong>–headless 192.168.122.101:4567</strong><br />
will make the web server listen to the IP 192.168.122.101, port 4567.<br />
<br />
If the IP is not assigned to any network interfaces, the default (<strong>localhost:1111</strong>) will be silently used; please always check the server’s address with the command: <strong>pyradio –addr</strong>.</p></li>
<li><p>using <strong>–headless localhost:23456</strong><br />
will make the web server listen to 127.0.0.1, port 23456</p></li>
<li><p>using <strong>–headless auto</strong><br />
will make the web server listen to 127.0.0.1, port 11111; this is the default and fallback configuration.</p></li>
</ul>
<p>To get the server ip and port, execute on a terminal</p>
<pre>pyradio --addr</pre>
<p>Which will return something like:</p>
<pre>PyRadio Remote Control Server
Headless server
Text address: http://127.0.0.1:11111
HTML address: http://127.0.0.1:11111/html</pre>
<p>If both a “headless” and a normal instance of <strong>PyRadio</strong> is running, you will get something like this:</p>
<pre>PyRadio Remote Control Server
Headless server
Text address: http://127.0.0.1:11111
HTML address: http://127.0.0.1:11111/html
Server
Text address: http://127.0.0.1:9998
HTML address: http://127.0.0.1:9998/html</pre>
<h3 id="how-it-works">How it works</h3>
<p>When <strong>PyRadio</strong> is executed with the <strong>–headles</strong> command line option, it will basically start the web server and wait for connections.</p>
<p>To make it less memory hungry, the default (aka “<em>dark</em>” theme) will be loaded, and access to themes and the configuration window will be restricted.</p>
<p>Additionally, it will not create a “<em>session lock file</em>”, so that other instances of the program can be executed normally (in a terminal), and be able to function properly.</p>
<p>It will create a “headless server lock file”, though, so that</p>
<ul>
<li><p>we cannot start a second headless server, and</p></li>
<li><p>we can get info about the server running.</p></li>
</ul>
<p>The “headless server lock file” is saved as <em>~/.config/pyradio/data/server-headles.txt</em> (or <em>~/.local/share/pyradio/server-headles.txt</em> if <strong>xdg_compliant</strong> is set to True), and will contain the IP address and port the servers is listening to. This is especially useful in case a user script needs to get this info (instead of parsing the output of the command <strong>pyradio –addr</strong>).</p>
<h2 id="installation">Installation <span style="padding-left: 10px;"><sup style="font-size: 50%"><a href="#" title="Go to top of the page">Top</a></sup></span></h2>
<p>By the term “installation”, we mean that we set up things in such a way, that after we log into the system, we find <strong>PyRadio</strong> ready to accept connections.</p>
<p>So, the installation can be as easy as adding a line in a configuration file (or the startup section of the <em>desktop environment</em>) or as hard as adding a system service.</p>
<h3 id="notice">Notice</h3>
<p>The commands that follow use the following conventions:</p>
<ol type="1">
<li><p>The username is <strong>spiros</strong>.<br />
Please replace it with your username.</p></li>
<li><p><strong>PyRadio</strong> is installed from source; this means that its executable is <strong>~/.local/bin/pyradio</strong>. If this is not the case (using a distribution package, for example), please replace it with the correct one.</p></li>
<li><p>Both <strong>tmux</strong> and <strong>screen</strong> are executed using their <em>absolute path</em> (<strong>/usr/bin/tmux</strong> and <strong>/usr/bin/screen</strong> respectively). If they are installed at a different location, please use the correct one instead.</p></li>
</ol>
<h3 id="using-tmux">Using tmux</h3>
<p>If <strong>bash</strong> is the default shell, this would do the trick:</p>
<pre>echo "/usr/bin/tmux new-session \
-dA -s pyradio-session /home/spiros/.local/bin/pyradio \
--headless auto" >> ~/.profile</pre>
<p>In case a <em>Window manager</em> is used, adding a line in its <strong>autostart</strong> file would be enough. For example, this would work for <strong>openbox</strong>:</p>
<pre>echo "(sleep 10; /usr/bin/tmux new-session -dA -s pyradio-session /home/spiros/.local/bin/pyradio --headless auto)" >> ~/.config/openbox/autostart</pre>
<p>And so on, and so forth…</p>
<h4 id="systemd">systemd</h4>
<p>The first thing you do is to create the start file. Write this to <strong>~/.local/bin/start-headless-pyradio.sh</strong></p>
<pre>#!/bin/bash
touch ~/pyradio.log
/usr/bin/tmux new-session -dA -s pyradio-session /home/spiros/.local/bin/pyradio --headless auto</pre>
<p>Then create the stop file. Writhe this to <strong>~/.local/bin/stop-headless-pyradio.sh</strong></p>
<pre>#!/bin/bash
[ -z "$(/usr/bin/tmux ls | grep pyradio-session)" ] || /usr/bin/tmux send-keys -t pyradio-session q
sleep 2
[ -z "$(/usr/bin/tmux ls | grep pyradio-session)" ] || /usr/bin/tmux send-keys -t pyradio-session q
[ -e /home/spiros/.config/pyradio/data/server-headless.txt ] && rm /home/spiros/.config/pyradio/data/server-headless.txt
[ -e /home/spiros/.local/state/pyradio/server-headless.txt ] && rm /home/spiros/.local/state/pyradio/server-headless.txt</pre>
<p>Make both files executable:</p>
<pre>chmod +x ~/.local/bin/start-headless-pyradio.sh
chmod +x ~/.local/bin/stop-headless-pyradio.sh</pre>
<p>Now you are ready to create the <a href="#systemd-service-file">service file</a>.</p>
<h3 id="using-screen">Using screen</h3>
<p>If <strong>bash</strong> is the default shell, this would do the trick:</p>
<pre>echo "/usr/bin/screen -U -S pyradio-session -d -m \
/home/spiros/.local/bin/pyradio \
--headless auto" >> ~/.profile</pre>
<p>In case a <em>Window manager</em> is used, adding a line in its <strong>autostart</strong> file would be enough. For example, this would work for <strong>openbox</strong>:</p>
<pre>echo "(sleep 10; /usr/bin/screen -U -S pyradio-session -d -m /home/spiros/.local/bin/pyradio --headless auto)" >> ~/.config/openbox/autostart</pre>
<p>And so on, and so forth…</p>
<h4 id="systemd-1">systemd</h4>
<p>The first thing you do is create the log file:</p>
<pre>touch ~/pyradio.log</pre>
<p>Then create the start file. Write this to <strong>~/.local/bin/start-headless-pyradio.sh</strong></p>
<pre>#!/bin/bash
/usr/bin/screen -U -S pyradio-session -d -m /home/spiros/.local/bin/pyradio --headless auto</pre>
<p>Then create the stop file. Writhe this to <strong>~/.local/bin/stop-headless-pyradio.sh</strong></p>
<pre>#!/bin/bash
[ -z "$(/usr/bin/screen -ls | grep pyradio-session)" ] || /usr/bin/screen -S pyradio-session -p 0 -X stuff q
sleep 2
[ -z "$(/usr/bin/screen -ls | grep pyradio-session)" ] || /usr/bin/screen -S pyradio-session -p 0 -X stuff q
[ -e /home/spiros/.config/pyradio/data/server-headless.txt ] && rm /home/spiros/.config/pyradio/data/server-headless.txt
[ -e /home/spiros/.local/state/pyradio/server-headless.txt ] && rm /home/spiros/.local/state/pyradio/server-headless.txt
</pre>
<p>Make both files executable:</p>
<pre>chmod +x ~/.local/bin/start-headless-pyradio.sh
chmod +x ~/.local/bin/stop-headless-pyradio.sh</pre>
<p>Now you are ready to create the service file</p>
<h3 id="systemd-service-file">systemd service file</h3>
<p>Create the file <strong>/lib/systemd/system/pyradio.service</strong></p>
<pre>[Unit]
Description=PyRadio Service
After=multi-user.target
[Service]
Type=forking
User=spiros
Environment="XDG_RUNTIME_DIR=/run/user/1000"
Environment="PULSE_RUNTIME_PATH=/run/user/1000/pulse/"
StandardOutput=append:/home/spiros/pyradio.log
StandardError=append:/home/spiros/pyradio.log
ExecStart=/home/spiros/.local/bin/start-headless-pyradio.sh
ExecStop=/home/spiros/.local/bin/stop-headless-pyradio.sh
[Install]
WantedBy=multi-user.target</pre>
<p>Then execute:</p>
<pre>sudo chmod 644 /lib/systemd/system/pyradio.service
sudo systemctl daemon-reload
sudo systemctl enable pyradio # enabling the autostart on every boot</pre>
<h3 id="notice-for-systemd-installation">Notice for systemd installation</h3>
<p>The service file has two lines starting with “<em>Environment=</em>”</p>
<p>These two lines provide an environment for <em>systemd</em>; I’ve found out that on Arch Linux, for example, <strong>PyRadio</strong> would produce no sound at all without them (it would not be able to connect to the sound server).</p>
<p>Note that you may have to change the value <strong>1000</strong> to the one given by the <em>id</em> command; this is actually your <strong>uid</strong> (user id), which is set to 1000 by default on many distros.</p>
<p>On other systems, on Raspberry Pi for example, they can be omitted altogether.</p>
</body>
</html>