<?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>phaq &#187; Programming</title>
	<atom:link href="http://phaq.phunsites.net/category/faq/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://phaq.phunsites.net</link>
	<description>my daily IT madness</description>
	<lastBuildDate>Mon, 30 Jan 2012 10:07:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.3</generator>
		<item>
		<title>Working around WordPress&#8217; wpdb limitations with MySQL User Variables</title>
		<link>http://phaq.phunsites.net/2012/01/27/working-around-wordpress-wpdb-limitations-with-mysql-user-variables/</link>
		<comments>http://phaq.phunsites.net/2012/01/27/working-around-wordpress-wpdb-limitations-with-mysql-user-variables/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 12:14:04 +0000</pubDate>
		<dc:creator>gdelmatto</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=914</guid>
		<description><![CDATA[Think about retrieving a data set from MySQL, where you need to add distinct, auto-incremented ID to each row retrieved. Sounds easy? Well, the ID has to be generated on-the-fly and out of nowhere. Still easy? One might think about using MySQL user variables to accomplish this, sure. But what if your framework does not [...]]]></description>
			<content:encoded><![CDATA[<p>Think about retrieving a data set from MySQL, where you need to add distinct, auto-incremented ID to each row retrieved. Sounds easy?</p>
<p>Well, the ID has to be generated on-the-fly and out of nowhere. Still easy?</p>
<p>One might think about using MySQL user variables to accomplish this, sure. But what if your framework does not allow injecting chained queries because of SQL injection countermeasures?<br />
<span id="more-914"></span><br />
The framework I used, WordPress&#8217; wpdb API to be exact, has such a restriction, which caused my to find an alternate way.</p>
<p>To illustrate the problem, I start with the date retrieved, which would normally look as shown below.</p>
<pre>mysql&gt; SELECT value1, value2 FROM sample_table;
+-----------------+-----------------+
| value1          | value2          |
+-----------------+-----------------+
| sample_value_1  | sample_value_2  |
| sample_value_a  | sample_value_b  |
+-----------------+-----------------+
2 rows in set (0.00 sec)</pre>
<p>Now, I need a line number for each record. When talking abut the line number, I&#8217;m strictly talking about a representation of &#8220;this is the first line&#8221;, &#8220;this is the second line&#8221;, etc.<br />
This particular line number must therefore not be identical to the tupel ID, if that even would exist.<br />
So this is what I would expect:</p>
<pre>
+------------+-----------------+-----------------+
| line_num   | value1          | value2          |
+------------+-----------------+-----------------+
| 1          | sample_value_1  | sample_value_2  |
| 2          | sample_value_a  | sample_value_b  |
+------------+-----------------+-----------------+
</pre>
<p>To generate this by the means of a query, one would usually use a MySQL user variable, that would be dynamically increased for each data row.<br />
In SQL speech the query would then look like this:</p>
<pre>
SELECT @line:=0;
SELECT @line:=@line+1 AS line_num, value1, value2 FROM sample_table;
+------------+-----------------+-----------------+
| line_num   | value1          | value2          |
+------------+-----------------+-----------------+
| 1          | sample_value_1  | sample_value_2  |
| 2          | sample_value_a  | sample_value_b  |
+------------+-----------------+-----------------+
</pre>
<p>It&#8217;s actually easy and conventient, and you get real, dynamically calculated &#8220;line numbers&#8221;. But this technique requires to actually run two statements to be run in a series.<br />
If you&#8217;re using your own database routines, this may not be a problem at all. But if you rely on a given framework, you may trip into SQL injection counter measures which will simply throw away a query constructed like this:</p>
<pre>
$my_query = "SELECT @line:=0; SELECT @line:=@line+1 AS line_num, value1, value2 FROM sample_table;";

$my_result = $pseudo_call_to_my_db_framework-&gt;execute( $my_query );
</pre>
<p>This was ecactly what I was trying to do with WordPress&#8217; wpdb API. However, as I found, SQL injection filters kicked in. This is absolutely not to blame the WordPress folks, of course. The filters in place serve a good purpose and thus forced me in taking a different approach.</p>
<p>After some searching on the net I found that I seemed to be the only one to be using users vars with wpdb :-/<br />
Of course, while this may not be widely used, I insisted in this approach. Suggestions in adding a loop or an extra-query where inappropriate to me, because it had to fit within the existing code base. That again required me to specifically do it in one SQL query, because I simply did not want to bloat the code by adding another loop in there.</p>
<p>So, the question is: Can the procedure described above be performed within ONE single query.</p>
<p>The answer is: Yes, but you&#8217;re required to invole a sub-query to achive this.</p>
<p>At first, leave the initial variable assignment away, so you end up with this query:</p>
<pre>
SELECT @line:=@line+1 AS line_num, value1, value2 FROM sample_table;
</pre>
<p>This would of course not yet work, because the user variable @line wouldn&#8217;t yet be defined at runtime.<br />
Since you can&#8217;t prepend the declaration, you need to embed it using a sub-query. This is needed to have the variable declaration ready at the earliest stage possible, namely while parsing the query, and not during result processing.</p>
<p>Let&#8217;s look at the final query and the comments:</p>
<pre>
SELECT
        @line:=@line+1 AS line_num,                     # increase the @line user variable for each row retrieved
        sample_table.value1,                            # include column 'value1' from table 'sample_table'
        sample_table.value2                             # include column 'value2' from table 'sample_table'
FROM
        (SELECT @line:=0) AS tmp_line,                  # this will fire during parsing: initialize the user var by selecting it into a dummy table
        sample_table;                                   # now add our actual data table as well
</pre>
<p>This way, you end up getting the same result as shown earlier. And yet, this query can be performed with WordPress&#8217; wpdb API and maybe other frameworks as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2012/01/27/working-around-wordpress-wpdb-limitations-with-mysql-user-variables/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Run command in background from PHP</title>
		<link>http://phaq.phunsites.net/2012/01/18/run-command-in-background-from-php/</link>
		<comments>http://phaq.phunsites.net/2012/01/18/run-command-in-background-from-php/#comments</comments>
		<pubDate>Tue, 17 Jan 2012 23:40:21 +0000</pubDate>
		<dc:creator>gdelmatto</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=904</guid>
		<description><![CDATA[While working on my newest project, a PHP- and AJAX-based network management application, I came along the need to run multiple commands on the server and track their return states (basically if they were run successful or not). While sticking together my framework, I found that forking a process into background from PHP requires some [...]]]></description>
			<content:encoded><![CDATA[<p>While working on my newest project, a PHP- and AJAX-based network management application, I came along the need to run multiple commands on the server and track their return states (basically if they were run successful or not).</p>
<p>While sticking together my framework, I found that forking a process into background from PHP requires some additional steps if you don&#8217;t want to break AJAX functionality.<br />
<span id="more-904"></span><br />
Here&#8217;s a sketch of the basic concept. It involves a Dispatcher, which creates a workqueue item in a database, and then forks a background process, which will perform various tasks. The latter will then report back the states of the tasks performed to the workqueue item in the database.<br />
On the other end, a Tracker will check the database for the running states and push progress information into the browser.</p>
<p><a href="http://phaq.phunsites.net/files/2012/01/ajax_dispatcher.png" rel="lightbox[904]"><img src="http://phaq.phunsites.net/files/2012/01/ajax_dispatcher-300x300.png" alt="" width="300" height="300" class="aligncenter size-medium wp-image-905" /></a></p>
<p>While it was working to some extent, my initial attempts at forking a background process from PHP failed terribly, because PHP always kept waiting for the command to complete.<br />
This behaviour had the side effect that the Dispatcher couldn&#8217;t immediately return the workqueue id to the AJAX client (the browser). But since the workqueue id was required by the AJAX-client to subsequently fire the Tracker, the initial request to the Dispatcher had to be synchronous instead of asynchronous.<br />
The blocking behaviour did however screw everything, so I had to find a way around.</p>
<p>Of course, I was thinking about the various methods in calling external commands from PHP, starting with simple backticks, exec(), passthru() and even popen(), despite some others as well.</p>
<p>People familiar to Unix/Linux environments would of course say, that a background task can be started easily by appending an ampersand to the end, making it look like this:</p>
<p><code><br />
exec( '/path/to/my/command &amp;' );<br />
system( '/path/to/my/command &amp;' );<br />
</code></p>
<p>But that does not work in PHP, because all calls are always waiting for the command to return.<br />
PHP effectively binds the STDERR and STDOUT I/O streams during execution, which is why a simple ampersand doesn&#8217;t work out.<br />
To get this to work, one must really detach the to-be-backgrounded program from the controlling terminal to trick PHP into returning from exec.</p>
<p>This can be done easily by redirecting STDOUT and STDERR to a logfile or /dev/null before background the program, and just return the pid.<br />
That would then look similar to this:</p>
<p><code><br />
exec( '/path/to/some/program &gt; /dev/null 2&gt;&amp;1 &amp; echo $!' );<br />
</code></p>
<p>The above example would detach the programm into background while returning control to your PHP application at once.</p>
<p>Consider the output destination being required in any case, otherwise the I/O streams won&#8217;t get detached.<br />
So this syntax, while being perfectly valid, will definitely run your command, but won&#8217;t place it into background at all:</p>
<p><code><br />
exec( '/path/to/some/program 2&gt;&amp;1 &amp; echo $!' );<br />
</code></p>
<p>That&#8217;s it <img src='http://phaq.phunsites.net/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2012/01/18/run-command-in-background-from-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Convert a Perl Hash of Hashes into XML with XML::Dumper</title>
		<link>http://phaq.phunsites.net/2012/01/09/convert-a-perl-hash-of-hashes-into-xml-with-xmldumper/</link>
		<comments>http://phaq.phunsites.net/2012/01/09/convert-a-perl-hash-of-hashes-into-xml-with-xmldumper/#comments</comments>
		<pubDate>Mon, 09 Jan 2012 15:01:46 +0000</pubDate>
		<dc:creator>gdelmatto</dc:creator>
				<category><![CDATA[Perl]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=890</guid>
		<description><![CDATA[For a project of mine, I wanted to convert a Perl data structure, a so called Hash of Hashes, into an XML. The simple solution to this is to use the XML::Dumper module. Let&#8217;s suppose your data structure looks like this: %hash_of_hashes = { item1 =&#62; { item1_1 =&#62; 'value1_1', item1_2 =&#62; 'value1_2', }, item2 [...]]]></description>
			<content:encoded><![CDATA[<p>For a project of mine, I wanted to convert a Perl data structure, a so called Hash of Hashes, into an XML.</p>
<p>The simple solution to this is to use the <a href="http://search.cpan.org/~mikewong/XML-Dumper-0.81/Dumper.pm" target="_blank">XML::Dumper</a> module.<br />
<span id="more-890"></span><br />
Let&#8217;s suppose your data structure looks like this:</p>
<pre>%hash_of_hashes = {
    item1 =&gt; {
                item1_1       =&gt; 'value1_1',
                item1_2       =&gt; 'value1_2',
    },
    item2 =&gt; {
                item2_1       =&gt; 'value2_1',
                item2_2       =&gt; 'value2_2',
    },
  };</pre>
<p>You can easily convert this into an XML representation using this command:</p>
<p><code><br />
my $xml_output  = XML::Dumper::pl2xml( \%hash_of_hashes );<br />
</code></p>
<p>So you&#8217;ll end up with this output:</p>
<pre>&lt;perldata&gt;
 &lt;hashref memory_address="0x878e784"&gt;
 &lt;item key="item1"&gt;
 &lt;hashref memory_address="0x87a8c58"&gt;
 &lt;item key="item1_1"&gt;value1_1&lt;/item&gt;
 &lt;item key="item1_2"&gt;value1_2&lt;/item&gt;
 &lt;/hashref&gt;
 &lt;/item&gt;
 &lt;item key="item2"&gt;
 &lt;hashref memory_address="0x87a8c61"&gt;
 &lt;item key="item2_1"&gt;value2_1&lt;/item&gt;
 &lt;item key="item2_2"&gt;value2_2&lt;/item&gt;
 &lt;/hashref&gt;
 &lt;/item&gt;
 &lt;/hashref&gt;
&lt;/perldata&gt;</pre>
<p>But be aware: You need to pass the hash by reference, imposing the <strong>\%hash_of_hashes</strong> notation, otherwise you end up with something like this:</p>
<pre>&lt;perldata&gt;
 &lt;scalar&gt;item_1&lt;/scalar&gt;
 &lt;scalar&gt;item_2&lt;/scalar&gt;
&lt;/perldata&gt;</pre>
<p>It&#8217;s so obvious, but I had overlooked that as well in the first attempts <img src='http://phaq.phunsites.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2012/01/09/convert-a-perl-hash-of-hashes-into-xml-with-xmldumper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VpnInit AppleScript: Override and Restore Default VPN-Routes on OS X</title>
		<link>http://phaq.phunsites.net/2011/12/29/vpninit-applescript-override-and-restore-default-vpn-routes-on-os-x/</link>
		<comments>http://phaq.phunsites.net/2011/12/29/vpninit-applescript-override-and-restore-default-vpn-routes-on-os-x/#comments</comments>
		<pubDate>Thu, 29 Dec 2011 17:37:04 +0000</pubDate>
		<dc:creator>gdelmatto</dc:creator>
				<category><![CDATA[Networking]]></category>
		<category><![CDATA[OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Utilities]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=876</guid>
		<description><![CDATA[Years ago I wrote a small script to restore local default route after connecting the RAS VPN on Windows. Now, I made up a similar script to do the same on OS X. The basic idea, now and then, was that I would not want to send all traffic through the VPN. Thus the script [...]]]></description>
			<content:encoded><![CDATA[<p>Years ago I wrote a small script <a href="/2007/06/06/ras_initvbs-override-and-restore-routes-with-windows-ras/">to restore local default route after connecting the RAS VPN on Windows</a>.</p>
<p>Now, I made up a similar script to do the same on OS X.<br />
<span id="more-876"></span><br />
The basic idea, now and then, was that I would not want to send all traffic through the VPN.<br />
Thus the script will assist in restoring your local default route after the VPN connection is established.<br />
Furthermore, it&#8217;ll add some specific routes directed to the VPN.</p>
<p>This way, all your usual traffic (internet, surfing, skype, whatever) is sent through your default gateway, while more specific routes (your business stuff) is sent through the VPN.</p>
<p>Below&#8217;s the code for the initial release. It may lack some details yet, like auto-detecting the tunnel device name, but it does the job already.</p>
<p>Just copy the code into Apple Script Editor and save it to a convenient location. Make sure you save it as &#8220;Application&#8221; and not as &#8220;Script&#8221; (which is the default). You you don&#8217;t, double-clicking the script will open the Script Editor instead of executing the script. Surely, not what you want.</p>
<p>Pay attention to the variables on the top, which need to be edited before you save the Script: _vpn_name, _default_gw, _networks, and _sudo_password (optional).<br />
I hope directions are clear enough from the comments sections.</p>
<pre>
# VpnInit
# ---
# an AppleScript utility to connect your vpn,
# restore local default route and add selected
# routes directed to the VPN only
# thus you'll end up sending only selected
# traffic through the VPN, while the rest
# goes through your local default gateway
# as usual
# ---
# released "as is" under the terms of GPL v2.
# Copyright © 2011 Gianpaolo Del Matto
# 
# r0.1 initial release 2011/12/29
#
# ToDo:
# - hardcoding the "sudo" password is a bad idea, maybe
#	need a better way to get away with it
# - vpn tunnel (utun0) is still hardcoded,
#	should be auto-detected
#

# the name of your vpn connection
#
set _vpn_name to "My VPN"

# your local default gateway
#
set _default_gw to "192.168.1.1"

# your remote networks to pass via VPN, separate multiple with comma
# like so: {"1.2.3.4/30", "5.6.7.8/30"}
#
set _networks to {"192.168.2.1/24"}

# your super-user (root) password
# actually needed to bypass the prompts
# leave empty to get prompted
#
set _sudo_password to ""

# ##################################################################
# DO NOT CHANGE ANYTHING BELOW
# ##################################################################

# kindly borrowed from
# http://www.macosxautomation.com/applescript/uiscripting/index.html
# make sure that support for assistive devices is enabled
#
tell application "System Events"
	if UI elements enabled is false then
		tell application "System Preferences"
			activate
			set current pane to pane id "com.apple.preference.universalaccess"
			display dialog "This script requires access for assistive devices be enabled." &amp; return &amp; return &amp; "To continue, click the OK button and enter an administrative password in the forthcoming security dialog." with icon 1
		end tell
		set UI elements enabled to true
		if UI elements enabled is false then
			display dialog "This script cannot run while access for assistive devices is disabled." &amp; return &amp; "Exiting now." buttons {"OK"} with icon 2
			return "user cancelled"
		end if
	end if
end tell

# now dive into the VPN setup part
#
tell application "System Events"
	set _if_tunnel to "utun0" #	do not change, will be auto-detected, just giving a reasonable default
	tell current location of network preferences
		if exists service _vpn_name then
			# try to connect the VPN service if it's disconnected
			#
			if current configuration of service _vpn_name is not connected then
				connect service _vpn_name
			end if

			# give it some time to settle
			#
			set _retval to false
			repeat until (_retval) is true
				set counter to 0
				repeat while counter is less than 16
					# exit if we get connected
					#
					if current configuration of service _vpn_name is connected then
						set _retval to true
						exit repeat
					end if

					# opt for exit if still not connected after 15 seconds
					#
					if counter is equal to 15 then
						display dialog "VPN '" &amp; _vpn_name &amp; "' is still not connected after 15 seconds. Do you want to keep waiting?" with title "VPN still not connected" buttons {"Yes", "No"}
						if button returned of result is "No" then
							# bail out if user decided not to wait any longer
							#
							set _retval to true
							return
						else
							# otherwise reset the counter so we can trigger again
							#
							set counter to 0
						end if
					end if

					set counter to counter + 1
					delay 1
				end repeat
			end repeat

			# now go to post processing and to the following:
			# - delete default route via vpn
			# - restore original default route
			# - add specific routes to vpn
			#
			if current configuration of service _vpn_name is connected then
				# restore local default route
				#
				do shell script "route delete default" password _sudo_password with administrator privileges
				do shell script "route add default " &amp; _default_gw password _sudo_password with administrator privileges

				# inject custom routes via VPN
				#
				repeat with _network in _networks
					do shell script "route add -interface " &amp; _network &amp; " utun0" password _sudo_password with administrator privileges
				end repeat
			end if
		else
			# bail out if the VPN service does not exist
			#
			display dialog "Given VPN '" &amp; _vpn_name &amp; "' does not exist. Please check the name"
		end if
	end tell
end tell
</pre>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2011/12/29/vpninit-applescript-override-and-restore-default-vpn-routes-on-os-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automating MakeMKV with AppleScript</title>
		<link>http://phaq.phunsites.net/2011/12/15/automating-makemkv-with-applescript/</link>
		<comments>http://phaq.phunsites.net/2011/12/15/automating-makemkv-with-applescript/#comments</comments>
		<pubDate>Thu, 15 Dec 2011 21:56:14 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=858</guid>
		<description><![CDATA[It&#8217;s only days since I wrote about a custom script action upon inserting a DVD in OS X, allowing me have either run the DVD Player or MakeMKV to rip the DVDs. Now I was digging around if I could do some automation on the GUI part, which indeed turned out to work &#8230; at [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s only days since I wrote about <a href="/make-os-x-run-custom-actions-upon-dvd-insert">a custom script action upon inserting a DVD</a> in OS X, allowing me have either run the DVD Player or MakeMKV to rip the DVDs.</p>
<p>Now I was digging around if I could do some automation on the GUI part, which indeed turned out to work &#8230; at least to a certain degree.<br />
<span id="more-858"></span><br />
Let&#8217;s face it: Ripping DVDs with MakeMKV is simple and easy, however its scripting abilities s*** <img src='http://phaq.phunsites.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>There is actually some limited CLI support available. If you dive into the application package, you&#8217;ll find the <b>/Applications/MakeMKV.app/Contents/MacOS/makemkvcon</b> program, which can be scripted somehow.</p>
<p>In the first place, I was perfectly able to rip off a complete DVD using the CLI command. But that was not what I had in mind, because I wanted to select only the main movies, and there only a limited set of audio streams and subtitles.<br />
As I seemed to be unable to figure out, how that would be possible (some rare comments on the <a href="http://www.makemkv.com/forum2/" target="_blank">MakeMKV forums</a> mentioned, that it would NOT be possible), I ended up using the GUI.</p>
<p>Well, after I wrote the auto-selector script, I started thinking on how to make this a bit more practical.<br />
I know Apple released support for GUI (graphical user interface) scripting already years ago, but I had never really looked into until today <img src='http://phaq.phunsites.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>After some reading over there at <a href="http://www.macosxautomation.com/applescript/uiscripting/index.html" target="_blank">macosxautomation.com</a> I started on extending my script.<br />
Please consider that you need to enable support for assistive devices, as mentioned on macosxautomation.com &#8212; otherwise the script will simply fail.</p>
<p>With help of <a href="http://pfiddlesoft.com/uibrowser" target="_blank">UI Browser</a>, a utility to explore GUI elements of any application, I was able to identify the relevant items.</p>
<p>So with the latest additions, the script does the following:</p>
<ul>
<li>Runs whenever a DVD is inserted</li>
<li>Automatically run DVD Player if no action is taken &#8211; or -</li>
<li>run MakeMKV if requested to do so</li>
<li>Wait for the DVD TOC (table of contents) to be read initially</li>
<li>As soon as the TOC is read, open the DVD in MakeMKV</li>
<li>Wait until the tracks selected were ripped and try to eject the DVD afterwards</li>
</ul>
<p>And here&#8217;s the code:</p>
<pre>
# dvd-action
# ---
# an AppleScript utility to select DVD Player or MakeMKV
# upon inserting a DVD
# ---
# released "as is" under the terms of GPL v2.
# Copyright © 2011 Gianpaolo Del Matto <www.phunsites.net>
# 
# r0.1 initial release 2011/12/09
# - simple selector with default action after timeout
#
# r0.2 2011/12/15
# - added limited GUI scripting functionality for MakeMKV
#
# r0.3 2011/12/16
# - added support to check for assistive device access
#	(code borrowed from http://www.macosxautomation.com)
# - added simple progress indicator while waiting for drive
#	do become available for access
#

# initialization
#
# true : show progress dialogs, false: hide progress dialogs
set verbose to true

# kindly borrowed from
# http://www.macosxautomation.com/applescript/uiscripting/index.html
# make sure that support for assistive devices is enabled
#
tell application "System Events"
	if UI elements enabled is false then
		tell application "System Preferences"
			activate
			set current pane to pane id "com.apple.preference.universalaccess"
			display dialog "This script requires access for assistive devices be enabled." &#038; return &#038; return &#038; "To continue, click the OK button and enter an administrative password in the forthcoming security dialog." with icon 1
		end tell
		set UI elements enabled to true
		if UI elements enabled is false then
			display dialog "This script cannot run while access for assistive devices is disabled." &#038; return &#038; "Exiting now." buttons {"OK"} with icon 2
			return "user cancelled"
		end if
	end if
end tell

# check if DVD Player or MakeMKV are already running
# if not, present a little menu, that allows to select
# which application should be run
#
if not appIsRunning("DVD Player") and not appIsRunning("MakeMKV") then

	with timeout of 3600 seconds
		display dialog "Please choose your desired action:" with title "Action for DVD" buttons {"Cancel", "play DVD", "rip DVD"} cancel button "Cancel" giving up after (5)
	end timeout
	if button returned of result is "rip DVD" then
		if verbose then display dialog "Starting MakeMKV" buttons {"OK"} giving up after 2
		tell application "MakeMKV" to activate
		repeat
			if application "MakeMKV" is running then exit repeat
			delay 5
		end repeat

	else if button returned of result is "Cancel" then
		return
	else
		if verbose then display dialog "Starting DVD Player" buttons {"OK"} giving up after 2
		tell application "DVD Player" to activate
		return
	end if

end if

# check again if MakeMKV is running
# this time, attempt to automate these steps:
# - automatically open the DVD as soon as the drive is ready for access
#
if appIsRunning("MakeMKV") then
	# now tell MakeMKV what to do
	tell application "System Events"
		tell process "MakeMKV"
			# in some rare cases, the menu bar items will stay "greyed out"
			# even if a DVD was inserted
			# the culprit: "AXEnabled" property of the menu will be TRUE even then,
			# although the menu items are not clickable
			# There seems to be no way to check, if they're actually active or inactive
			# However, as a workaround, sending CMD+O to fire up the "File - Open" dialog
			# seems to work, and yet: just opening and closing it will enable the menu bar
			#
			set _retval to false
			repeat until (_retval) is true
				try
					tell application "MakeMKV" to activate
					keystroke "o" using {command down}
					delay 1

					if (exists window 1) and (exists window 2) and (value of attribute "AXRoleDescription" of window 1) = "dialog" then
						click button "Cancel" of window 1
						set _retval to true
					end if
				end try
				delay 1
			end repeat

			# note on the dvd drive selection and menu handling:
			#
			# because we don't know the name of the DVD device,
			# we simply address it by the id of 'menu item 1'
			# so we're just selecting the first device found there.
			# we might have more than one DVD drive, but this is out of scope for now
			#
			# this script was initially triggered by inserting a new disc
			# thus we need to wait until the disc is initially read
			# while this is in progress, our 'Open disc' menu item will be disabled
			#
			set _retval to false
			repeat until (_retval) is true
				try
					repeat while (value of attribute "AXEnabled" of menu "Open disc" of menu item "Open disc" of menu "File" of menu bar item "File" of menu bar 1) is false
						get value of attribute "AXEnabled" of menu "Open disc" of menu item "Open disc" of menu "File" of menu bar item "File" of menu bar 1
						set counter to 5
						repeat while counter is greater than 0
							if verbose then display dialog "Waiting for dvd drive to become ready for use ..." with title "Please wait …" buttons {"" &#038; counter &#038; ""} giving up after 1
							set counter to counter - 1
						end repeat
					end repeat
					set _retval to true
				on error
					display dialog "error"
				end try
				delay 1
			end repeat

			# seems that the dvd drive is now ready for use, now try to load the disc
			#
			if verbose then display dialog "Trying to load DVD in MakeMKV now …" giving up after 1

			# now load the drive
			#
			tell application "MakeMKV" to activate
			click menu item 1 of menu 1 of menu item "Open disc" of menu 1 of menu bar item "File" of menu bar 1

			# now stay and wait until another window appears
			# this should be "completed" dialog at the end
			#
			repeat until ((exists window 1) and (exists window 2))
				delay 15
			end repeat

			# check the type of window 1, which should be a dialog
			# if so, let's close it and try to eject the disk
			#
			if (exists window 1) and (exists window 2) and ((value of attribute "AXRoleDescription" of window 1) = "dialog" or (value of attribute "AXRoleDescription" of window 1) = "standard window") then
				click button 1 of window 1

				click menu item "Eject disc" of menu 1 of menu bar item "File" of menu bar 1
			end if

		end tell
	end tell
end if

# func:appIsRunning
#	appName	: string : name of application (e.g. "DVD Player")
#
# helper to check if application is running or not
#
on appIsRunning(appName)
	tell application "System Events" to (name of processes) contains appName
end appIsRunning
</pre>
<p>This, as far as it goes, saves at least the additional button click to load the DVD in MakeMKV.<br />
However, there is one drawback after all &#8230;</p>
<p>While examining the MakeMKV GUI, I figured that the main panel was not recognized by UI Browser. It was just reported as <b>unknown (UI element #4)</b>. Unfortunately there was no obvious way to get access to the elements within that panel.<br />
This &#8211; as of today &#8211; effectively limits the use of GUI scripting, as it is not possible to interact with the elements within that panel.<br />
Otherwise, I&#8217;d be happy to sit down and write the part, which does auto-selection of the track elements according to some given criteria.</p>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2011/12/15/automating-makemkv-with-applescript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Interface-Statistiken in Cacti für Swisscom CentroGrande erstellen</title>
		<link>http://phaq.phunsites.net/2011/12/13/interface-statistiken-in-cacti-fur-swisscom-centrogrande-erstellen/</link>
		<comments>http://phaq.phunsites.net/2011/12/13/interface-statistiken-in-cacti-fur-swisscom-centrogrande-erstellen/#comments</comments>
		<pubDate>Tue, 13 Dec 2011 22:31:53 +0000</pubDate>
		<dc:creator>gdelmatto</dc:creator>
				<category><![CDATA[HowTo's]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=806</guid>
		<description><![CDATA[Als Follow-Up zu meinem letzten Post über den Swisscom CentroGrande Router, widme ich mich nun erneut diesem Gerät. Heute geht es darum, Interface-Statistiken in Cacti zu erzeugen &#8212; und das obwohl der CentroGrande den hierfür nötigen SNMP-Support schmerzlich vermissen lässt. Auch wenn der CentroGrande als Consumer-Gerät positioniert ist, wäre für mich &#8211; und wohl auch [...]]]></description>
			<content:encoded><![CDATA[<p>Als Follow-Up zu meinem letzten Post über den <a href="/2011/12/03/swisscom-centro-grande-aufbohren/">Swisscom CentroGrande</a> Router, widme ich mich nun erneut diesem Gerät. Heute geht es darum, Interface-Statistiken in Cacti zu erzeugen &#8212; und das obwohl der CentroGrande den hierfür nötigen SNMP-Support schmerzlich vermissen lässt.</p>
<p><span id="more-806"></span><br />
Auch wenn der CentroGrande als Consumer-Gerät positioniert ist, wäre für mich &#8211; und wohl auch einige andere &#8211; SNMP das Mittel der Wahl zur Überwachung des Geräts wie auch des Netzwerks.</p>
<p>Wenn man die normalerweise deaktivierte Pirelli Management Console auf dem Router aktiviert, gelangt man zwar an einige offiziel nicht zugängliche Funktionen, SNMP ist da aber definitiv nicht dabei. Zwar kann man über die Pirelli Console die Konfigurationsdatei einsehen &#8211; und findet dort auch Hinweise auf SNMP &#8211; doch selbst wer des SNMP-Feature in der Konfiguration manuell aktiviert, wird nach einem Neustart bitter enttäuscht: Weit und breit kein SNMP aktiv <img src='http://phaq.phunsites.net/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> </p>
<p>Glücklicherweise kann man aber auch für den CentroGrande Interface-Statistiken erzeugen, auch wenn man dafür gewissermassen mit der Kirche ums Dorf herum gehen muss.</p>
<p>Der Trick liegt im Command Line Interface, welches per Telnet und SSH erreichbar ist. Hier kann mit dem Befehl &#8220;net ifcnt all&#8221; für jede Schnittstelle des Routers eine Statistik ausgegeben werden.<br />
Ersetzt man das Schlüsselwort &#8220;all&#8221; durch die Interface-Bezeichnung, bspw. &#8220;wl0&#8243;, erhält man die jeweiligen Einzelstatistiken.</p>
<p>Im folgenden Beispiel werden die Statistiken zur WAN-Schnittstelle angezeigt:</p>
<p><code><br />
[~] # ssh admin@192.168.100.254<br />
OpenRG> net ifcnt eth5.10<br />
---- Driver statistics: port "LAN Fiber VLAN 10" ----<br />
	Device name: eth5.10 - Type: 48, Ethernet<br />
	Network = WAN<br />
	Port status = Connected<br />
	Counters<br />
	  Rx Packets:        2006090<br />
	  Tx Packets:        2477100<br />
	  Rx Bytes:          835058499<br />
	  Tx Bytes:          2356068887<br />
	  Rx Pkts Errors:    0<br />
	  Tx Pkts Problems:  0<br />
	  Rx Dropped Pkts:   0<br />
	  Tx Dropped Pkts:   0<br />
	  Rx Multicast Pkts: NA<br />
	  Tx Multicast Pkts: NA<br />
	  Rx Broadcast Pkts: NA<br />
	  Tx Broadcast Pkts: NA<br />
	  Collisions:        NA</p>
<p>Returned 0<br />
OpenRG><br />
</code></p>
<p>Wer sich in der Pirelli Console schon umgesehen hat, ist vielleicht angesichts der vielen Schnittstellen etwas überfordert.<br />
Die gute Nachricht: Die meisten davon braucht&#8217;s nur für interne Zwecke und sind für die Überwachung kaum relevant. Daher hier eine Auflistung der notwendigen Schnittstellen und deren Funktion:</p>
<pre>
eth0         Switchport 1
eth1         Switchport 2
eth2         Switchport 3
eth3         Switchport 4
wl0          WLAN Access Point
eth5.10      WAN Schnittstelle (Fiber oder DSL)
</pre>
<p>Damit diese Daten nun für Cacti nutzbar werden, bedarf es eines Hilfsprogramms, welches folgende Schritte durchführt:</p>
<ul>
<li>Login auf den Router</li>
<li>Abrufen der Interface-Ststistiken</li>
<li>Ausgabe der bereinigten Informationen</li>
</ul>
<p>Gerade letzterem kommt eine grosse Bedeutung zu, da die Ausgabe wiederum scriptbasiert verarbeitet werden soll und somit normalisiert werden muss.<br />
Wie dies im Detail aussieht, beschreibt die <a href="http://www.cacti.net/downloads/docs/html/making_scripts_work_with_cacti.html" target="_blank">Cacti-Dokumentation</a>.</p>
<p>Basierend auf einem Beispiel-Script aus dem py-expect Package habe ich eine stark abgewandelte Version erstellt, welche allein dem Auslesen des CentroGrande dient und vollständig parametrisierbar ist.<br />
Damit das Script ausführbar wird, sind zum Beispiel unter Debian die Packages python2.5 und python-pexpect erforderlich.</p>
<p>Das ganze sieht beim Ausführen dann wie folgt aus:</p>
<pre>
[~] # /opt/sbin/cg_ifstats.py -u admin -p password -h 192.168.100.254 -i wl0
RxBytes:4230422745 TxBytes:3249795610
</pre>
<p>Damit steht bereits der erste Baustein bereit. Nun muss Cacti noch entsprechend eingerichtet werden, damit die Script-Ausgabe zur Erstellung von Statistiken verwendet werden.</p>
<p>Anweisungen dazu finden sich ebenfalls in der <a href="http://www.cacti.net/downloads/docs/html/how_to.html" target="_blank">Cacti-Dokumentation</a>.</p>
<p>Die nachfolgenden Schritte verdeutlichen dies anhand einiger Screenshoots.<br />
Man kann &#8211; und darf <img src='http://phaq.phunsites.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  &#8211; es sich aber auch ein bisschen einfacher machen und einfach das Data Template mit den Abhängigkeiten direkt importieren.<br />
Das Data Template kann zusammen mit dem Python Script <a href='http://phaq.phunsites.net/files/2011/12/cg_ifstats.zip'>hier heruntergeladen</a> werden.</p>
<p>Wer die erforderlichen Schritte selbst durchführen möchte, erstellt zuerst eine sogenannte Date Input Method nach dem gezeigten Vorbild.<br />
Dabei müssen insbesonders die Input wie auch die Output Fields erfasst werden (auf Schreibweise achten).<br />
Die Data Input Method wird unter der Bezeichnung &#8220;CentroGrande &#8211; IFSTATS&#8221; gespeichert.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/data_input1.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/data_input1-300x100.png" alt="" width="300" height="100" class="aligncenter size-medium wp-image-813" /></a></p>
<p>Anschliessend wird ein neues Data Template mit der Bezeichnung &#8220;CentroGrande &#8211; Traffic&#8221; erzeugt.<br />
Unter Data Input Method wird die zuvor erstellte Datenquelle &#8220;CentroGrande &#8211; IFSTATS&#8221; verwendet.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/data_template1.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/data_template1-300x76.png" alt="" width="300" height="76" class="aligncenter size-medium wp-image-814" /></a></p>
<p>Weiterhin benötigt das Data Template die Quelldatensätze, &#8220;traffic_in&#8221; und &#8220;traffic_out&#8221;. Diese werden mit den einzelnen Zählern der Data Input Method &#8220;CentroGrande &#8211; IFSTATS&#8221; verbunden, also &#8220;traffic_in&#8221; mit &#8220;RxBytes&#8221; und &#8220;traffic_out&#8221; mit &#8220;TxBytes&#8221;.<br />
Wichtig ist, dass als &#8220;Data Source Type&#8221; der Typ &#8220;COUNTER&#8221; verwendet wird.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/data_template2.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/data_template2-300x68.png" alt="" width="300" height="68" class="aligncenter size-medium wp-image-815" /></a></p>
<p><a href="http://phaq.phunsites.net/files/2011/12/data_template3.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/data_template3-300x68.png" alt="" width="300" height="68" class="aligncenter size-medium wp-image-816" /></a></p>
<p>Unter &#8220;Custom Data&#8221; wird bei allen Feldern die Checkbox &#8220;User Per-Data Source Value&#8221; markiert.<br />
Dies ist erforderlich, damit beim folgenden Erzeugen der Graphen die Werte pro Host und Datenquelle einzeln definiert werden können.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/data_template4.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/data_template4-300x45.png" alt="" width="300" height="45" class="aligncenter size-medium wp-image-817" /></a></p>
<p>Nun fehlt das Graph Template. Hierfür klont man am einfachsten eines der bestehenden Graph Templates, beispielsweise &#8220;Interface &#8211; Traffic (bits/sec, Total Bandwidth)&#8221;.<br />
Das geklonte Graph Template bedarf noch einiger Anpassungen, insbesonders bei den Graph Template Items und Graph Item Inputs.<br />
Als Letztere dienen die bereits zuvor definierten Datenquellen &#8220;traffic_in&#8221; und &#8220;traffic_out&#8221;.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/graph_template1.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/graph_template1-300x100.png" alt="" width="300" height="100" class="aligncenter size-medium wp-image-819" /></a></p>
<p>Die Datenquell muss auch bei den Graph Template Items noch entsprechend zu &#8220;traffic_in&#8221; und &#8220;traffic_out&#8221; angepasst werden. </p>
<p><a href="http://phaq.phunsites.net/files/2011/12/graph_template2.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/graph_template2-300x95.png" alt="" width="300" height="95" class="aligncenter size-medium wp-image-820" /></a></p>
<p>Damit wäre soweit alles vorbereit, dass nun ein Host-Objekt für den Centro Grande erfasst werden kann.<br />
Anschliessend werden dem Host-Objekt neue Graphs hinzugefügt.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/create_graph1.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/create_graph1-300x36.png" alt="" width="300" height="36" class="aligncenter size-medium wp-image-811" /></a></p>
<p>Je nach Bedarf werden für einzelne oder alle Schnittstelle (wl0, eth5.10, eth0, usw) die Graphen erzeugt.<br />
Dazu muss man zur besseren Unterscheidung unter Title auch die jeweilige Schnittstellenbezeichnung ergänzt werden.<br />
Ferner sind in den Feldern für Username, Passwort, Hostname und Interface die erforderlichen Daten einzutragen.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/create_graph2.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/create_graph2-300x78.png" alt="" width="300" height="78" class="aligncenter size-medium wp-image-812" /></a></p>
<p><a href="http://phaq.phunsites.net/files/2011/12/graph_list.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/graph_list-300x69.png" alt="" width="300" height="69" class="aligncenter size-medium wp-image-818" /></a></p>
<p>Nach Abschluss aller Schritte lassen sich fortan die erzeugten Graphs in Cacti bewundern.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/graphs.png" rel="lightbox[806]"><img src="http://phaq.phunsites.net/files/2011/12/graphs-300x150.png" alt="" width="300" height="150" class="aligncenter size-medium wp-image-821" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2011/12/13/interface-statistiken-in-cacti-fur-swisscom-centrogrande-erstellen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Make OS X run custom actions upon DVD insert</title>
		<link>http://phaq.phunsites.net/2011/12/11/make-os-x-run-custom-actions-upon-dvd-insert/</link>
		<comments>http://phaq.phunsites.net/2011/12/11/make-os-x-run-custom-actions-upon-dvd-insert/#comments</comments>
		<pubDate>Sun, 11 Dec 2011 10:44:39 +0000</pubDate>
		<dc:creator>gdelmatto</dc:creator>
				<category><![CDATA[OS X]]></category>
		<category><![CDATA[Operating Systems]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=837</guid>
		<description><![CDATA[I&#8217;m currently ripping my complete DVD collection off to MKV (Matroska) format, so I can stream them across my home network. So I sought a way to have my OS X give me the choice to either start DVD Player or MakeMKV upon inserting a DVD. First I wrote a little AppleScript which gives me [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m currently ripping my complete DVD collection off to MKV (Matroska) format, so I can stream them across my home network.</p>
<p>So I sought a way to have my OS X give me the choice to either start DVD Player or <a href="http://www.makemkv.com/" target="_blank">MakeMKV</a> upon inserting a DVD.<br />
<span id="more-837"></span><br />
First I wrote a little AppleScript which gives me the choice. If I&#8217;m not taking any action, it will play the DVD automatically after 5 seconds, so it&#8217;s very similar to the default behaviour of OS X.</p>
<p>So just run Apple Script-Editor and store this code to a convenient location you like (usually it&#8217;s ~/Library/Scripts).</p>
<pre>
if not appIsRunning("DVD Player") and not appIsRunning("MakeMKV") then
	with timeout of 3600 seconds
		display dialog "Bitte wählen Sie gewünschte Aktion:" with title "Aktion für DVD" buttons {"Cancel", "DVD abspielen", "DVD rippen"} cancel button "Cancel" giving up after (5)
	end timeout
	if button returned of result is "DVD rippen" then
		display dialog "Starte MakeMKV" buttons {"OK"} giving up after 2
		tell application "MakeMKV" to activate
	else if button returned of result is "Cancel" then
		quit
	else
		display dialog "Starte DVD-Player" buttons {"OK"} giving up after 2
		tell application "DVD Player" to activate
	end if
end if

on appIsRunning(appName)
	tell application "System Events" to (name of processes) contains appName
end appIsRunning
</pre>
<p>Then go to system properties and select CDs &amp; DVDs properties. Beneath &#8220;When you a insert a Video-DVD&#8221; choose &#8220;Run Script&#8221; and locate the script file you created before.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/dvdaction1.jpg" rel="lightbox[837]"><img src="http://phaq.phunsites.net/files/2011/12/dvdaction1-300x119.jpg" alt="" width="300" height="119" class="aligncenter size-medium wp-image-838" /></a></p>
<p>From now on, you&#8217;ll be presented with a selection prompt. Doing nothing will automatically start the DVD Player, or the DVD Ripper, if you choose to do so.<br />
Quiet cool, isn&#8217;t it? <img src='http://phaq.phunsites.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p><a href="http://phaq.phunsites.net/files/2011/12/dvdaction2.png" rel="lightbox[837]"><img src="http://phaq.phunsites.net/files/2011/12/dvdaction2-300x96.png" alt="" width="300" height="96" class="aligncenter size-medium wp-image-839" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2011/12/11/make-os-x-run-custom-actions-upon-dvd-insert/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shutting Speakers on OS X when Screen Saver runs</title>
		<link>http://phaq.phunsites.net/2011/12/02/shutting-speakers-on-os-x-when-screen-saver-runs/</link>
		<comments>http://phaq.phunsites.net/2011/12/02/shutting-speakers-on-os-x-when-screen-saver-runs/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 14:32:32 +0000</pubDate>
		<dc:creator>gdelmatto</dc:creator>
				<category><![CDATA[OS X]]></category>
		<category><![CDATA[Scripting]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=780</guid>
		<description><![CDATA[Why for God&#8217;s sake would anyone even think about shutting speakers while the screen saver runs? Don&#8217;t these thingies provide an internal mute switch to stay quiet? Well, yes, most of the time, they do. Though in my case, I run that nice and decent System47 LCARS-style screen saver. And while it provides indeed a [...]]]></description>
			<content:encoded><![CDATA[<p>Why for God&#8217;s sake would anyone even think about shutting speakers while the screen saver runs?<br />
Don&#8217;t these thingies provide an internal mute switch to stay quiet?</p>
<p>Well, yes, most of the time, they do. Though in my case, I run that nice and decent <a href="http://www.mewho.com/system47/" target="_blank">System47</a> LCARS-style screen saver. And while it provides indeed a mute switch, it yet refuses to honor that flag and will always revert to non-muted operations. This drives me crazy, at least during the night time.</p>
<p>So here&#8217;s my solution to shut it quiet &#8212; really handy when I&#8217;m not along and forgot to turn volume down &#8230;<br />
<span id="more-780"></span><br />
The key to it lies with a small Automator script, which I hacked up and which you can <a href='http://phaq.phunsites.net/files/2011/12/Shut-Speakers-on-Screen-Saver.zip'>download here</a>.</p>
<p>It basically consists of an endless loop, which will sleep some time, wake up, check if the screen saver is running and mute the speakers if that&#8217;s the case.<br />
It will also unmute the speakers if the screen saver is not running, e.g. when you return to the work place.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/preview.png" rel="lightbox[780]"><img src="http://phaq.phunsites.net/files/2011/12/preview-300x114.png" alt="" width="300" height="114" class="aligncenter size-medium wp-image-783" /></a></p>
<p>So first download the file and extract it to your desktop.<br />
Then double click the file to import it to Automator.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/step1.png" rel="lightbox[780]"><img src="http://phaq.phunsites.net/files/2011/12/step1-300x125.png" alt="" width="300" height="125" class="aligncenter size-medium wp-image-785" /></a></p>
<p><a href="http://phaq.phunsites.net/files/2011/12/step2.png" rel="lightbox[780]"><img src="http://phaq.phunsites.net/files/2011/12/step2-300x90.png" alt="" width="300" height="90" class="aligncenter size-medium wp-image-786" /></a></p>
<p>You&#8217;ll end up with the script being added to your &#8220;Services&#8221; menu.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/step3.png" rel="lightbox[780]"><img src="http://phaq.phunsites.net/files/2011/12/step3-300x125.png" alt="" width="300" height="125" class="aligncenter size-medium wp-image-787" /></a></p>
<p>Now open up your control panel and go the the <strong>Users &amp; Groups</strong> preferences. Select your account and navigate to <strong>Startup Items</strong>.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/step4.png" rel="lightbox[780]"><img src="http://phaq.phunsites.net/files/2011/12/step4-300x226.png" alt="" width="300" height="226" class="aligncenter size-medium wp-image-788" /></a></p>
<p>Click the + icon to add a new startup item. Use Finder to navigate to the Library folder below your home directory and then locate the <strong>Shutting Speakers on Screen Saver</strong> automator script beneth the Services folder.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/step5.png" rel="lightbox[780]"><img src="http://phaq.phunsites.net/files/2011/12/step5-300x156.png" alt="" width="300" height="156" class="aligncenter size-medium wp-image-789" /></a></p>
<p>Note for OS X Lion Users: You may not see the Library folder in the first place due to restrictive defaults on Lion. If that&#8217;s the case, open a Terminal and type this command in there:</p>
<p><code><br />
chflags nohidden ~/Library<br />
</code></p>
<p>This will enable the Library folder to be seen within Finder.</p>
<p>Now select the <strong>Shutting Speakers on Screen Saver</strong>. It will be added to your startup item preferences.</p>
<p><a href="http://phaq.phunsites.net/files/2011/12/step6.png" rel="lightbox[780]"><img src="http://phaq.phunsites.net/files/2011/12/step6-300x226.png" alt="" width="300" height="226" class="aligncenter size-medium wp-image-790" /></a></p>
<p>The script will now run everytime after logon, so you won&#8217;t need to care about having the system muted or not.<br />
If you want to run it now without logoff/logon, just go to Finder menu and click on <strong>Shutting Speakers on Screen Saver</strong> on the Services submenu.</p>
<p>Enjoy the silence <img src='http://phaq.phunsites.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2011/12/02/shutting-speakers-on-os-x-when-screen-saver-runs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sleep Timeout on TCL (and Cisco too&#8230;)</title>
		<link>http://phaq.phunsites.net/2011/11/09/sleep-timeout-on-tcl-and-cisco-too/</link>
		<comments>http://phaq.phunsites.net/2011/11/09/sleep-timeout-on-tcl-and-cisco-too/#comments</comments>
		<pubDate>Tue, 08 Nov 2011 23:43:38 +0000</pubDate>
		<dc:creator>gdelmatto</dc:creator>
				<category><![CDATA[Cisco]]></category>
		<category><![CDATA[TCL]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=775</guid>
		<description><![CDATA[Being used to other languages sometime leads to false assumptions, like having the same commands every now and then. While doing some TCL scripting on a Cisco I just had the need for a &#8216;sleep&#8217; command or equivalent. Since no &#8216;sleep&#8217; exists, the &#8216;after&#8217; command will do. Just supply it with the timeout in milliseconds, [...]]]></description>
			<content:encoded><![CDATA[<p>Being used to other languages sometime leads to false assumptions, like having the same commands every now and then.<br />
While doing some TCL scripting on a Cisco I just had the need for a &#8216;sleep&#8217; command or equivalent.</p>
<p>Since no &#8216;sleep&#8217; exists, the &#8216;after&#8217; command will do. Just supply it with the timeout in milliseconds, like this for a 10-second timeout:</p>
<p><code>after 10000</code></p>
<p>Or, with a bit more overhead, but some may think it&#8217;s more readable:</p>
<p><code>after [expr {int(10 * 1000)}]</code></p>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2011/11/09/sleep-timeout-on-tcl-and-cisco-too/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extract and Unify Cisco Device-Types with SNMP and Perl</title>
		<link>http://phaq.phunsites.net/2011/11/02/extract-and-unify-cisco-device-types-with-snmp-and-perl/</link>
		<comments>http://phaq.phunsites.net/2011/11/02/extract-and-unify-cisco-device-types-with-snmp-and-perl/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 16:43:07 +0000</pubDate>
		<dc:creator>gdelmatto</dc:creator>
				<category><![CDATA[Cisco]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://phaq.phunsites.net/?p=772</guid>
		<description><![CDATA[Here&#8217;s a short script which I use to extract Cisco device-types from SNMP. Bad enough, most of these devices return their device type ID differently, e.g. sometimes prefixed with an uppercase &#8216;C&#8217;, sometimes without any prefix, then again sometimes we find a suffix. So here&#8217;s a snippet, that makes them look neat, so I can [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a short script which I use to extract Cisco device-types from SNMP.<br />
Bad enough, most of these devices return their device type ID differently, e.g. sometimes prefixed with an uppercase &#8216;C&#8217;, sometimes without any prefix, then again sometimes we find a suffix.</p>
<p>So here&#8217;s a snippet, that makes them look neat, so I can work with simple and unified looking device IDs.<br />
<span id="more-772"></span><br />
Just make sure to fill in your hostnames and the SNMP community.</p>
<pre>
#!/usr/local/bin/perl -w

foreach $_SITE ('hostname1', 'hostname2', 'hostname3', 'hostname4') {

        my $_cpe_snmp_router_type = `/usr/local/bin/snmpget -v2c -c SNMP_COMMUNITY_NAME $_SITE .1.3.6.1.4.1.9.3.6.11.1.3.1`;

        print "debug: $_snmp_router_type \n";

        if ( $_snmp_router_type =~ /.*=\sSTRING:\s\"[cC]?(\d+[a-zA-Z0-9]+?)(?:\s.*)?\"/ ) {
                print "router type: $1 \n";
        } else {
                print "error: failed on extracting device ID!\n";
        }
}
</pre>
<p>And here&#8217;s what we get as output from this script:</p>
<pre>
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "886"

router type: 886
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "887VDSL2"

router type: 887VDSL2
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "c2851 Motherboard with 2GE and integrated VPN"

router type: 2851
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "C836"

router type: 836
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "887VDSL2"

router type: 887VDSL2
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "C836"

router type: 836
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "877"

router type: 877
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "871"

router type: 871
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "1803"

router type: 1803
debug: SNMPv2-SMI::enterprises.9.3.6.11.1.3.1 = STRING: "876"

router type: 876
</pre>
]]></content:encoded>
			<wfw:commentRss>http://phaq.phunsites.net/2011/11/02/extract-and-unify-cisco-device-types-with-snmp-and-perl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

