Results tagged “timesaver” from @Dexter's Blog

Hello everyone,

As promised in my previous post, here is the whole story of me getting both licensed to ride a motorcycle on the road and the motorcycle itself. But first, I know some of you are craving some photos so here is the first batch, along with a promise to take and upload better ones soon.



The saga starts somewhere at the beginning of June 2009, when I took the decision to follow classes for a driver's license. It is as of yet unclear what caused or influenced this decision but there are speculations that a certain change (to the better) in my personal life is the culprit.

I chose this school for my driver training because it was close to where I live (a 20 minute walk) and because it looked the most trustworthy of all driving schools in this area. I submitted my application on Monday, June 15th; got scheduled for the psychology test the next day and I attended the first driving law theory class the third day, Wednesday, June 17th. The first motorcycle riding class was held on Thursday and the first car driving class the next Monday.

According to local laws, the psychology test must be taken (and passed) before any driving school attendance. Following that, the theory course must then be completed before any actual driving/riding takes place and only after completing that last part are you allowed to submit you application for the government-administered driving license examination.
As you all know, laws are treated as advisories here so the school only enforced the amount of time that had to pass from the date the psychology test was passed to the day they would sign your file and thus allow you to submit your application to the authorities.



Moving on to the schooling itself, the law theory classes were a good idea and I attended about three weeks of them (and since the classes were held three times a week, that would sum up to about 9 2-hour classes). Unfortunately, the local view about laws is that you will obey them if you are made sufficiently aware of their content (and not their meaning and/or applicability). On the same note, the theory exam contains 20 multiple-choice questions for future riders (26 for future drivers) which can have one, two or even all three correct answers and it's light years away from being at least psychometrically correct, let alone well balanced, normalized and entropy-masked.
The questions cover what you would expect: signs and markings, right-of-way, speed limits, highway driving; what you would less expect: preventive driving, ecological driving, automotive mechanics; and even what you would not expect: detailed aspects from the text of the law itself.

The law theory class consisted of us solving sets of 26 questions (picked from the same database that the formal examination draws them from), checking our results and then the instructor explaining the correct answer for any and all questions that we've messed up. It is a good method for gaining enough knowledge (read: experience with question-type fingerprinting) to pass the exam but it has nothing to do with learning and understanding the law itself (not that there would be enough meaning in any local law to warrant understanding it).



Moving on to the driving and riding classes which were also held three times a week. Driving was on Monday, Wednesday and Friday whereas riding was on Tuesday, Thursday and Saturday. As you probably know, local laws mandate that the practical examination for a future rider consists of performing a fixed choreography in a closed court within 4 minutes and without making more than 3 mistakes. As opposed to that, the practical examination for a future driver consists of driving a car in live traffic, following live navigation orders from the exam judge.
Because of that, practical training for the two disciplines follows differing paths and methods, rendering both training efforts insufficient and incomplete -- something which is not readily obvious unless you do what I did and take up both riding and driving classes. The reason for drawing that conclusion is that operating a device is one area of interest while using a device in a context driven by usage laws and populated by other users is a totally different thing.

So, if you are to take up driving classes, you are going to end up knowing how are you supposed to drive a car in traffic, obeying all rules -- but being unable to drive the car itself proficiently and master driving itself as a skill; while if you are going to take up riding classes, you are going to master controlling the motorcycle -- but you will remain totally unprepared for riding in in the wild, on the open road and unforgiving weather.

Moving on to the more hand-on part of the classes, the driving part was held on Citroen C1s which (both the vendor and my instructor) called "a car". I really beg to differ on that ... but it was enough of a car for me to learn driving. The riding part was held on a pack of Suzuki, three GN250 (yes, there is a typo in the first post, claiming they were "GZ" 250s), one GN125 and one Marauder 250. Even though not exactly right for all people, the attitude of the riding instructor was perfect for my way of learning new things: after making sure we mastered "how not to drop the motorcycle", he left us to roam freely around the court, practicing the exam choreography in whichever order we felt comfortable with, giving us a chance to discover the art behind motorcycle riding ourselves.

It is at this point that [om3ga] (or Sixx as he signs his posts now) suggested David L. Hough's books as compulsory reading, which I have read one-per-night and which I hold directly responsible for me understanding (and learning how to apply!) enough motorcycle physics to pass the practical exam with no sweat. My thanks and gratitude go to both of you!



Moving further, after completing all paperwork for the final examination (which included a thorough-wannabe medical examination), I have submitted my application on August 11th. The dialogue with the clerk remains a landmark of local flavor:
Clerk: "So, which exam to you want to take first? Riding or driving?"
Me: (large grin) "Riding first, please!"
Clerk: (after typing at the computer) "Soooooo, we have riding examination on the 26th and driving examination on the 19th!"
The theory exam can be taken at any time from the day you submitted your application (inclusive) until the day of the practical examination (exclusive) so I came back the next day and did them both. The results were no surprise: I passed the riding part and failed the driving one.

I decided I shall put driving on the back burner and concentrate on riding and so, on the 26th, I took and passed the practical examination. I got my license the next day and so I was now legally a motorcyclist :-)



That's about it for now. I'm sure I must have missed some details -- please ask and I shall answer.

@Dexter
Good evening to those who will go to sleep soon and good morning to those who just woke up :-)

It is with great pleasure that I announce the launch of the first version of NABPS, namely 0.5-alpha. This will change into 0.5-beta as soon as all the extra features are in (see below) and, subsequently, into 0.75-rc1 as soon as common-sense testing takes place and is passed with flying colours.

NABPS is an acronym for New Aggregator Because Planet Sucks and is meant as a reminder for the main reason of starting to develop it, in the first place.

You can see a live demo here (you can always compare it with the original here).



In an attempt to make NABPS compatible with RFC-ignorant web servers (RFC2616, section 14.3 comes to mind), I have tweaked some options I'm feeding to CURL in the Fetcher which seems to have fixed the "Oops, is that gzip? I was expecting XML!" problem.
Unfortunately, this still does not guard against uninspired WordPress plugins, such as WP Super Cache, which (even if transparently decompressed) do not produce well-formed XML, as you can see in the example below:
<!-- Page not cached by WP Super Cache. No closing HTML tag. Check your theme. -->
<?xml version="1.0" encoding="UTF-8"?>

Unfortunately for its owner, the feed above has been disabled until such time it shall be fixed.

Furthermore, while I am still adding features and fixing obvious bugs there will be no "release" package so, to compensate for that, here is the Subversion repository if you wish to check the code out (and here is the DAV version of the above, for direct access with svn, TortoiseSVN and the like).

Finally, I did not mention (and the sources do not, as of yet, reflect that), but all code is released under the GPL, version 2.



Please tell me what you think (obviously, if feedback is positive NABPS will replace Planet at the above address -- and fast at that).

Have a nice week ahead and don't forget to leave your feedback here (if I am not told what does not work, I cannot fix it :-) ),
@Dexter
Today's topic in this category: Internet Protocol, Version 6. Pure perfection but, sadly, no one cares :-(

Just compare, this (using IPv6):
# traceroute6 download.wikimedia.org
traceroute to download.wikimedia.org (2620:0:860:2:230:48ff:fe5a:eb1e), 30 hops max, 40 byte packets
 1  atlas.linux360.ro (2001:5c0:9a05::1)  0.285 ms  0.279 ms  0.279 ms
 2  2001:5c0:8fff:fffe::79a4 (2001:5c0:8fff:fffe::79a4)  147.944 ms  149.277 ms  150.772 ms
 3  * * *
 4  if-5-0-1.6bb1.mtt-montreal.ipv6.teleglobe.net (2001:5a0:300::5)  193.968 ms  195.987 ms  201.568 ms
 5  if-1-0.mcore3.mtt-montreal.ipv6.teleglobe.net (2001:5a0:300:100::1)  195.907 ms  195.897 ms  200.469 ms
 6  if-13-0.mcore4.nqt-newyork.ipv6.teleglobe.net (2001:5a0:300:100::2)  206.977 ms  206.969 ms  206.930 ms
 7  if-4-0.mcore4.pdi-paloalto.ipv6.teleglobe.net (2001:5a0:1200::1)  275.155 ms  267.837 ms  267.607 ms
 8  2001:5a0:1200::6 (2001:5a0:1200::6)  267.070 ms * *
 9  2001:5a0:1200:100::e (2001:5a0:1200:100::e)  266.977 ms * *
10   (2610:18:10a::2)  346.465 ms  346.458 ms  346.426 ms
11   (2610:18:10a::2)  347.111 ms  347.096 ms  342.075 ms
12  2620:0:860:2:230:48ff:fe5a:eb1e (2620:0:860:2:230:48ff:fe5a:eb1e)  342.051 ms  341.723 ms  341.700 ms

with this (using IPv4):
# traceroute download.wikimedia.org
traceroute to download.wikimedia.org (208.80.152.183), 30 hops max, 40 byte packets
 1  gw.dexter.linux360.ro (192.168.10.1)  0.396 ms  0.384 ms  0.395 ms
 2   (89.37.42.1)  1.096 ms  1.523 ms  1.754 ms
 3  79.134.34.217 (79.134.34.217)  1.200 ms  1.661 ms  1.862 ms
 4  79.134.32.137 (79.134.32.137)  1.160 ms  1.102 ms  1.852 ms
 5  rc1-buc-uplink2-rd1-buc.airbites.net (195.170.181.169)  1.525 ms  0.981 ms  1.414 ms
 6  GigabitEthernet2-1-106.ipcolo2.frankfurt.level3.net (62.67.38.185)  219.299 ms  219.417 ms  219.401 ms
 7  vlan89.csw3.Frankfurt1.Level3.net (4.68.23.190)  46.631 ms  46.562 ms  46.577 ms
 8  ae-81-81.ebr1.Frankfurt1.Level3.net (4.69.140.9)  59.094 ms  58.886 ms  59.033 ms
 9  ae-2.ebr2.Paris1.Level3.net (4.69.132.141)  65.521 ms  65.465 ms  65.631 ms
10  ae-41.ebr2.Washington1.Level3.net (4.69.137.50)  149.641 ms ae-43.ebr2.Washington1.Level3.net (4.69.137.58)  149.121 ms ae-42.ebr2.Washington1.Level3.net (4.69.137.54)  147.043 ms
11  ae-62-62.csw1.Washington1.Level3.net (4.69.134.146)  139.431 ms  136.973 ms ae-72-72.csw2.Washington1.Level3.net (4.69.134.150)  137.448 ms
12  ae-81-81.ebr1.Washington1.Level3.net (4.69.134.137)  137.381 ms ae-91-91.ebr1.Washington1.Level3.net (4.69.134.141)  141.602 ms ae-61-61.ebr1.Washington1.Level3.net (4.69.134.129)  141.883 ms
13  ae-2.ebr3.Atlanta2.Level3.net (4.69.132.85)  152.735 ms  165.104 ms  165.049 ms
14  ae-62-60.ebr2.Atlanta2.Level3.net (4.69.138.3)  157.452 ms ae-72-70.ebr2.Atlanta2.Level3.net (4.69.138.19)  153.395 ms ae-62-60.ebr2.Atlanta2.Level3.net (4.69.138.3)  162.608 ms
15  ae-1-6.bar1.Tampa1.Level3.net (4.69.137.113)  170.868 ms  170.782 ms  170.258 ms
16  ae-5-5.car1.Tampa1.Level3.net (4.69.133.49)  171.663 ms  171.380 ms  171.518 ms
17  ae-13-13.car3.Tampa1.Level3.net (4.69.133.54)  170.908 ms  171.654 ms  171.454 ms
18  e1-11-level3.co2.tpax.as30217.net (4.71.0.10)  170.310 ms  169.683 ms  169.681 ms
19  ge8-1.csw5-pmtpa.wikimedia.org (66.113.197.94)  170.530 ms  170.073 ms  170.015 ms
20  storage2.wikimedia.org (208.80.152.183)  170.670 ms  171.357 ms  169.819 ms


And you tell me which you like better!
@Dexter
As promised, I am hereby replying to the first questions submitted by you, my readers:

  • You seem to be extremely hard to get at times, why is that?
  • I was born under the sign of Cancer -- we are all very, very good at hiding, especially in plain sight. To put it otherwise, if I do not want to be found by someone then they shall not find me. The only exception to that (up to date) being a couple of ladies which (at two different moments in history) had little trouble in finding me -- but they both had a quality that seems to be extinct today among people: they were determined.
    Switching to a more personal note, if you had trouble finding (or getting through to) me, it must be that my wish not
    to be contacted by you played an important part in that.
    Finally, on a purely technical note, as all CyberDyne 7 models, I sport grid-awareness which renders efforts to get to me (against my will) useless because I sense intent to get to me, before someone starts acting on it, therefore giving me ample time to avoid it.
  • Your CLIP-aware communications terminal seems to behave erratically: sometimes it works, sometimes it does not and even when it seems to be working the call will sometimes pass unanswered. Why is that so?
  • I try to make all my communication terminals CLIP-aware (protocol/techonology -permitting, of course) because "to communicate" is one of those concepts which only have a plural form in my dictionary. This means that I cannot (and shall not) communicate when I can neither associate nor create an identity to/for the other end of a communication link attempting to get itself established. In practice this means that if you try to call me while having enabled CLIR, you shall get a busy tone and in plain English this means I shall never accept calls (or other forms of communication, for that matter) from "anonymous", "John DOEs" and the like.
    Another important thing to note is that I answer calls coming in on my personal terminal at my own discretion for the plain and simple reason that it is I who pays its bill so I am entitled to complete discretionary control over it. A good side-effect of this is that I tend to go quite a distance in maintaining my terminal online, just in case somebody I want to be found by would attempt communication.
    Finally, in what calls coming in on my work terminal are concerned, I tend to only guarantee an answer to my boss (the person I directly report to) -- and even that isn't always synchronous. Answering any other calls is serviced on a best effort, first come-first served basis (with logging) so your call may get dropped.
  • You are known to be a very discerning person in matters of manners and etiquette. What would (in your oppinion) be proper etiquette to follow when an attempt to call you goes unanswered?
  • I have detailed logging enabled on all my terminals. Your call may have gone unanswered (by me), but it won't go away from the missed calls log. If you are on my callback list, I shall call you back at the earliest opportunity. If you feel the message you want to send through is of an urgent nature, it is good etiquette to retry in 5 minutes and then an hour later -- for a total maximum of three calls that day. Please note that anyone generating more than three consecutive entries per day in the missed calls log will be blacklisted for an entire week (audit log flood protection).
    If at the second attempt your call continues to remain unanswered and you either do not wish to wait the whole hour or feel that the urgency of your message warrants a quicker response, it is good etiquette to write a short message (be that SMS for GSM/CDMA or offline message for XMPP etc.) describing the nature of your emergency as concisely as possible. Writing a message that is offtopic or on an unappropiate tone (e.g. "Call me immediately!", "Why don't you answer?!") is considered very bad etiquette and will usually result in blacklisting for an entire day.
  • Why don't you just reject calls coming in when you're not in a position/the mood to answer?
  • Actively refusing a connection is like slamming the door in one's face and the only place where that is preferable to silently ignoring the connection attempt (and thus acceptable as proper etiquette) is TCP/IP.
    Besides, on protocols where an incoming connection is actively signaled at the receiving end (e.g. by ringing, on telephone networks), it is good etiquette to allow the line to ring at most three times after which the calling end is to voluntarily hang the line up. On systems where there is no ringback tone (or equivalent thereof), "four times the call setup or dispatch time" is to be used instead (which equates to about 10 seconds on PSTN and 15 seconds on GSM, after finishing the dialling sequence).
    Please note that allowing the line to ring more than five times (six times the call setup or dispatch time) will be awarded with a day long blacklisting (far end line hijack protection).
  • What about when your controlling node reports you are unreachable or any other error condition?
  • When your attempt to call me results in anything else but either being answered or ringback indication, including any kind of error condition, it is good etiquette to attempt writing a short message (see above) as an alternative means of contacting me. This usually has the advantange of being delivered asynchronously by my controlling node whenever my terminal comes back online.
    Please note that cycling through the terminal addresses you've got filed under my name and calling each repeatedly in a loop, in an attempt to contact me, is frowned upon and seen as particularly poor etiquette -- however, short-messaging each at most once is accepted.
  • Finally, what is the best way to contact and/or communicate with you?
  • By far, the most appropiate and the one warranting the fastest and at the same time the highest quality response means of communication is electronic mail. This applies especially for work or business -related communication, whereas various exceptions (e.g. the callback list mentioned above) apply for communication of a personal nature.

That's about it for now, next time I'll answer a very interesting batch of questions I've received, concerning what seems to have become a very disputed subject today: religion.

Good night,
@Dexter
Hello everyone and welcome back. I am hereby writing the first post of the "Since you have asked" series, dedicated to making it easier for You to understand me.

The entries will be structured as a self-interview comprised, of course, of questions and answers (you might want to call it a FAQ as well, but I prefer the former). Communication format being all setup and explained, let's get down to business:
  • Answering to your own questions is unfairly simple! Can we submit our own questions?
  • Sure thing, not only can you -- I actually encourage you to do just that! Submit your questions here and I shall answer them on a first come, first served basis.

  • What warrants that you will answer all questions submitted?
  • My word. Should be more than enough.

Having said that, I'll stop for now (leaving you, my readers the unique opportunity of asking the first question) and make some room for something bigger ...

@Dexter
Following Monday evening's test (with the usual live show session) and thanks to some uniquely useful input from d3vi1 and his friend Mircea, I have come to the following configuration for the Marconi Transmitter:
#!/usr/bin/liquidsoap

# Import system-wide settings
%include "/etc/liquidsoap/settings.liq"

# Fallback/Background sound sources
playlist_monday = playlist(id="monpls", mode="random", "/usr/local/etc/liquidsoap/monday.m3u")
playlist_tuesday = playlist(id="tuepls", mode="random", "/usr/local/etc/liquidsoap/tuesday.m3u")
playlist_wednesday = playlist(id="wedpls", mode="random", "/usr/local/etc/liquidsoap/wednesday.m3u")
playlist_thursday = playlist(id="thupls", mode="random", "/usr/local/etc/liquidsoap/thursday.m3u")
playlist_friday = playlist(id="fripls", mode="random", "/usr/local/etc/liquidsoap/friday.m3u")
playlist_weekend = playlist(id="wepls", mode="random", "/usr/local/etc/liquidsoap/weekend.m3u")

# Add them up
background = switch([({1w}, playlist_monday),
({2w}, playlist_tuesday),
({3w}, playlist_wednesday),
({4w}, playlist_thursday),
({5w}, playlist_friday),
({6w or 7w}, playlist_weekend)])

# Leave some room for interactivity (Public Requests)
backandreq = fallback([request.equeue(id="pubreq"),
background])

# Leave some room for management (External status callbacks)
def liveup()
system("/usr/share/icecast/scripts/live-up.sh")
end

def livedown()
system("/usr/share/icecast/scripts/live-down.sh")
end

# Plug the live studio in ...
production = input.harbor(id="production", on_connect=liveup, on_disconnect=livedown, "live.ogg")

# ... and make sure it is heard when On Air
master_out = fallback(track_sensitive=false,
[production,
backandreq])

# Leave room for some more interactivity (RDS Ticker)
masterandrds = insert_metadata(id="rds", master_out)

# Emulate the final stage before the Tx PA: dynamics processing
def tx_dsp(s)
# Emulate a three-band crossover network
low = filter.iir.eq.low(frequency=200.)
mhi = filter.iir.eq.high(frequency=140.)
mlo = filter.iir.eq.low(frequency=2500.)
hhi = filter.iir.eq.high(frequency=2400.)
hlo = filter.iir.eq.low(frequency=15000.)
comp = compress(rms_window=0.03)

# Normalize (perform AGC)
n = normalize(target=0., window=0.03, gain_min=-10., gain_max=10., s)

# Emulate a three-band dynamic range compressor
c = add(normalize=false,
[comp(attack=1., release=50., threshold=-27., ratio=5., gain=-4., knee=10., low(n)),
comp(attack=1., release=80., threshold=-17., ratio=3., gain=-4., knee=10., mlo(mhi(n))),
comp(attack=1., release=80., threshold=-20., ratio=7., gain=-4., knee=10., hlo(hhi(n)))])

# Limit the signal output to prevent clipping
limit(attack=1., release=100., threshold=-2., rms_window=0.001, gain=0., c)
end

tx_out = tx_dsp(mksafe(masterandrds))

# And, finally, send it all to the transmitter
output.icecast.mp3(host="localhost", password="", bitrate=96, samplerate=44100, mount="live",
description="YO3HVT Radio", genre="Talk Radio", url="http://radio.dexter.linux360.ro/",
tx_out)
output.icecast.vorbis(host="localhost", password="", quality=-0.5, samplerate=44100, mount="live.ogg",
description="YO3HVT Radio", genre="Talk Radio", url="http://radio.dexter.linux360.ro/",
tx_out)



As always, trouble never shows up alone, so here they are:
  • the Intel Pentium running @ 1GHz inside Atlas just cannot cope with applying a 4th order Butterworth filter in realtime over a 44.1kHz stereo signal coming in 16bit-wide samples :-( -- so I'm stuck with IIR filters and making up a bandpass version of those by connecting two of the same in series
  • if the weekend configuration drove Atlas to ~0.85 loadavg (and 90% CPU usage); tonight configuration (albeit, sounding a lot better) pushes it to 1.01 loadavg and 95% CPU usage -- I think that's about as much as I can push it before making a mess of the whole thing :(
Given the above, I'm thinking very seriously about doing one (or more) of the following:
  • connect the dynamics processor to the Production room input only, such that it will only be used by live shows (leaving the CPU less tired during non-live activity for, e.g. system jobs) -- easy on CPU, bad on off-peak hour quality :(
  • buy more hardware, specifically a node dedicated to the whole sound processing/enhancing job (it's easy to link it to other liquidsoap instances via the input.rtp() and output.rtp() operators) -- good on quality, bad on the electricity bill and my wallet
  • move some of the processing to the Production room -- defeats initial design aim, probably kills the CPU power headroom I found very useful to have at hand in a few critical situations while on air
So I'm stuck :( Any suggestions/help are welcome.

Good night,
@Dexter
Most of you know from Friday's show (sorry to those who missed it, no tape, it was an unplugged performance :( ) that I've made major changes in what the digital (or purely-software-based) part of Radio Andromeda's Marconi studio is concerned.

My initial intent was to separate batch processing duties from the live ones and distribute the former to Atlas and the latter to BeatrixKiddo -- in effect splitting the Marconi location between a Transmitter and a Production room.

As is always the case with science: easier said than done! I used Savonet's liquidsoap for the Transmitter (alongside IceCast2 as a final Tx PA and antenna, of course) and I stuck to the hybrid configuration made up of XMMS, linphone and darkice on the digital side and Behringer's UCA200, UCA202, XENIX1002, C-3, XM8500, HA400 and HPM1000 on the analog one for the Production.
My design intent was to identify all processing (be that of the audio signal or otherwise) that would not change during normal operations of the station and move it completely out of the way, on the Transmitter -- leaving ample room for experiments (trial and error) and flexibility in Production.

Identifying was the easy job: the Tx PA is constant and so is the relay network; the background (i.e. when not live) music is again static; finally, any generic signal processing (i.e. enhancements) is again static and therefore belongs on the Transmitter.
Implementation was not so :( Moving the entire music collection within Atlas' reach was rather easy compared to building playlists for each day out of nearly 5000 tracks. Then came the problems: liquidsoap does not (yet) know how to read FLAC, nor MPEG 4 Audio (AAC+) so those tracks had to be grep -v -ed out of the daily playlists. Furthermore, a means had to be devised to connect Production to the output stream when the former would be airing -- fortunately the track-insensitive version of the fallback() operator in liquidsoap did the job nicely.

But the most mind boggling task of all was the dynamics processor + AGC. Thanks to the excellent documentation in liquidsoap and to the great freeverb3 project (and its XMMS plugin, as a working example), I was finally able to arrive at a working configuration. Whether the result is satisfactory, it's up to you to decide, my dear listeners :-)
Anyway, here is the code that controlls it all (the Transmitter part):

#!/usr/bin/liquidsoap

# Import system-wide settings
%include "/etc/liquidsoap/settings.liq"

# Fallback/Background sound sources
playlist_monday = playlist(id="monpls", mode="random", "/usr/local/etc/liquidsoap/monday.m3u")
playlist_tuesday = playlist(id="tuepls", mode="random", "/usr/local/etc/liquidsoap/tuesday.m3u")
playlist_wednesday = playlist(id="wedpls", mode="random", "/usr/local/etc/liquidsoap/wednesday.m3u")
playlist_thursday = playlist(id="thupls", mode="random", "/usr/local/etc/liquidsoap/thursday.m3u")
playlist_friday = playlist(id="fripls", mode="random", "/usr/local/etc/liquidsoap/friday.m3u")
playlist_weekend = playlist(id="wepls", mode="random", "/usr/local/etc/liquidsoap/weekend.m3u")

# Add them up
background = switch([({1w}, playlist_monday),
({2w}, playlist_tuesday),
({3w}, playlist_wednesday),
({4w}, playlist_thursday),
({5w}, playlist_friday),
({6w or 7w}, playlist_weekend)])

# Leave some room for interactivity (Public Requests)
backandreq = fallback([request.equeue(id="pubreq"),
background])

# Leave some room for management (External status callbacks)
def liveup()
system("/usr/share/icecast/scripts/live-up.sh")
end

def livedown()
system("/usr/share/icecast/scripts/live-down.sh")
end

# Plug the live studio in ...
production = input.harbor(id="production", on_connect=liveup, on_disconnect=livedown, "live.ogg")

# ... and make sure it is heard when On Air
master_out = fallback(track_sensitive=false,
[production,
backandreq])

# Leave room for some more interactivity (RDS Ticker)
masterandrds = insert_metadata(id="rds", master_out)

# Emulate the final stage before the Tx PA: dynamics processing
def tx_dsp(s)
# Emulate a three-band crossover network
low = filter.iir.eq.low(frequency=140.)
mhihalf = filter.iir.eq.high(frequency=130.)
mlohalf = filter.iir.eq.low(frequency=6400.)
high = filter.iir.eq.high(frequency=6300.)
comp = compress(rms_window=0.03)

# Emulate a three-band dynamic range compressor
c = add(normalize=false,
[comp(attack=1., release=50., threshold=-27., ratio=5., gain=-4., knee=10., low(s)),
comp(attack=1., release=80., threshold=-17., ratio=3., gain=-4., knee=10., mlohalf(mhihalf(s))),
comp(attack=1., release=80., threshold=-20., ratio=7., gain=-4., knee=10., high(s))])

# Normalize (perform AGC) and then limit the signal
limit(attack=1., release=100., threshold=-2., rms_window=0.001, gain=0.,
normalize(target=0., window=0.03, gain_min=-10., gain_max=10., c))
end

tx_out = tx_dsp(mksafe(masterandrds))

# And, finally, send it all to the transmitter
output.icecast.mp3(host="localhost", password="", bitrate=64, samplerate=44100, mount="live",
description="YO3HVT Radio", genre="Talk Radio", url="http://radio.dexter.linux360.ro/",
tx_out)
output.icecast.vorbis(host="localhost", password="", quality=-0.5, samplerate=44100, mount="live.ogg",
description="YO3HVT Radio", genre="Talk Radio", url="http://radio.dexter.linux360.ro/",
tx_out)

What's next, you might ask? Well, the web interface for submitting those requests that the code above can serve ;-) and many many more to come. Stay tuned,

Have a nice week,
@Dexter
Just as a reminder to all of you out there trying to make that particular CGI work:

At least on RedHat (and derivatives thereof), Apache is factory configured to use the suexec mechanism for CGI execution. This means that Apache's behavior (UNIX-system wise) will be different while executing CGIs from a ScriptAliased directory than when executing CGIs from other folders (i.e. then ones for which Options +ExecCGI has been set via, e.g., .htaccess).
  • For the remainder of the text, we consider the configuration directive AddType application/x-httpd-cgi .cgi added to the relevant Apache configuration file.
  • For the remainder of the text, the "target user" is meant to be the user on whose behalf mod_userdir serves the current request.

When executing a CGI from a ScriptAliased folder, Apache will directly attempt to popen(); said CGI script and thus the CGI will be ran as the user the main server runs as (i.e. apache on the distribution in question). Any errors encountered (most notably "premature end of script headers") will most probably be caused by said user not being able to execute the script and/or access mandatory resources thereof.
  • To debug such a situation, su to apache and attempt to execute the script -- in most cases you'll find evidence of the culprit on stdout/stderr.
When executing a CGI from a folder with Options +ExecCGI set, Apache will call suexec which in turn will setuid(); to the target user and then attempt to popen(); the script. One side effect of this is that the script will be executed with the target user's privileges (which may be less or more than those of apache and thus be the root cause of errors). Another side effect of this is that the suexec program will perform its own security checks (akin to Sendmail's smrsh) -- failure of which will result in the same, cryptic, "premature end of script headers" error message.
  • To debug such a situation, su to the target user and attempt to execute the script -- in most cases you'll find evidence of the culprit on stdout/stderr.
  • Moreover, check the /var/log/httpd/suexec.log file as it's the only place Apache will complain if it was suexec itself that denied execution of said script.
Following the suexec case, you should know that, just like Sendmail's smrsh, it has a path hard coded inside (configurable only at compile time) -- and this path is the name of the user's public HTML folder, within that user's home folder (as given by getent();). Please note that the factory default configuration states "public_html" as the name of that folder -- a value which can easily be overridden in Apache's configuration file but cannot, at all, be overridden in what suexec is concerned! suexec will complain with an even more cryptic "cannot get docroot information" message to /var/log/httpd/suexec.log if that value is changed in practice (via /etc/httpd/conf/httpd.conf), effectively denying any CGI execution if attempted from outside an ScriptAliased directory.
  • The only way to work around this design flaw (without fully recompiling Apache) is to make a symbolic link from public_html to the actual folder name used in that particular installation -- that way both the custom setup and suexec's security expectations will be kept happy :-)

Hope this helps,
@Dexter