<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Håkon Nessjøen &#187; perl</title>
	<atom:link href="http://lunatic.no/category/perl/feed/" rel="self" type="application/rss+xml" />
	<link>http://lunatic.no</link>
	<description>Just another life hacker</description>
	<lastBuildDate>Tue, 29 Jun 2010 17:50:12 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Simple Perl based Icecast clone</title>
		<link>http://lunatic.no/2010/01/simple-perl-based-icecast-clone/</link>
		<comments>http://lunatic.no/2010/01/simple-perl-based-icecast-clone/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 00:23:08 +0000</pubDate>
		<dc:creator>Håkon Nessjøen</dc:creator>
				<category><![CDATA[hobby]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">http://lunatic.no/?p=69</guid>
		<description><![CDATA[This is acctually a mini project I did a while ago, but I thought I could write a small post about it here, and give out the source code.
The reason I did this, was because I used icecast, and had 5 streams up with a lot of users, but sometimes you would get sound from [...]]]></description>
			<content:encoded><![CDATA[<p>This is acctually a mini project I did a while ago, but I thought I could write a small post about it here, and give out the source code.</p>
<p>The reason I did this, was because I used icecast, and had 5 streams up with a lot of users, but sometimes you would get sound from other streams on the same server, or old sound in the middle of the stream. I tried googling after other people with the same problems as me. But found nothing. So I thought; it&#8217;s quite simple software, how hard can it be to make a stable myself?</p>
<p>So first I made a proof-of-concept perl script to receive data, and send out to several listeners. Worked great at first try. Only a minior problems. If I paused the stream on one client, the whole server started waiting for that one listener, before sending any more data to all the other listeners. (more about this later) The other problem was that I didn&#8217;t have any in-stream &#8220;title&#8221; support.</p>
<p>The reason the stream stopped when one of the clients stopped listening for data (and blocked further data), is that I was sending data with a blocking socket. Now I tried googling about how to _send_ nonblocking, but coulnd&#8217;t find anything. So I made my own little workaround. (someone please give me a better solution)</p>
<p>Instead of:</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #0000ff;">$sock</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">syswrite</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$data</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p>I wrote a new send subroutine using IO::Select to check if the client is ready for data:</p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">sub</span> <span style="color: #000066;">send</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$self</span> <span style="color: #339933;">=</span> <span style="color: #000066;">shift</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$sock</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$self</span><span style="color: #339933;">-&gt;</span><span style="color: #009900;">&#123;</span><span style="color: #ff0000;">'sock'</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$data</span> <span style="color: #339933;">=</span> <span style="color: #000066;">shift</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$select</span> <span style="color: #339933;">=</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Select</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">new</span><span style="color: #339933;">;</span>
	<span style="color: #0000ff;">$select</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">add</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$sock</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$select</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">can_write</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066;">return</span> <span style="color: #0000ff;">$sock</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">syswrite</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$data</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
		<span style="color: #000066;">return</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This finally did the work for me. The &#8220;send()&#8221; subroutine now returns how many bytes it sent to the client, and if it couldn&#8217;t send any, then it returns zero of course.</p>
<p>Then over to the problem of sending title updates inside the stream. I googled this and found a nice informative page about <a href="http://www.smackfu.com/stuff/programming/shoutcast.html" target="_blank">Shoutcast MetaData</a>.  To bring it into a short explanation; if the client supports shoutcast metadata, it sends the following request header &#8220;<code>Icy-MetaData:1</code>&#8221; to inform the server that it knows about metadata. Then the server, my script, sends &#8220;icy-metaint: 123&#8243; back in the response header, where &#8220;123&#8243; is the amount of mp3 bytes before a metadata string should arrive. After exactly 123 (or whatever the server decides) bytes, the server sends a byte containing information about how long the metadata block is, and then the metadata right after. The &#8220;length byte&#8221; must be multiplied by 16 to get the real length of the metadata string. So the largest metadata string possible would be 4096 bytes long. Just after the metadata, the mp3 data continues as usual. Usually you won&#8217;t send the title data each time the metaint-counter goes around. You&#8217;re probably good by sending zero length metadata (just sending a &#8216;\0&#8242; byte as metadata-length) all the time, until the title actually changes.</p>
<p>So at this time I rewrote the script, and mode it more module based, and added support for several streams, and yaml configuration file for access control, and some status pages, using <a href="http://template-toolkit.org/" target="_blank">TemplateToolkit</a>.</p>
<p>So anyways, the script is still in early beta stage, but it should work fluently. It did however seem that the title-data got out of sync after about a day of listening to a stream, until you reconnected. Can&#8217;t seem to understand how it would get out of sync, unless a malformed tcp packet would arrive. So either I was testing it with a really crappy internet connection that time, or there is a bug berried deep in the simple code. You are free to have fun with the script, and tell me whats wrong. I also think it&#8217;s still full of debug printing. But I have already warned you, this is still in the proof of concept &#8220;whack-some-shit-together&#8221; stage. I&#8217;ts just one of those projects that ends up collecting dust.</p>
<p>If you fire the script up, and go to http://127.0.0.1:8001/ it should give you a list of the current connected streams. Also http://127.0.0.1:8001/xml should give you xml output of current streams. I&#8217;ve been using oddcast to send icecast stream to it.</p>
<p>Here&#8217;s the full script: <a href="http://lunatic.no/wp-content/uploads/2010/01/perlcast.tar.gz">perlcast.tar</a></p>
]]></content:encoded>
			<wfw:commentRss>http://lunatic.no/2010/01/simple-perl-based-icecast-clone/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>DMX system in perl</title>
		<link>http://lunatic.no/2009/08/dmx-system-in-perl-2/</link>
		<comments>http://lunatic.no/2009/08/dmx-system-in-perl-2/#comments</comments>
		<pubDate>Sun, 09 Aug 2009 13:25:57 +0000</pubDate>
		<dc:creator>Håkon Nessjøen</dc:creator>
				<category><![CDATA[dmx]]></category>
		<category><![CDATA[hobby]]></category>
		<category><![CDATA[perl]]></category>

		<guid isPermaLink="false">urn:myopera-lunatic-blog-4226181</guid>
		<description><![CDATA[William and me are starting to prepare for the next Exploit party, and this year we have decided to control all the lightning and video equiptment by perl.
We started for two days ago. William has a ENTTEC USB Pro which is fine for interfacing. In Linux, it is recognized as a standard COM port, and [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://williamviker.net/" target="_blank">William</a> and me are starting to prepare for the next Exploit party, and this year we have decided to control all the lightning and video equiptment by perl.</p>
<p>We started for two days ago. William has a <a href="http://www.enttec.com/index.php?main_menu=Products&amp;prod=70304&amp;show=description" target="_blank">ENTTEC USB Pro</a> which is fine for interfacing. In Linux, it is recognized as a standard COM port, and the API consists of sending characters to the virtual COM port.</p>
<p>So as an example of how easy it is to send DMX with this device from perl, I&#8217;ll give an example below:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl</span>
<span style="color: #000000; font-weight: bold;">use</span> Device<span style="color: #339933;">::</span><span style="color: #006600;">SerialPort</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> Time<span style="color: #339933;">::</span><span style="color: #006600;">HiRes</span> <span style="color: #009966; font-style: italic;">qw/usleep/</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">use</span> strict<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$PORT</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'/dev/ttyUSB0'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$ob</span> <span style="color: #339933;">=</span> Device<span style="color: #339933;">::</span><span style="color: #006600;">SerialPort</span><span style="color: #339933;">-</span><span style="color: #0000ff;">&amp;gt</span><span style="color: #339933;">;</span>new<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$PORT</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">or</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;Can't Open $PORT: $!&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$packet</span> <span style="color: #339933;">=</span> <span style="color: #000066;">chr</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">chr</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">128</span><span style="color: #009900;">&#41;</span> x <span style="color: #cc66cc;">30</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$length</span> <span style="color: #339933;">=</span> <span style="color: #000066;">length</span> <span style="color: #0000ff;">$packet</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$write</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$ob</span><span style="color: #339933;">-</span><span style="color: #0000ff;">&amp;gt</span><span style="color: #339933;">;</span>write<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\x</span>7E<span style="color: #000099; font-weight: bold;">\x</span>06&quot;</span> <span style="color: #339933;">.</span> <span style="color: #000066;">chr</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$length</span> <span style="color: #0000ff;">&amp;amp</span><span style="color: #339933;">;</span> 0xFF<span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000066;">chr</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$length</span> <span style="color: #0000ff;">&amp;gt</span><span style="color: #339933;">;</span><span style="color: #0000ff;">&amp;gt</span><span style="color: #339933;">;</span> <span style="color: #cc66cc;">8</span><span style="color: #009900;">&#41;</span> <span style="color: #0000ff;">&amp;amp</span><span style="color: #339933;">;</span> 0xFF<span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">$packet</span> <span style="color: #339933;">.</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\x</span>E7&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Wrote $write bytes to DMX controller<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>This little script will send 30 channels of value 128 to the DMX controller, which will keep repeating this information, until it gets new information.</p>
<p>To clarify, the first byte 0&#215;7E is the start byte for the enttec api. The next byte 0&#215;06 is the function we are using, which is DMX OUT. Then there is two bytes of length information, describing how many channels we are going to send. And then the package is sent. It&#8217;s important to remember to send a 0&#215;00 byte as the first channel, since this is the start byte of the actual DMX data. (also called the SC in the DMX standard specification)</p>
<p>We needed a central area to save our current channel data, and william found a nice perl module called Cache::FastMmap which uses mmap to save data. This way we can have several scripts using the same memory buffer, where we will putt the current DMX channel data. The first byte in the shared memory holds the current &#8216;version number&#8217; of the data. Each time any data is changed, the first byte&#8217;s value is increased. This way each &#8220;reader&#8221; can check if there are new data asyncronically.</p>
<p>So after some initial successful testing, I created a module called Exploit::Scene. This is the module that all scripts that need direct DMX control will use. The external methods are pretty simple. You have get(), set(), to get and set a single channel value, isNew() and resetNew() to check if the DMX channel data has changed since last time you checked. commit() to save new channel data you have edited, and getDMXpacket() to get full 513 bytes of channel data. (or less, if you have set a smaller universe_size)</p>
<p>Now we could start to create some small test scripts. So William made a script that tests a single RGB LED fixture. And I created a console application to show/edit the DMX data. Of course these scripts are just for testing, and will not be used in the finished &#8216;product&#8217;, since everything will be centralized in a web interface to combine effects, etc.</p>
<p><span class="imgcenter"><img src="http://files.myopera.com/lunatic/blog/dmx_test.png" alt="" /></span></p>
<p>Here you can se the console application i wrote with the Curses perl module. The green cursor on the left is moved with your up and down keys, to select a channel. If you use the left or right keys, you increase or decrease the channel value. If you press space, you toggle the channel to full 0xff or null 0&#215;00 values. Page Up and Page Down will show you next &#8216;page&#8217; of channels, up to 512. The color on the bars is reflecting the channel value, first 1/3 is red, next is yellow, and last is green. The console is live, so if any other processes is changing DMX data, it will immediately show the new data while you are editing. So it&#8217;s both a monitor and editor. Which will be nice to have when the full system is done. So we can monitor the dmx channels live without the actual fixtures.</p>
<p>We have created two backend scripts. backend-dmx and backend-udp. These connect to the mmap with the Exploit::Scene module as explained, and use the getDMXpacket() function to get the data to send to either the DMX controller, or udp. By UDP I mean that we are sending all the DMX data to a local multicast address. 239.255.0.$universe. This way, any computer on the network can connect to this stream, and get out the data it needs. So we can have several computers on the network triggering on DMX data. For this we have the Exploit::UDPScene module, which behaves similar to the MMAP version, but used multicast to get it&#8217;s data.</p>
<p>More info will come when we are further along with the project.</p>
]]></content:encoded>
			<wfw:commentRss>http://lunatic.no/2009/08/dmx-system-in-perl-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
