Merge remote-tracking branch 'upstream/master' into gh-actions
This commit is contained in:
commit
4a36f85743
|
@ -12,10 +12,7 @@ define('COMPANY_SITE' , 'libretime.org');
|
|||
define('COMPANY_SITE_URL' , 'http://libretime.org');
|
||||
define('SUPPORT_ADDRESS' , 'https://discourse.libretime.org/');
|
||||
|
||||
define("AIRTIMEPRO_API_URL", "https://account.example.com:5001/api/");
|
||||
|
||||
define('HELP_URL' , 'https://discourse.libretime.org/');
|
||||
define('FAQ_URL' , 'http://libretime.org/faq');
|
||||
define('WHOS_USING_URL' , 'https://github.com/orgs/LibreTime/people');
|
||||
define('TERMS_AND_CONDITIONS_URL' , 'https://github.com/LibreTime/libretime/blob/master/README.md');
|
||||
define('PRIVACY_POLICY_URL' , 'https://github.com/LibreTime/code-of-conduct/blob/master/CODE_OF_CONDUCT.md');
|
||||
|
|
|
@ -163,11 +163,6 @@ $pages[] = array(
|
|||
'action' => 'help',
|
||||
'resource' => 'dashboard'
|
||||
),
|
||||
array(
|
||||
'label' => _('FAQ'),
|
||||
'uri' => FAQ_URL,
|
||||
'target' => "_blank"
|
||||
),
|
||||
array(
|
||||
'label' => _('User Manual'),
|
||||
'uri' => USER_MANUAL_URL,
|
||||
|
|
|
@ -90,7 +90,7 @@ class ScheduleController extends Zend_Controller_Action
|
|||
AirtimeTableView::injectTableJavaScriptDependencies($headScript, $baseUrl, $CC_CONFIG['airtime_version']);
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/moment.min.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/moment-timezone-with-data-2010-2020.min.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/libs/moment-timezone.min.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/utilities/utilities.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
||||
$this->view->headScript()->appendFile($baseUrl.'js/airtime/buttons/buttons.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
|
||||
|
|
|
@ -284,8 +284,8 @@ class Application_Model_StreamSetting
|
|||
'output' => 'icecast',
|
||||
'user' => $config['stationId'],
|
||||
'pass' => Application_Model_Preference::getDefaultIcecastPassword(),
|
||||
// Kind of ugly... convert prefix int to ascii char
|
||||
'mount' => $config['stationId'] . '_' . chr($prefix[1] + 96),
|
||||
// Manually setting default mountpoint
|
||||
'mount' => 'airtime_128',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
this.settings = {
|
||||
'elementId': id_element, // leave alone
|
||||
'autoplay': false, // or true (only works on some browsers)
|
||||
'forceHTTPS': true, // or true if the stream is in SSL (beware of the listening port, usually 8000)
|
||||
'replacePort':false, // false for disabled or '8000' as the usual start port, forces to specify replacePortTo.
|
||||
'replacePortTo':'' // either '' to use the default port of the browser (80/http, 443/https) or '8443' to force the port of the stream.
|
||||
'forceHTTPS': false, // or true if the stream is in SSL (beware of the listening port, usually 8000)
|
||||
'replacePort': false, // false for disabled or '8000' as the usual start port, forces to specify replacePortTo.
|
||||
'replacePortTo': '' // either '' to use the default port of the browser (80/http, 443/https) or '8443' to force the port of the stream.
|
||||
};
|
||||
|
||||
if (this.playerMode == "manual") {
|
||||
|
@ -109,7 +109,7 @@
|
|||
|
||||
Html5Player.prototype.play = function() {
|
||||
console.log('play');
|
||||
playerhtml5_audio.src = this.settings.url+'?'+Math.floor(Math.random() * Math.floor(100000));
|
||||
playerhtml5_audio.src = this.settings.url;
|
||||
playerhtml5_audio.play();
|
||||
togglePlayStopButton();
|
||||
};
|
||||
|
@ -267,4 +267,4 @@
|
|||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -36,11 +36,12 @@ If the service isn't wanting to restart, look at its status for clues as to why
|
|||
|
||||
> If you find yourself constantly needing to restart a service, there's a chance it was never set to autostart on system boot. Use `sudo systemctl enable servicename` to fix this problem.
|
||||
|
||||
## 3. Basic troubleshooting
|
||||
## 3. Known problems
|
||||
|
||||
If you have one of these issues, please try to resolve it with the instructions below before moving on in the
|
||||
troubleshooting checklist.
|
||||
|
||||
- **Streaming player on Microsite and Listen player on Dashboard not working?** The problem could be caused by a bug in writing to the database during the setup wizard. This can be fixed by going to **Settings** -> **Stream Settings** and toggling the **Default Streaming** and **Custom/ 3rd Party Streaming** option, accepting the popup dialogues, and clicking **Save** at the top of the settings page.
|
||||
- **File not importing successfully?** Libretime has been known to work with MP3 and WAV files, encoded using 41,100 Hz. Variable Bit Rate (VBR) files are currently hit or miss with the importer. Please convert your file to an MP3 or WAV at 41,100 Hz. and try uploading again.
|
||||
- **Podcast hosted by Anchor.fm not importing?** There is no known work-around at this time. Ask your producers to provide their show files manually or check with the show's distributer.
|
||||
- **Tracks won't publish?** We know the Publish screen is broken and we're working on it. A potential work-around is to use an external podcast host like [Anchor.fm](https://www.anchor.fm) or [Blubrry](https://blubrry.com/).
|
||||
|
|
|
@ -34,7 +34,7 @@ s2_namespace = ref ''
|
|||
s3_namespace = ref ''
|
||||
just_switched = ref false
|
||||
|
||||
%include "ls_lib_legacy.liq"
|
||||
%include "ls_lib.liq"
|
||||
|
||||
sources = ref []
|
||||
source_id = ref 0
|
|
@ -0,0 +1,24 @@
|
|||
if bitrate == 24 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 24, aot="mpeg4_he_aac_v2", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 32 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 32, aot="mpeg4_he_aac_v2", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 48 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 48, aot="mpeg4_he_aac_v2", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 64 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 64, aot="mpeg4_he_aac_v2", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 96 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 96, aot="mpeg4_aac_lc", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 128 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 128, aot="mpeg4_aac_lc", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 160 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 160, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
elsif bitrate == 192 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 192, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
elsif bitrate == 224 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 224, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
elsif bitrate == 256 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 256, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
elsif bitrate == 320 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 320, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
end
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
if bitrate == 24 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 24, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 24, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 32 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 32, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 32, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 48 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 48, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 48, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 64 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 64, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 64, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 96 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 96, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 96, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 128 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 128, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 128, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 160 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 160, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 160, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 192 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 192, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 192, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 224 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 224, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 224, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 256 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 256, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 256, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 320 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 320, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 320, stereo = false), mean(!source)))
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
if not icecast_vorbis_metadata then
|
||||
source := add(normalize=false, [amplify(0.00001, noise()), !source])
|
||||
end
|
||||
|
||||
if bitrate == 24 or bitrate == 32 or bitrate == 48 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=-0.1, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=-0.1, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 64 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 96 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.2, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.2, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 128 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.4, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.4, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 160 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.5, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.5, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 192 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.6, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.6, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 224 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.7, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.7, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 256 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.8, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.8, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 320 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.9, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.9, channels = 1), mean(!source)))
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
if bitrate == 24 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 24, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 24, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 32 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 32, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 32, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 48 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 48, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 48, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 64 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 64, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 64, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 96 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 96, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 96, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 128 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 128, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 128, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 160 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 160, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 160, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 192 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 192, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 192, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 224 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 224, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 224, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 256 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 256, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 256, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 320 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 320, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 320, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
if bitrate == 24 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 24, aot="mpeg4_he_aac_v2", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 32 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 32, aot="mpeg4_he_aac_v2", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 48 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 48, aot="mpeg4_he_aac_v2", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 64 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 64, aot="mpeg4_he_aac_v2", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 96 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 96, aot="mpeg4_aac_lc", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 128 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 128, aot="mpeg4_aac_lc", afterburner=false, sbr_mode=true), !source))
|
||||
elsif bitrate == 160 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 160, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
elsif bitrate == 192 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 192, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
elsif bitrate == 224 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 224, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
elsif bitrate == 256 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 256, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
elsif bitrate == 320 then
|
||||
ignore(output_stereo(%fdkaac(bitrate = 320, aot="mpeg4_aac_lc", afterburner=true, sbr_mode=true), !source))
|
||||
end
|
||||
|
|
@ -0,0 +1,389 @@
|
|||
def notify(m)
|
||||
command = "timeout --signal=KILL 45 pyponotify --media-id=#{m['schedule_table_id']} &"
|
||||
log(command)
|
||||
system(command)
|
||||
end
|
||||
|
||||
def notify_queue(m)
|
||||
f = !dynamic_metadata_callback
|
||||
ignore(f(m))
|
||||
notify(m)
|
||||
end
|
||||
|
||||
def notify_stream(m)
|
||||
json_str = string.replace(pattern="\n",(fun (s) -> ""), json_of(m))
|
||||
#if a string has a single apostrophe in it, let's comment it out by ending the string before right before it
|
||||
#escaping the apostrophe, and then starting a new string right after it. This is why we use 3 apostrophes.
|
||||
json_str = string.replace(pattern="'",(fun (s) -> "'\''"), json_str)
|
||||
command = "timeout --signal=KILL 45 pyponotify --webstream='#{json_str}' --media-id=#{!current_dyn_id} &"
|
||||
|
||||
if !current_dyn_id != "-1" then
|
||||
log(command)
|
||||
system(command)
|
||||
end
|
||||
end
|
||||
|
||||
# A function applied to each metadata chunk
|
||||
def append_title(m) =
|
||||
log("Using stream_format #{!stream_metadata_type}")
|
||||
|
||||
if list.mem_assoc("mapped", m) then
|
||||
#protection against applying this function twice. It shouldn't be happening
|
||||
#and bug file with Liquidsoap.
|
||||
m
|
||||
else
|
||||
if !stream_metadata_type == 1 then
|
||||
[("title", "#{!show_name} - #{m['artist']} - #{m['title']}"), ("mapped", "true")]
|
||||
elsif !stream_metadata_type == 2 then
|
||||
[("title", "#{!station_name} - #{!show_name}"), ("mapped", "true")]
|
||||
else
|
||||
if "#{m['artist']}" == "" then
|
||||
[("title", "#{m['title']}"), ("mapped", "true")]
|
||||
else
|
||||
[("title", "#{m['artist']} - #{m['title']}"), ("mapped", "true")]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def transition(a,b) =
|
||||
log("transition called...")
|
||||
add(normalize=false,
|
||||
[ sequence([ blank(duration=0.01),
|
||||
fade.initial(duration=!default_dj_fade, b) ]),
|
||||
fade.final(duration=!default_dj_fade, a) ])
|
||||
end
|
||||
|
||||
# we need this function for special transition case(from default to queue)
|
||||
# we don't want the trasition fade to have effect on the first song that would
|
||||
# be played siwtching out of the default(silent) source
|
||||
def transition_default(a,b) =
|
||||
log("transition called...")
|
||||
if !just_switched then
|
||||
just_switched := false
|
||||
add(normalize=false,
|
||||
[ sequence([ blank(duration=0.01),
|
||||
fade.initial(duration=!default_dj_fade, b) ]),
|
||||
fade.final(duration=!default_dj_fade, a) ])
|
||||
else
|
||||
just_switched := false
|
||||
b
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Define a transition that fades out the
|
||||
# old source, adds a single, and then
|
||||
# plays the new source
|
||||
def to_live(old,new) =
|
||||
# Fade out old source
|
||||
old = fade.final(old)
|
||||
# Compose this in sequence with
|
||||
# the new source
|
||||
sequence([old,new])
|
||||
end
|
||||
|
||||
|
||||
def output_to(output_type, type, bitrate, host, port, pass, mount_point, url, description, genre, user, s, stream, connected, name, channels) =
|
||||
source = ref s
|
||||
def on_error(msg)
|
||||
connected := "false"
|
||||
command = "timeout --signal=KILL 45 pyponotify --error='#{msg}' --stream-id=#{stream} --time=#{!time} &"
|
||||
system(command)
|
||||
log(command)
|
||||
5.
|
||||
end
|
||||
def on_connect()
|
||||
connected := "true"
|
||||
command = "timeout --signal=KILL 45 pyponotify --connect --stream-id=#{stream} --time=#{!time} &"
|
||||
system(command)
|
||||
log(command)
|
||||
end
|
||||
|
||||
stereo = (channels == "stereo")
|
||||
|
||||
if output_type == "icecast" then
|
||||
user_ref = ref user
|
||||
if user == "" then
|
||||
user_ref := "source"
|
||||
end
|
||||
output_mono = output.icecast(host = host,
|
||||
port = port,
|
||||
password = pass,
|
||||
mount = mount_point,
|
||||
fallible = true,
|
||||
url = url,
|
||||
description = description,
|
||||
name = name,
|
||||
genre = genre,
|
||||
user = !user_ref,
|
||||
on_error = on_error,
|
||||
on_connect = on_connect)
|
||||
|
||||
output_stereo = output.icecast(host = host,
|
||||
port = port,
|
||||
password = pass,
|
||||
mount = mount_point,
|
||||
fallible = true,
|
||||
url = url,
|
||||
description = description,
|
||||
name = name,
|
||||
genre = genre,
|
||||
user = !user_ref,
|
||||
on_error = on_error,
|
||||
on_connect = on_connect)
|
||||
if type == "mp3" then
|
||||
%include "mp3.liq"
|
||||
end
|
||||
if type == "ogg" then
|
||||
%include "ogg.liq"
|
||||
end
|
||||
|
||||
%ifencoder %opus
|
||||
if type == "opus" then
|
||||
%include "opus.liq"
|
||||
end
|
||||
%endif
|
||||
|
||||
%ifencoder %fdkaac
|
||||
if type == "aac" then
|
||||
%include "fdkaac.liq"
|
||||
end
|
||||
%endif
|
||||
else
|
||||
user_ref = ref user
|
||||
if user == "" then
|
||||
user_ref := "source"
|
||||
end
|
||||
|
||||
output_mono = output.shoutcast(id = "shoutcast_stream_#{stream}",
|
||||
host = host,
|
||||
port = port,
|
||||
password = pass,
|
||||
fallible = true,
|
||||
url = url,
|
||||
genre = genre,
|
||||
name = description,
|
||||
user = !user_ref,
|
||||
on_error = on_error,
|
||||
on_connect = on_connect)
|
||||
|
||||
output_stereo = output.shoutcast(id = "shoutcast_stream_#{stream}",
|
||||
host = host,
|
||||
port = port,
|
||||
password = pass,
|
||||
fallible = true,
|
||||
url = url,
|
||||
genre = genre,
|
||||
name = description,
|
||||
user = !user_ref,
|
||||
on_error = on_error,
|
||||
on_connect = on_connect)
|
||||
|
||||
if type == "mp3" then
|
||||
%include "mp3.liq"
|
||||
end
|
||||
|
||||
%ifencoder %fdkaac
|
||||
if type == "aac" then
|
||||
%include "fdkaac.liq"
|
||||
end
|
||||
%endif
|
||||
end
|
||||
end
|
||||
|
||||
# Add a skip function to a source
|
||||
# when it does not have one
|
||||
# by default
|
||||
#def add_skip_command(s)
|
||||
# # A command to skip
|
||||
# def skip(_)
|
||||
# # get playing (active) queue and flush it
|
||||
# l = list.hd(server.execute("queue.secondary_queue"))
|
||||
# l = string.split(separator=" ",l)
|
||||
# list.iter(fun (rid) -> ignore(server.execute("queue.remove #{rid}")), l)
|
||||
#
|
||||
# l = list.hd(server.execute("queue.primary_queue"))
|
||||
# l = string.split(separator=" ", l)
|
||||
# if list.length(l) > 0 then
|
||||
# source.skip(s)
|
||||
# "Skipped"
|
||||
# else
|
||||
# "Not skipped"
|
||||
# end
|
||||
# end
|
||||
# # Register the command:
|
||||
# server.register(namespace="source",
|
||||
# usage="skip",
|
||||
# description="Skip the current song.",
|
||||
# "skip",fun(s) -> begin log("source.skip") skip(s) end)
|
||||
#end
|
||||
|
||||
def clear_queue(s)
|
||||
source.skip(s)
|
||||
end
|
||||
|
||||
def set_dynamic_source_id(id) =
|
||||
current_dyn_id := id
|
||||
string_of(!current_dyn_id)
|
||||
end
|
||||
|
||||
def get_dynamic_source_id() =
|
||||
string_of(!current_dyn_id)
|
||||
end
|
||||
|
||||
#cc-4633
|
||||
|
||||
|
||||
# NOTE
|
||||
# A few values are hardcoded and may be dependent:
|
||||
# - the delay in gracetime is linked with the buffer duration of input.http
|
||||
# (delay should be a bit less than buffer)
|
||||
# - crossing duration should be less than buffer length
|
||||
# (at best, a higher duration will be ineffective)
|
||||
|
||||
# HTTP input with "restart" command that waits for "stop" to be effected
|
||||
# before "start" command is issued. Optionally it takes a new URL to play,
|
||||
# which makes it a convenient replacement for "url".
|
||||
# In the future, this may become a core feature of the HTTP input.
|
||||
# TODO If we stop and restart quickly several times in a row,
|
||||
# the data bursts accumulate and create buffer overflow.
|
||||
# Flushing the buffer on restart could be a good idea, but
|
||||
# it would also create an interruptions while the buffer is
|
||||
# refilling... on the other hand, this would avoid having to
|
||||
# fade using both cross() and switch().
|
||||
def input.http_restart(~id,~initial_url="http://dummy/url")
|
||||
|
||||
source = audio_to_stereo(input.http(buffer=5.,max=15.,id=id,autostart=false,initial_url))
|
||||
|
||||
def stopped()
|
||||
"stopped" == list.hd(server.execute("#{id}.status"), default="")
|
||||
end
|
||||
|
||||
server.register(namespace=id,
|
||||
"restart",
|
||||
usage="restart [url]",
|
||||
fun (url) -> begin
|
||||
if url != "" then
|
||||
log(string_of(server.execute("#{id}.url #{url}")))
|
||||
end
|
||||
log(string_of(server.execute("#{id}.stop")))
|
||||
add_timeout(0.5,
|
||||
{ if stopped() then
|
||||
log(string_of(server.execute("#{id}.start"))) ;
|
||||
(-1.)
|
||||
else 0.5 end})
|
||||
"OK"
|
||||
end)
|
||||
|
||||
# Dummy output should be useless if HTTP stream is meant
|
||||
# to be listened to immediately. Otherwise, apply it.
|
||||
#
|
||||
# output.dummy(fallible=true,source)
|
||||
|
||||
source
|
||||
|
||||
end
|
||||
|
||||
# Transitions between URL changes in HTTP streams.
|
||||
def cross_http(~debug=true,~http_input_id,source)
|
||||
|
||||
id = http_input_id
|
||||
last_url = ref ""
|
||||
change = ref false
|
||||
|
||||
def on_m(m)
|
||||
notify_stream(m)
|
||||
changed = m["source_url"] != !last_url
|
||||
log("URL now #{m['source_url']} (change: #{changed})")
|
||||
if changed then
|
||||
if !last_url != "" then change := true end
|
||||
last_url := m["source_url"]
|
||||
end
|
||||
end
|
||||
|
||||
# We use both metadata and status to know about the current URL.
|
||||
# Using only metadata may be more precise is crazy corner cases,
|
||||
# but it's also asking too much: the metadata may not pass through
|
||||
# before the crosser is instantiated.
|
||||
# Using only status in crosser misses some info, eg. on first URL.
|
||||
source = on_metadata(on_m,source)
|
||||
|
||||
cross_d = 3.
|
||||
|
||||
def crosser(a,b,ma,mb,sa,sb)
|
||||
url = list.hd(server.execute('#{id}.url'), default="")
|
||||
status = list.hd(server.execute('#{id}.status'))
|
||||
on_m([("source_url",url)])
|
||||
if debug then
|
||||
log("New track inside HTTP stream")
|
||||
log(" status: #{status}")
|
||||
log(" need to cross: #{!change}")
|
||||
log(" remaining #{source.remaining(sa)} sec before, \
|
||||
#{source.remaining(sb)} sec after")
|
||||
end
|
||||
if !change then
|
||||
change := false
|
||||
# In principle one should avoid crossing on a live stream
|
||||
# it'd be okay to do it here (eg. use add instead of sequence)
|
||||
# because it's only once per URL, but be cautious.
|
||||
sequence([fade.out(duration=cross_d,sa),fade.in(sb)])
|
||||
else
|
||||
# This is done on tracks inside a single stream.
|
||||
# Do NOT cross here or you'll gradually empty the buffer!
|
||||
sequence([sa,sb])
|
||||
end
|
||||
end
|
||||
|
||||
# Setting conservative=true would mess with the delayed switch below
|
||||
cross(duration=cross_d,conservative=false,crosser,source)
|
||||
end
|
||||
|
||||
# Custom fallback between http and default source with fading of
|
||||
# beginning and end of HTTP stream.
|
||||
# It does not take potential URL changes into account, as long as
|
||||
# they do not interrupt streaming (thanks to the HTTP buffer).
|
||||
def http_fallback(~http_input_id,~http,~default)
|
||||
|
||||
id = http_input_id
|
||||
|
||||
# We use a custom switching predicate to trigger switching (and thus,
|
||||
# transitions) before the end of a track (rather, end of HTTP stream).
|
||||
# It is complexified because we don't want to trigger switching when
|
||||
# HTTP disconnects for just an instant, when changing URL: for that
|
||||
# we use gracetime below.
|
||||
|
||||
def gracetime(~delay=3.,f)
|
||||
last_true = ref 0.
|
||||
{ if f() then
|
||||
last_true := gettimeofday()
|
||||
true
|
||||
else
|
||||
gettimeofday() < !last_true+delay
|
||||
end }
|
||||
end
|
||||
|
||||
def connected()
|
||||
status = list.hd(server.execute("#{id}.status"), default="")
|
||||
not(list.mem(status,["polling","stopped"]))
|
||||
end
|
||||
connected = gracetime(connected)
|
||||
|
||||
def to_live(a,b) =
|
||||
log("TRANSITION to live")
|
||||
add(normalize=false,
|
||||
[fade.initial(b),fade.final(a)])
|
||||
end
|
||||
def to_static(a,b) =
|
||||
log("TRANSITION to static")
|
||||
sequence([fade.out(a),fade.initial(b)])
|
||||
end
|
||||
|
||||
switch(
|
||||
track_sensitive=false,
|
||||
transitions=[to_live,to_static],
|
||||
[(# make sure it is connected, and not buffering
|
||||
{connected() and source.is_ready(http) and !webstream_enabled}, http),
|
||||
({true},default)])
|
||||
|
||||
end
|
|
@ -0,0 +1,462 @@
|
|||
%include "/etc/airtime/liquidsoap.cfg"
|
||||
|
||||
set("log.file.path", log_file)
|
||||
set("server.telnet", true)
|
||||
set("server.telnet.port", 1234)
|
||||
# set("init.daemon.pidfile.path", "/var/run/airtime/airtime-liquidsoap.pid")
|
||||
|
||||
|
||||
#Dynamic source list
|
||||
#dyn_sources = ref []
|
||||
webstream_enabled = ref false
|
||||
|
||||
time = ref string_of(gettimeofday())
|
||||
|
||||
#live stream setup
|
||||
set("harbor.bind_addr", "0.0.0.0")
|
||||
|
||||
current_dyn_id = ref '-1'
|
||||
|
||||
pypo_data = ref '0'
|
||||
stream_metadata_type = ref 0
|
||||
default_dj_fade = ref 0.
|
||||
station_name = ref ''
|
||||
show_name = ref ''
|
||||
|
||||
dynamic_metadata_callback = ref fun (~new_track=false, s) -> begin () end
|
||||
|
||||
s1_connected = ref ''
|
||||
s2_connected = ref ''
|
||||
s3_connected = ref ''
|
||||
s4_connected = ref ''
|
||||
s1_namespace = ref ''
|
||||
s2_namespace = ref ''
|
||||
s3_namespace = ref ''
|
||||
just_switched = ref false
|
||||
|
||||
%include "ls_lib.liq"
|
||||
|
||||
sources = ref []
|
||||
source_id = ref 0
|
||||
|
||||
def check_version(~version=liquidsoap.version, major, minor) =
|
||||
v = list.map(int_of_string, string.split(separator="\.", version))
|
||||
list.nth(v,0,default=0) > major or list.nth(v,0,default=0) == major and list.nth(v,1,default=0) >= minor
|
||||
end
|
||||
|
||||
# cue cut fix for liquidsoap <1.2.2
|
||||
#
|
||||
# This was most likely broken on 1.1.1 (debian) as well.
|
||||
#
|
||||
# adapted from https://github.com/savonet/liquidsoap/issues/390#issuecomment-277562081
|
||||
#
|
||||
def fix_cue_in(~cue_in_metadata='liq_cue_in', m) =
|
||||
# 0.04 might need to be adjusted according to your frame size
|
||||
if float_of_string(m[cue_in_metadata]) < 0.04 then
|
||||
[(cue_in_metadata, "0")]
|
||||
else
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
def create_source()
|
||||
l = request.equeue(id="s#{!source_id}", length=0.5)
|
||||
|
||||
l = audio_to_stereo(id="queue_src", l)
|
||||
|
||||
l = if not check_version(1, 3) then
|
||||
map_metadata(fix_cue_in, l)
|
||||
else
|
||||
l
|
||||
end
|
||||
l = cue_cut(l)
|
||||
l = amplify(1., override="replay_gain", l)
|
||||
|
||||
# the crossfade function controls fade in/out
|
||||
l = crossfade(duration=0., smart=true, l)
|
||||
|
||||
l = on_metadata(notify_queue, l)
|
||||
|
||||
sources := list.append([l], !sources)
|
||||
server.register(namespace="queues",
|
||||
"s#{!source_id}_skip",
|
||||
fun (s) -> begin log("queues.s#{!source_id}_skip")
|
||||
clear_queue(l)
|
||||
"Done"
|
||||
end)
|
||||
source_id := !source_id + 1
|
||||
end
|
||||
|
||||
create_source()
|
||||
create_source()
|
||||
create_source()
|
||||
create_source()
|
||||
|
||||
create_source()
|
||||
create_source()
|
||||
create_source()
|
||||
create_source()
|
||||
|
||||
queue = add(!sources, normalize=false)
|
||||
pair = insert_metadata(queue)
|
||||
dynamic_metadata_callback := fst(pair)
|
||||
queue = snd(pair)
|
||||
|
||||
output.dummy(fallible=true, queue)
|
||||
|
||||
http = input.http_restart(id="http")
|
||||
http = cross_http(http_input_id="http",http)
|
||||
output.dummy(fallible=true, http)
|
||||
stream_queue = http_fallback(http_input_id="http", http=http, default=queue)
|
||||
stream_queue = map_metadata(update=false, append_title, stream_queue)
|
||||
|
||||
ignore(output.dummy(stream_queue, fallible=true))
|
||||
|
||||
server.register(namespace="vars",
|
||||
"pypo_data",
|
||||
fun (s) -> begin log("vars.pypo_data") pypo_data := s "Done" end)
|
||||
server.register(namespace="vars",
|
||||
"stream_metadata_type",
|
||||
fun (s) -> begin log("vars.stream_metadata_type") stream_metadata_type := int_of_string(s) s end)
|
||||
server.register(namespace="vars",
|
||||
"show_name",
|
||||
fun (s) -> begin log("vars.show_name") show_name := s s end)
|
||||
server.register(namespace="vars",
|
||||
"station_name",
|
||||
fun (s) -> begin log("vars.station_name") station_name := s s end)
|
||||
server.register(namespace="vars",
|
||||
"bootup_time",
|
||||
fun (s) -> begin log("vars.bootup_time") time := s s end)
|
||||
server.register(namespace="streams",
|
||||
"connection_status",
|
||||
fun (s) -> begin log("streams.connection_status") "1:#{!s1_connected},2:#{!s2_connected},3:#{!s3_connected},4:#{!s4_connected}" end)
|
||||
server.register(namespace="vars",
|
||||
"default_dj_fade",
|
||||
fun (s) -> begin log("vars.default_dj_fade") default_dj_fade := float_of_string(s) s end)
|
||||
|
||||
server.register(namespace="dynamic_source",
|
||||
description="Enable webstream output",
|
||||
usage='start',
|
||||
"output_start",
|
||||
fun (s) -> begin log("dynamic_source.output_start")
|
||||
notify([("schedule_table_id", !current_dyn_id)])
|
||||
webstream_enabled := true "enabled" end)
|
||||
server.register(namespace="dynamic_source",
|
||||
description="Enable webstream output",
|
||||
usage='stop',
|
||||
"output_stop",
|
||||
fun (s) -> begin log("dynamic_source.output_stop") webstream_enabled := false "disabled" end)
|
||||
|
||||
server.register(namespace="dynamic_source",
|
||||
description="Set the streams cc_schedule row id",
|
||||
usage="id <id>",
|
||||
"id",
|
||||
fun (s) -> begin log("dynamic_source.id") set_dynamic_source_id(s) end)
|
||||
|
||||
server.register(namespace="dynamic_source",
|
||||
description="Get the streams cc_schedule row id",
|
||||
usage="get_id",
|
||||
"get_id",
|
||||
fun (s) -> begin log("dynamic_source.get_id") get_dynamic_source_id() end)
|
||||
|
||||
#server.register(namespace="dynamic_source",
|
||||
# description="Start a new dynamic source.",
|
||||
# usage="start <uri>",
|
||||
# "read_start",
|
||||
# fun (uri) -> begin log("dynamic_source.read_start") begin_stream_read(uri) end)
|
||||
#server.register(namespace="dynamic_source",
|
||||
# description="Stop a dynamic source.",
|
||||
# usage="stop <id>",
|
||||
# "read_stop",
|
||||
# fun (s) -> begin log("dynamic_source.read_stop") stop_stream_read(s) end)
|
||||
|
||||
#server.register(namespace="dynamic_source",
|
||||
# description="Stop a dynamic source.",
|
||||
# usage="stop <id>",
|
||||
# "read_stop_all",
|
||||
# fun (s) -> begin log("dynamic_source.read_stop") destroy_dynamic_source_all() end)
|
||||
|
||||
default = amplify(id="silence_src", 0.00001, noise())
|
||||
ref_off_air_meta = ref off_air_meta
|
||||
if !ref_off_air_meta == "" then
|
||||
ref_off_air_meta := "LibreTime - offline"
|
||||
end
|
||||
def map_off_air_meta(m) =
|
||||
[("title", !ref_off_air_meta)]
|
||||
end
|
||||
default = map_metadata(map_off_air_meta, default)
|
||||
ignore(output.dummy(default, fallible=true))
|
||||
|
||||
master_dj_enabled = ref false
|
||||
live_dj_enabled = ref false
|
||||
scheduled_play_enabled = ref false
|
||||
|
||||
def make_master_dj_available()
|
||||
master_dj_enabled := true
|
||||
end
|
||||
|
||||
def make_master_dj_unavailable()
|
||||
master_dj_enabled := false
|
||||
end
|
||||
|
||||
def make_live_dj_available()
|
||||
live_dj_enabled := true
|
||||
end
|
||||
|
||||
def make_live_dj_unavailable()
|
||||
live_dj_enabled := false
|
||||
end
|
||||
|
||||
def make_scheduled_play_available()
|
||||
scheduled_play_enabled := true
|
||||
just_switched := true
|
||||
end
|
||||
|
||||
def make_scheduled_play_unavailable()
|
||||
scheduled_play_enabled := false
|
||||
end
|
||||
|
||||
def update_source_status(sourcename, status) =
|
||||
command = "timeout --signal=KILL 45 pyponotify --source-name=#{sourcename} --source-status=#{status} &"
|
||||
system(command)
|
||||
log(command)
|
||||
end
|
||||
|
||||
def live_dj_connect(header) =
|
||||
update_source_status("live_dj", true)
|
||||
end
|
||||
|
||||
def live_dj_disconnect() =
|
||||
update_source_status("live_dj", false)
|
||||
end
|
||||
|
||||
def master_dj_connect(header) =
|
||||
update_source_status("master_dj", true)
|
||||
end
|
||||
|
||||
def master_dj_disconnect() =
|
||||
update_source_status("master_dj", false)
|
||||
end
|
||||
|
||||
# Auth function for live stream
|
||||
# @Category LiveStream
|
||||
# @param user Username to check against LibreTime API
|
||||
# @param password Password to check against LibreTime API
|
||||
# @param ~type Type of password to check, "dj" or "master, default: "master"
|
||||
def check_auth(user="", password="", ~type="master") =
|
||||
log("#{type} user #{user} connected",label="#{type}_source")
|
||||
|
||||
# Check auth based on return value from auth script
|
||||
ret = test_process("python3 #{auth_path} --#{type} #{user} #{password}")
|
||||
|
||||
if ret then
|
||||
log("#{type} user #{user} authenticated",label="#{type}_source")
|
||||
else
|
||||
log("#{type} user #{user} auth failed",label="#{type}_source",level=2)
|
||||
end
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
# Check master source auth
|
||||
# @Category LiveStream
|
||||
# @param user Username to check against LibreTime API
|
||||
# @param password Password to check against LibreTime API
|
||||
def check_master_dj_client(user, password) =
|
||||
check_auth(user, password)
|
||||
end
|
||||
|
||||
# Check dj/show source auth
|
||||
# @Category LiveStream
|
||||
# @param user Username to check against LibreTime API
|
||||
# @param password Password to check against LibreTime API
|
||||
def check_dj_client(user, password) =
|
||||
check_auth(user, password, type="dj")
|
||||
end
|
||||
|
||||
s = switch(id="schedule_noise_switch",
|
||||
track_sensitive=false,
|
||||
transitions=[transition_default, transition],
|
||||
[({!scheduled_play_enabled}, stream_queue), ({true}, default)]
|
||||
)
|
||||
|
||||
s = if dj_live_stream_port != 0 and dj_live_stream_mp != "" then
|
||||
dj_live =
|
||||
audio_to_stereo(
|
||||
input.harbor(id="live_dj_harbor",
|
||||
dj_live_stream_mp,
|
||||
port=dj_live_stream_port,
|
||||
auth=check_dj_client,
|
||||
max=40.,
|
||||
on_connect=live_dj_connect,
|
||||
on_disconnect=live_dj_disconnect))
|
||||
|
||||
ignore(output.dummy(dj_live, fallible=true))
|
||||
|
||||
switch(id="show_schedule_noise_switch",
|
||||
track_sensitive=false,
|
||||
transitions=[transition, transition],
|
||||
[({!live_dj_enabled}, dj_live), ({true}, s)]
|
||||
)
|
||||
else
|
||||
s
|
||||
end
|
||||
|
||||
s = if master_live_stream_port != 0 and master_live_stream_mp != "" then
|
||||
master_dj =
|
||||
audio_to_stereo(
|
||||
input.harbor(id="master_harbor",
|
||||
master_live_stream_mp,
|
||||
port=master_live_stream_port,
|
||||
auth=check_master_dj_client,
|
||||
max=40.,
|
||||
on_connect=master_dj_connect,
|
||||
on_disconnect=master_dj_disconnect))
|
||||
|
||||
ignore(output.dummy(master_dj, fallible=true))
|
||||
|
||||
switch(id="master_show_schedule_noise_switch",
|
||||
track_sensitive=false,
|
||||
transitions=[transition, transition],
|
||||
[({!master_dj_enabled}, master_dj), ({true}, s)]
|
||||
)
|
||||
else
|
||||
s
|
||||
end
|
||||
|
||||
|
||||
# Attach a skip command to the source s:
|
||||
#add_skip_command(s)
|
||||
|
||||
server.register(namespace="streams",
|
||||
description="Stop Master DJ source.",
|
||||
usage="master_dj_stop",
|
||||
"master_dj_stop",
|
||||
fun (s) -> begin log("streams.master_dj_stop") make_master_dj_unavailable() "Done." end)
|
||||
server.register(namespace="streams",
|
||||
description="Start Master DJ source.",
|
||||
usage="master_dj_start",
|
||||
"master_dj_start",
|
||||
fun (s) -> begin log("streams.master_dj_start") make_master_dj_available() "Done." end)
|
||||
server.register(namespace="streams",
|
||||
description="Stop Live DJ source.",
|
||||
usage="live_dj_stop",
|
||||
"live_dj_stop",
|
||||
fun (s) -> begin log("streams.live_dj_stop") make_live_dj_unavailable() "Done." end)
|
||||
server.register(namespace="streams",
|
||||
description="Start Live DJ source.",
|
||||
usage="live_dj_start",
|
||||
"live_dj_start",
|
||||
fun (s) -> begin log("streams.live_dj_start") make_live_dj_available() "Done." end)
|
||||
server.register(namespace="streams",
|
||||
description="Stop Scheduled Play source.",
|
||||
usage="scheduled_play_stop",
|
||||
"scheduled_play_stop",
|
||||
fun (s) -> begin log("streams.scheduled_play_stop") make_scheduled_play_unavailable() "Done." end)
|
||||
server.register(namespace="streams",
|
||||
description="Start Scheduled Play source.",
|
||||
usage="scheduled_play_start",
|
||||
"scheduled_play_start",
|
||||
fun (s) -> begin log("streams.scheduled_play_start") make_scheduled_play_available() "Done." end)
|
||||
|
||||
if output_sound_device then
|
||||
success = ref false
|
||||
|
||||
log(output_sound_device_type)
|
||||
|
||||
%ifdef output.alsa
|
||||
if output_sound_device_type == "ALSA" then
|
||||
ignore(output.alsa(s))
|
||||
success := true
|
||||
end
|
||||
%endif
|
||||
|
||||
%ifdef output.ao
|
||||
if output_sound_device_type == "AO" then
|
||||
ignore(output.ao(s))
|
||||
success := true
|
||||
end
|
||||
%endif
|
||||
|
||||
%ifdef output.oss
|
||||
if output_sound_device_type == "OSS" then
|
||||
ignore(output.oss(s))
|
||||
success := true
|
||||
end
|
||||
%endif
|
||||
|
||||
%ifdef output.portaudio
|
||||
if output_sound_device_type == "Portaudio" then
|
||||
ignore(output.portaudio(s))
|
||||
success := true
|
||||
end
|
||||
%endif
|
||||
|
||||
%ifdef output.pulseaudio
|
||||
if output_sound_device_type == "Pulseaudio" then
|
||||
ignore(output.pulseaudio(s))
|
||||
success := true
|
||||
end
|
||||
%endif
|
||||
|
||||
if (!success == false) then
|
||||
ignore(output.prefered(s))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if s1_enable == true then
|
||||
if s1_output == 'shoutcast' then
|
||||
s1_namespace := "shoutcast_stream_1"
|
||||
else
|
||||
s1_namespace := s1_mount
|
||||
end
|
||||
server.register(namespace=!s1_namespace, "connected", fun (s) -> begin log("#{!s1_namespace}.connected") !s1_connected end)
|
||||
output_to(s1_output, s1_type, s1_bitrate, s1_host, s1_port, s1_pass,
|
||||
s1_mount, s1_url, s1_description, s1_genre, s1_user, s, "1",
|
||||
s1_connected, s1_name, s1_channels)
|
||||
end
|
||||
|
||||
if s2_enable == true then
|
||||
if s2_output == 'shoutcast' then
|
||||
s2_namespace := "shoutcast_stream_2"
|
||||
else
|
||||
s2_namespace := s2_mount
|
||||
end
|
||||
server.register(namespace=!s2_namespace, "connected", fun (s) -> begin log("#{!s2_namespace}.connected") !s2_connected end)
|
||||
output_to(s2_output, s2_type, s2_bitrate, s2_host, s2_port, s2_pass,
|
||||
s2_mount, s2_url, s2_description, s2_genre, s2_user, s, "2",
|
||||
s2_connected, s2_name, s2_channels)
|
||||
|
||||
end
|
||||
|
||||
if s3_enable == true then
|
||||
if s3_output == 'shoutcast' then
|
||||
s3_namespace := "shoutcast_stream_3"
|
||||
else
|
||||
s3_namespace := s3_mount
|
||||
end
|
||||
server.register(namespace=!s3_namespace, "connected", fun (s) -> begin log("#{!s3_namespace}.connected") !s3_connected end)
|
||||
output_to(s3_output, s3_type, s3_bitrate, s3_host, s3_port, s3_pass,
|
||||
s3_mount, s3_url, s3_description, s3_genre, s3_user, s, "3",
|
||||
s3_connected, s3_name, s3_channels)
|
||||
end
|
||||
|
||||
s4_namespace = ref ''
|
||||
if s4_enable == true then
|
||||
log("Stream 4 Enabled")
|
||||
if s4_output == 'shoutcast' then
|
||||
s4_namespace := "shoutcast_stream_4"
|
||||
else
|
||||
s4_namespace := s4_mount
|
||||
end
|
||||
server.register(namespace=!s4_namespace, "connected", fun (s) -> begin log("#{!s4_namespace}.connected") !s4_connected end)
|
||||
output_to(s4_output, s4_type, s4_bitrate, s4_host, s4_port, s4_pass,
|
||||
s4_mount, s4_url, s4_name, s4_genre, s4_user, s, "4",
|
||||
s4_connected, s4_description, s4_channels)
|
||||
end
|
||||
|
||||
|
||||
command = "timeout --signal=KILL 45 pyponotify --liquidsoap-started &"
|
||||
log(command)
|
||||
system(command)
|
|
@ -0,0 +1,68 @@
|
|||
if bitrate == 24 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 24, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 24, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 32 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 32, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 32, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 48 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 48, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 48, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 64 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 64, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 64, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 96 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 96, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 96, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 128 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 128, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 128, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 160 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 160, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 160, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 192 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 192, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 192, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 224 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 224, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 224, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 256 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 256, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 256, stereo = false), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 320 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%mp3(bitrate = 320, stereo = true), !source))
|
||||
else
|
||||
ignore(output_mono(%mp3(bitrate = 320, stereo = false), mean(!source)))
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
if not icecast_vorbis_metadata then
|
||||
source := add(normalize=false, [amplify(0.00001, noise()), !source])
|
||||
end
|
||||
|
||||
if bitrate == 24 or bitrate == 32 or bitrate == 48 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=-0.1, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=-0.1, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 64 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 96 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.2, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.2, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 128 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.4, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.4, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 160 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.5, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.5, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 192 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.6, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.6, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 224 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.7, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.7, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 256 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.8, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.8, channels = 1), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 320 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%vorbis(quality=0.9, channels = 2), !source))
|
||||
else
|
||||
ignore(output_mono(%vorbis(quality=0.9, channels = 1), mean(!source)))
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
if bitrate == 24 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 24, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 24, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 32 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 32, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 32, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 48 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 48, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 48, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 64 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 64, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 64, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 96 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 96, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 96, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 128 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 128, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 128, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 160 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 160, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 160, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 192 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 192, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 192, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 224 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 224, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 224, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 256 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 256, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 256, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
elsif bitrate == 320 then
|
||||
if stereo then
|
||||
ignore(output_stereo(%opus(bitrate = 320, channels = 2, signal="music", application="audio", complexity=10, vbr="constrained"), !source))
|
||||
else
|
||||
ignore(output_mono(%opus(bitrate = 320, channels = 1, signal="music", application="audio", complexity=10, vbr="constrained"), mean(!source)))
|
||||
end
|
||||
end
|
||||
|
|
@ -7,10 +7,11 @@ import logging
|
|||
import subprocess
|
||||
from pypo import pure
|
||||
|
||||
PYPO_HOME = '/var/tmp/airtime/pypo/'
|
||||
PYPO_HOME = "/var/tmp/airtime/pypo/"
|
||||
|
||||
|
||||
def run():
|
||||
'''Entry-point for this application'''
|
||||
"""Entry-point for this application"""
|
||||
print("Airtime Liquidsoap")
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-d", "--debug", help="run in debug mode", action="store_true")
|
||||
|
@ -19,18 +20,29 @@ def run():
|
|||
os.environ["HOME"] = PYPO_HOME
|
||||
|
||||
if args.debug:
|
||||
logging.basicConfig(level=getattr(logging, 'DEBUG', None))
|
||||
logging.basicConfig(level=getattr(logging, "DEBUG", None))
|
||||
|
||||
generate_liquidsoap_cfg.run()
|
||||
''' check liquidsoap version if less than 1.3 use legacy liquidsoap script '''
|
||||
liquidsoap_version = subprocess.check_output("liquidsoap --version", shell=True, universal_newlines=True)
|
||||
if "1.1.1" not in liquidsoap_version:
|
||||
script_path = os.path.join(os.path.dirname(__file__), 'ls_script.liq')
|
||||
else:
|
||||
script_path = os.path.join(os.path.dirname(__file__), 'ls_script_legacy.liq')
|
||||
""" check liquidsoap version so we can run a scripts matching the liquidsoap minor version """
|
||||
liquidsoap_version = subprocess.check_output(
|
||||
"liquidsoap --force-start 'print(liquidsoap.version) shutdown()'",
|
||||
shell=True,
|
||||
universal_newlines=True,
|
||||
)[0:3]
|
||||
script_path = os.path.join(
|
||||
os.path.dirname(__file__), liquidsoap_version, "ls_script.liq"
|
||||
)
|
||||
exec_args = [
|
||||
"/usr/bin/liquidsoap",
|
||||
"airtime-liquidsoap",
|
||||
script_path,
|
||||
"--verbose",
|
||||
"-f",
|
||||
]
|
||||
if args.debug:
|
||||
os.execl('/usr/bin/liquidsoap', 'airtime-liquidsoap', script_path, '--verbose', '-f', '--debug')
|
||||
else:
|
||||
os.execl('/usr/bin/liquidsoap', 'airtime-liquidsoap', script_path, '--verbose', '-f')
|
||||
print(f"Liquidsoap {liquidsoap_version} using script: {script_path}")
|
||||
exec_args.append("--debug")
|
||||
os.execl(*exec_args)
|
||||
|
||||
|
||||
run()
|
||||
|
|
|
@ -40,7 +40,7 @@ setup(name='airtime-playout',
|
|||
license='AGPLv3',
|
||||
packages=['pypo', 'pypo.media', 'pypo.media.update',
|
||||
'liquidsoap'],
|
||||
package_data={'': ['*.liq', '*.cfg', '*.types']},
|
||||
package_data={'': ['**/*.liq', '*.cfg', '*.types']},
|
||||
scripts=[
|
||||
'bin/airtime-playout',
|
||||
'bin/airtime-liquidsoap',
|
||||
|
|
Loading…
Reference in New Issue