<?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>actionshrimp.com</title>
	<atom:link href="http://www.actionshrimp.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.actionshrimp.com</link>
	<description>fun and geekery</description>
	<lastBuildDate>Thu, 12 May 2011 20:12:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Speech Bubble Popups containing a View for Android MapView</title>
		<link>http://www.actionshrimp.com/2011/05/speech-bubble-popups-containing-a-view-for-android-mapview/</link>
		<comments>http://www.actionshrimp.com/2011/05/speech-bubble-popups-containing-a-view-for-android-mapview/#comments</comments>
		<pubDate>Thu, 12 May 2011 19:41:22 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[balloon]]></category>
		<category><![CDATA[bubble]]></category>
		<category><![CDATA[Dialog]]></category>
		<category><![CDATA[LayoutParams]]></category>
		<category><![CDATA[MapView]]></category>
		<category><![CDATA[Overlay]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=361</guid>
		<description><![CDATA[I&#8217;ve recently been playing around with Android, and have been building a small app that uses MapView to display various locations on the map. I succeeded in drawing markers on the MapView using ItemizedOverlay, but was having a fair bit of difficulty drawing little bubble popups that appeared when you tapped on the OverlayItems (which [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2011/05/bubble-screen-cropped.png"><img class="alignleft size-medium wp-image-362" title="bubble-screen-cropped" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2011/05/bubble-screen-cropped-293x300.png" alt="" width="293" height="300" /></a> I&#8217;ve recently been playing around with Android, and have been building a small app that uses MapView to display various locations on the map.</p>
<p>I succeeded in drawing markers on the MapView using <a href="http://code.google.com/android/add-ons/google-apis/reference/com/google/android/maps/ItemizedOverlay.html">ItemizedOverlay</a>, but was having a fair bit of difficulty drawing little bubble popups that appeared when you tapped on the OverlayItems (which unfortunately isn&#8217;t available in the API as a &#8216;standard&#8217; feature). My main problem was I wanted to be able to draw a full View on top of the map at the right location. I had a good old search on Google for a while, and couldn&#8217;t seem to find any easy way to do this, so I thought I&#8217;d write up how I ended up with the bubble in the screenshot. (Now I know how it&#8217;s done however, the Google results seem a lot more knowledgeable on the subject &#8211; I was probably searching for the wrong things <img src='http://www.actionshrimp.com/wordpress/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />  )</p>
<p>My first approach was to build a subclass of Overlay and override its draw() method, where I  converted the View to a Drawable to draw it directly onto the MapView canvas (passed to draw() ). This worked, but naturally events would no longer work properly in the View if it contained things like buttons, so it was back to the drawing board.</p>
<p>Next, I tried subclassing <a href="http://developer.android.com/reference/android/app/Dialog.html">Dialog</a>, and used a custom Dialog theme with my bubble background. The View I wanted was just injected into the Dialog through its <a href="http://developer.android.com/reference/android/app/Dialog.html#setContentView(int)">setContentView</a> method. This worked again, but I found myself fighting with the Dialog class a fair bit, and positioning it turned out to be a bit fiddly &#8211; there had to be a better way.</p>
<p>Finally I discovered that MapView inherits from the Android <a href="http://developer.android.com/reference/android/view/ViewGroup.html">ViewGroup</a>, which means it can contain other Views. After a bit more probing, and a peek at the implementation of <a href="https://github.com/jgilfelt/android-mapviewballoons">android-mapviewballoons</a> (which is excellent, but didn&#8217;t quite fit my purposes due to lack of custom balloon layouts) found a way to do it which should probably have been obvious from the outset! The general approach is to add a new child View to the MapView, and then use the <a href="http://code.google.com/android/add-ons/google-apis/reference/com/google/android/maps/MapView.LayoutParams.html">MapView.LayoutParams</a> to position it.</p>
<p>Here&#8217;s a quick outline example if you&#8217;re unfamiliar (the View I&#8217;m displaying has a <a href="http://developer.android.com/reference/android/graphics/NinePatch.html">NinePatch</a> as the background attribute of a top level LinearLayout, which makes the bubble wrap the content):</p>
<p>This is in the initial activity setup &#8211; my balloon is re-used for all OverlayItems drawn on my map:</p>
<pre>//Reference to our MapView
MapView mapView = (MapView) activity.findViewById(R.id.mapview);

//Get a LayoutInflater and load up the view we want to display.
//The false in inflater.inflate prevents the bubble View being added to the MapView straight away
LayoutInflater inflater = activity.getLayoutInflater();
LinearLayout bubble = (LinearLayout) inflater.inflate(R.layout.bubble, mapView, false);

//Set up the bubble's close button
ImageButton bubbleClose = (ImageButton) bubble.findViewById(R.id.bubbleclose);
bubbleClose.setOnClickListener(new View.OnClickListener() {
	public void onClick(View v) {
		Animation fadeOut = AnimationUtils.loadAnimation(ResultsMapResultsDisplayer.this.activity, R.anim.fadeout);
		bubble.startAnimation(fadeOut);
		bubble.setVisibility(View.GONE);
	}
});</pre>
<p>This next part is the important bit, and actually positions the bubble on the MapView using MapView.LayoutParams. It&#8217;s called by the onTap method of the ItemizedOverlay that contains my map markers:</p>
<pre>private void displaySearchResultBubble(final SearchResult result) {
	//Hide the bubble if it's already showing for another result
	map.removeView(bubble);
	bubble.setVisibility(View.GONE);

	//Set some view content
	TextView venueName = (TextView) bubble.findViewById(R.id.venuename);
	venueName.setText(result.getName());

	//This is the important bit - set up a LayoutParams object for positioning of the bubble.
	//This will keep the bubble floating over the GeoPoint result.getPoint() as you move the MapView around,
	//but you can also keep the view in the same place on the map using a different LayoutParams constructor
	MapView.LayoutParams params = new MapView.LayoutParams(
		LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
 		result.getPoint(), MapView.LayoutParams.BOTTOM_CENTER);

	bubble.setLayoutParams(params);

	map.addView(bubble);
	//Measure the bubble so it can be placed on the map
	map.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

	//Runnable to fade the bubble in when we've finished animatingTo our OverlayItem (below)
	Runnable r = new Runnable() {
		public void run() {
			Animation fadeIn = AnimationUtils.loadAnimation(activity, R.anim.fadein);
			bubble.setVisibility(View.VISIBLE);
			bubble.startAnimation(fadeIn);
		}
	};

	//This projection and offset finds us a new GeoPoint slightly below the actual OverlayItem,
	//which means the bubble will end up being centered nicely when we tap on an Item.
	Projection projection = map.getProjection();
	Point p = new Point();

	projection.toPixels(result.getPoint(), p);
	p.offset(0, -(bubble.getMeasuredHeight() / 2));
	GeoPoint target = projection.fromPixels(p.x, p.y);

	//Move the MapView to our point, and then call the Runnable that fades in the bubble.
	mapController.animateTo(target, r);
 }</pre>
<p>That&#8217;s it! It&#8217;s a fairly quick example but feel free to let me know in the comments if you want any more detail.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2011/05/speech-bubble-popups-containing-a-view-for-android-mapview/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Vim XPath Plugin</title>
		<link>http://www.actionshrimp.com/2011/04/vim-xpath-plugin/</link>
		<comments>http://www.actionshrimp.com/2011/04/vim-xpath-plugin/#comments</comments>
		<pubDate>Sat, 02 Apr 2011 23:55:01 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Vim]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[vim]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[xpath]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=324</guid>
		<description><![CDATA[I&#8217;ve built a plugin that adds XPath search functionality to Vim. Check out the demo video below. Features: Quick XPath search input with smart, context-sensitive tab completion Results shown in a pop-up results window. Jump to the line of a matching result easily. Debug invalid XML &#8211; jump to the the line number of an [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve built a plugin that adds XPath search functionality to Vim. Check out the demo video below.</p>
<p style="text-align: center;"><iframe src='http://player.vimeo.com/video/21857707?title=0&amp;byline=0&amp;portrait=0' width='450' height='388' frameborder='0'></iframe></p>
<p>Features:</p>
<ul>
<li>Quick XPath search input with smart, context-sensitive tab completion</li>
<li>Results shown in a pop-up results window. Jump to the line of a matching result easily.</li>
<li>Debug invalid XML &#8211; jump to the the line number of an XML error from the results window</li>
</ul>
<p>Requirements:</p>
<ul>
<li>Python support enabled in Vim</li>
<li>lxml library installed for Python (ideally 2.7 or higher).</li>
</ul>
<p>For more info, and to grab the plugin by downloading the vimball, visit my github:</p>
<p><a href="https://github.com/actionshrimp/vim-xpath">https://github.com/actionshrimp/vim-xpath</a></p>
<p>Let me know what you think / any improvement suggestions in the comments below.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2011/04/vim-xpath-plugin/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Streaming Spotify to a PS3 from Ubuntu</title>
		<link>http://www.actionshrimp.com/2010/08/streaming-spotify-to-a-ps3-from-ubuntu/</link>
		<comments>http://www.actionshrimp.com/2010/08/streaming-spotify-to-a-ps3-from-ubuntu/#comments</comments>
		<pubDate>Sun, 15 Aug 2010 17:50:48 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Music]]></category>
		<category><![CDATA[icecast]]></category>
		<category><![CDATA[ps3mediaserver]]></category>
		<category><![CDATA[radio]]></category>
		<category><![CDATA[spotify]]></category>
		<category><![CDATA[stream]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=302</guid>
		<description><![CDATA[A post came up a couple of days ago on the Spotify &#8220;What&#8217;s new&#8221; feed: how to stream spotify wirelessly to your stereo, which got me thinking about something I&#8217;ve been after for a while &#8211; the ability to stream spotify audio to PS3. This is mentioned in the link, but the main method they [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" title="Spotify" src="http://www.spotify.com/wp-content/themes/spotify/images/header/logo.png" alt="" width="76" height="76" /> A post came up a couple of days ago on the Spotify &#8220;What&#8217;s new&#8221; feed: <a href="http://www.simpleeditions.com/8001/how-to-stream-spotify-wirelessly-to-your-stereo">how to stream spotify wirelessly to your stereo</a>, which got me thinking about something I&#8217;ve been after for a while &#8211; the ability to stream spotify audio to PS3. This is mentioned in the link, but the main method they talk about is for Windows, and a solution for mac is touched upon. I figured I&#8217;d have a go at doing this on Ubuntu.</p>
<p>Before you have a go at this, I should mention a slight drawback &#8211; there&#8217;s a fair delay on the audio steam that reaches the PS3, around 20 or 30 seconds. This makes it good for playing a playlist as background music, but if you&#8217;re wanting to be able to flick around loads of different songs then you might get a bit frustrated. Read on if you&#8217;re still keen&#8230;</p>
<p><span id="more-302"></span></p>
<p>The general approach we&#8217;re going for is to convert the computer that&#8217;s playing spotify&#8217;s audio feed into a web radio station, which can then be played through a UPnP server that can be read by the ps3. Sounds a bit long winded? Well it is really! I&#8217;m sure there are better ways &#8211; I tried to pipe the spotify feed to a file and then play the file through the UPnP server instead, but this didn&#8217;t work with the way the PS3 buffers. Let me know if you find a better way though. Here&#8217;s how I did it anyway:</p>
<h2>1. Install ps3mediaserver</h2>
<p>You may have come across <a href="http://http://ps3mediaserver.blogspot.com/">ps3mediaserver</a> before if you&#8217;re a PS3 owner &#8211; it&#8217;s a great UPnP server that requires little setup. Head over to the <a href="http://code.google.com/p/ps3mediaserver/downloads/list">downloads page</a>. I grabbed pms-generic-linux-unix-1.20.409-BETA.tgz, although I&#8217;m pretty sure this will work fine with the stable version too. Extract the archive somewhere and fire up ps3mediaserver to try it out. With any luck it should locate your ps3. Add a share with some mp3s/videos in, restart it and give them a spin to check it all works. Try and make sure this is all working fine before carrying on, otherwise the later steps are unlikely to work.</p>
<h2>2. Grab pmsencoder</h2>
<p>The next thing we need is a plugin for ps3mediaserver called <a href="http://github.com/chocolateboy/pmsencoder">pmsencoder</a>. This is pretty handy in itself &#8211; it allows you to stream podcasts from a feed URL, shoutcast radio stations and various web video streams. Head over to the pmsencoder page, and look in the installation instructions on how to install the plugin. You pretty much just need to download the plugin .jar file to your ps3mediaserver /plugins folder, and then add the pmsencoder engine to the engines line in the PMS.conf configuration file (if the PMS.conf configuration doesn&#8217;t exist, open up ps3media server, fiddle with some settings (like adding a share or changing transcoding options, then hit &#8216;save&#8217;. This will create the file). When that&#8217;s all done, restart ps3mediaserver and have a look on your PS3 again. With any luck, there should be a folder called &#8216;Web&#8217;, with some default web sources available to have a look at (Endgadget Podcast, various Youtube feeds). Again, try these out and see if they work, as if they don&#8217;t then you&#8217;ll probably want to get this working before proceeding. In particular, make sure the &#8216;Radio&#8217; sources are working, as we&#8217;re gonna be pushing our Spotify feed through as a radio station.</p>
<h2>3. Grab icecast2</h2>
<p>Once ps3mediaserver and pmsencoder are working, we need to set up an icecast server to broadcast our soon-to-be-made stream to pmsencoder. If you&#8217;re on ubuntu, you can just do:</p>
<p><code>sudo apt-get install icecast2</code></p>
<p>to grab the icecast2 server. Once this is done, edit /etc/icecast2/icecast.xml and change the source and admin password to prevent random hijacking of your radio station. When the passwords have been changed, you&#8217;ll want to edit /etc/default/icecast2 and change the line at the bottom ENABLE=false to ENABLE=true. Now you can launch the icecast server:</p>
<p><code>sudo /etc/init.d/icecast2 start</code></p>
<p>Try and visit http://localhost:8000/ and see if anything displays. If all has gone well, you should get the icecast2 status page.</p>
<h2>4. Add a spotify radio source to pmsencoder</h2>
<p>Now our icecast server is running, we need to let pmsencoder and ps3mediaserver know about it. Open up the file WEB.conf in the directory where you&#8217;ve been running ps3mediaserver from. Under the #shoutcasts section, add a new source:</p>
<p><code>audiostream.Web,Radios=Spotify,http://localhost:8000/spotify.ogg</code></p>
<p>then restart ps3mediaserver.</p>
<h2>5. Send the computer&#8217;s audio to icecast2</h2>
<p>Next, we grab the computer&#8217;s audio and use gstreamer to send it to icecast2.  Type the following:</p>
<p><code>pacmd list-sources | less</code></p>
<p>This will list pulseaudio sources. You should get a bunch of output back, but it should hopefully only list one device. You&#8217;re looking for the beginning part like this:</p>
<p><code> </code></p>
<p><code>...</code></p>
<p><code></p>
<div id="_mcePaste">index: 0</div>
<div id="_mcePaste">name: &lt;alsa_output.pci-0000_00_08.0.analog-stereo.monitor&gt;</div>
<div id="_mcePaste">driver: &lt;module-alsa-card.c&gt;</div>
<div id="_mcePaste">flags: DECIBEL_VOLUME LATENCY DYNAMIC_LATENCY</div>
<div id="_mcePaste">state: IDLE</div>
<p></code></p>
<p>&#8230;</p>
<p>&#8230;</p>
<p>in particular the name, which in my case is alsa_output.pci-0000_00_08.0.analog-stereo.monitor. Make a note of yours.</p>
<p>Next we just run a command to convert this pulse source into an ogg file, which is then sent to the icecast2 server. Run the following, replacing the device with your own, and the password at the end with the icecast2 source password you set earlier:</p>
<p><code>gst-launch-0.10 pulsesrc device=alsa_output.pci-0000_00_08.0.analog-stereo.monitor ! audioconvert ! vorbisenc ! oggmux ! shout2send ip=localhost port=8000 password=hackme mount=spotify.ogg</code></p>
<p>Now all sound that comes through your computer&#8217;s speakers is being sent to your icecast2 server. All that remains is to fire up Spotify. Start playing a track, and then on your ps3 navigate to the Web folder &gt; Radio &gt; Spotify. With any luck, after 20 or 30 seconds you should hear the track starting on your ps3 as well!</p>
<p>Let me know if you have any problems with the last few steps, although any problems with ps3mediaserver or pmsencoder are probably best tackled through the ps3mediaserver forums as I&#8217;m no expert on these two. Hopefully someone out there will have found this useful &#8211; again, let me know if you do <img src='http://www.actionshrimp.com/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2010/08/streaming-spotify-to-a-ps3-from-ubuntu/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>CakePHP: PagesController with Admin Routing</title>
		<link>http://www.actionshrimp.com/2009/04/cakephp-pagescontroller-with-admin-routing/</link>
		<comments>http://www.actionshrimp.com/2009/04/cakephp-pagescontroller-with-admin-routing/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 17:46:14 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[admin]]></category>
		<category><![CDATA[cake]]></category>
		<category><![CDATA[pagescontroller]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=272</guid>
		<description><![CDATA[For small Cake websites with admin routing enabled, I like to use the Auth component to require a login for all admin routes, and allow access to everything else using the following beforeFilter in the AppController superclass: function beforeFilter(){ $admin = Configure::read(&#039;Routing.admin&#039;); if (isset($this-&#62;params[$admin]) and $this-&#62;params[$admin]){ $this-&#62;layout = &#039;admin&#039;; } else { $this-&#62;Auth-&#62;allow(); } } [...]]]></description>
			<content:encoded><![CDATA[<p>For small Cake websites with admin routing enabled, I like to use the Auth component to require a login for all admin routes, and allow access to everything else using the following beforeFilter in the AppController superclass:</p>
<pre class="brush: php">

function beforeFilter(){
    $admin = Configure::read(&#039;Routing.admin&#039;);
    if (isset($this-&gt;params[$admin]) and $this-&gt;params[$admin]){
        $this-&gt;layout = &#039;admin&#039;;
    }
    else {
        $this-&gt;Auth-&gt;allow();
    }
}
</pre>
<p>The problem with this however is static pages handled by the pages controller cannot be password protected. To resolve this problem, I had to overload the PagesController class that Cake comes with, and add in the required functionality. Part of the reason for doing this for me was to allow a setup where there was a password protected admin welcome page or control panel located at my_app_URL/admin, so I&#8217;ll show you the necessary routing to achieve that too.</p>
<p><span id="more-272"></span></p>
<h3>Adding a route and overloading PagesController</h3>
<p>First of all, copy your_app_dir/cake/libs/controller/pages_controller.php into your_app_dir/app/controllers with the rest of your application&#8217;s controllers. Then fire up an editor and take a look at your newly copied version.  You&#8217;ll see there is a function called display, this is what the pages controller uses to display pages. There is a route in app/config/routes.php that maps /pages/* to /pages/display/* to make the URL easier on the eyes, so if we&#8217;re gonna have /admin/pages/* working properly, we&#8217;ll need a similar route. Open up app/config/routes.php, and underneath the line</p>
<pre class="brush: php">

Router::connect(&#039;/pages/*&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;));
</pre>
<p>add in the following route:</p>
<pre class="brush: php">

Router::connect(&#039;/admin/pages/*&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true));
</pre>
<p>Now, when admin routing is enabled, Cake looks for controller actions appened with &#8220;admin_&#8221;, so we&#8217;d better add in the function to handle this in PagesController. Open it up, and underneath the display function, add the following:</p>
<pre class="brush: php">

function admin_display() {
    $path = func_get_args();
    $temp = null;

    $count = count($path);

    if ($path[0] != &#039;admin&#039;) {
        //This adds admin to the beginning of the path so the pages controller will look in the &#039;admin&#039; folder in pages directory
        $path = array_merge((array)&#039;admin&#039;, $path);
    } else {
        //This removes admin from the beginning if it&#039;s there already, and sends the request round again so we end up with URLs that look like app/admin/pages/x
        //when app/admin/pages/admin/x is requested somehow.
        $path = array_slice($path, 1);
        $this-&gt;redirect(array_merge(array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true), $path));
    }

    if (!$count) {
        $this-&gt;redirect(&#039;/&#039;);
    }
    $page = $subpage = $title = null;

    if (!empty($path[0])) {
        $page = $path[0];
    }
    if (!empty($path[1])) {
        $subpage = $path[1];
    }
    if (!empty($path[$count - 1])) {
        $title = Inflector::humanize($path[$count - 1]);
    }
    $this-&gt;set(compact(&#039;page&#039;, &#039;subpage&#039;, &#039;title&#039;));
    $this-&gt;render(join(&#039;/&#039;, $path));
}
</pre>
<p>As you can see it&#8217;s fairly similar to the display function, with a few extra lines added in that handle admin pages. There are a few subtleties here which I will explain in a second. Before that however, we also require a slight change to the existing, non-admin display function. Look for the if statement below:</p>
<pre class="brush: php">

if (!empty($path[0])) {
    $page = $path[0];
}
</pre>
<p>and change it to:</p>
<pre class="brush: php">

if (!empty($path[0])) {
    $page = $path[0];
    if ($page == &#039;admin&#039;) {
        //Sends admin page requests to their proper place to stop sneaky access attempts
        $this-&gt;redirect(array_merge(array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true), $path));
    }
}
</pre>
<p>Ok so what have we done?</p>
<ol>
<li>The added nested if statement in the display() function redirects requests for /pages/admin/x to their proper place, /admin/pages/x.</li>
<li>The &#8216;else&#8217; clause of the if ($path[0] == &#8216;admin&#8217;) in admin_display redirects requests for /admin/pages/admin/x to /admin/pages/x, which just tidies up a URL aesthetics issue.</li>
<li>Finally, the first part of the same if statement is what handles the /admin/pages/x requests proper &#8211; it adds the &#8216;admin&#8217; part back to the beginning of the $path variable that point 2 removes. This is actually just exploiting a subtlety of the pages controller, &#8216;subpages&#8217; (this seems to be quite hard to find in the documentation actually) &#8211; requests sent to /pages/a/b will display a page b stored in the folder your_app_dir/app/views/pages/a, rather than a page b stored in the pages root. Adding this additional logic helps organisation a bit by storing all admin pages in you_app_dir/app/views/pages/admin/.</li>
</ol>
<p>So now this is all in place, everything should work correctly. Requests to /pages/admin/x and /admin/pages/admin/x both get sent to /admin/pages/x, and these require proper authentication.</p>
<p>The final step is to add in a route that allows my original use for this whole setup to work properly &#8211; displaying an admin homepage or control panel that requires authentication when a user visits your_app_URL/admin, i.e. without referring to any controllers or actions. First, create a page in your_app_dir/app/views/pages/admin/, called home.ctp that contains the content you want. You can now access this from your_app_URL/admin/pages/home, but the shorter URL works after adding the route:</p>
<pre class="brush: php">

Router::connect(&#039;/admin&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;admin&#039; =&gt; true, &#039;home&#039;));
</pre>
<p>Hooray! We now have an admin homepage. Hope everything worked for you, hit me with a comment if you have an issues and I&#8217;ll try and help out.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/04/cakephp-pagescontroller-with-admin-routing/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>CakePHP Tutorial Part 2: Authentication and Tweaking</title>
		<link>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-2-authentication/</link>
		<comments>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-2-authentication/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 19:51:59 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[cake]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=178</guid>
		<description><![CDATA[In the first part of my CakePHP tutorial, I showed you how to use Cake&#8217;s Bake utility to set up the basic back end of an online illustration portfolio. In this part, I&#8217;ll tweak the automatically generated code into useable website and admin section and show you how to use some of Cake&#8217;s features along [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/cake-logo1.png"><img class="alignleft size-full wp-image-252" title="cake-logo1" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/cake-logo1.png" alt="cake-logo1" width="180" height="180" /></a>In the <a href="http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-1-bake-utility/">first part of my CakePHP tutorial</a>, I showed you how to use Cake&#8217;s Bake utility to set up the basic back end of an online illustration portfolio. In this part, I&#8217;ll tweak the automatically generated code into useable website and admin section and show you how to use some of Cake&#8217;s features along the way, including the Authentication component.<br />
<span id="more-178"></span></p>
<h3>Joining the sections together</h3>
<p>If you followed the first part of the tutorial, we currently have a few sections that we&#8217;ve generated models, controllers and views for. By navigating to your_app/controllername/action in your browser, you can access the different functions of the application. But unless your users know this in advance, they have no way of accessing them.</p>
<p>The easiest way of implementing navigation common to all pages is to use Cake&#8217;s built in templating system, the page &#8220;layout&#8221;. Cake uses its built-in layout if it finds no user defined layout default available. To add one, create the file your_app_dir/app/views/layouts/default.ctp, and put in your basic page layout. Mine looked like this:</p>
<pre class="brush: php">
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
&lt;title&gt;&lt;?php echo $title_for_layout ?&gt;&lt;/title&gt;
&lt;link href=&quot;favicon.ico&quot; type=&quot;image/x-icon&quot; rel=&quot;shortcut icon&quot; /&gt;
&lt;?php echo $html-&gt;css(&#039;default&#039;) ?&gt;
&lt;?php echo $scripts_for_layout ?&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id=&quot;container&quot;&gt;
&lt;div id=&quot;header&quot;&gt;
&lt;h1&gt;King-Jon Illustration&lt;/h1&gt;
&lt;/div&gt;
&lt;div id=&quot;navigation&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;?php echo $html-&gt;link(&#039;News&#039;, array(&#039;controller&#039;=&gt;&#039;News&#039;))?&gt;&lt;/li&gt;
&lt;li&gt;&lt;?php echo $html-&gt;link(&#039;Works&#039;, array(&#039;controller&#039;=&gt;&#039;Works&#039;))?&gt;&lt;/li&gt;
&lt;li&gt;&lt;?php echo $html-&gt;link(&#039;Sketches&#039;, array(&#039;controller&#039;=&gt;&#039;Sketches&#039;))?&gt;&lt;/li&gt;
&lt;li&gt;&lt;?php echo $html-&gt;link(&#039;Friends&#039;, array(&#039;controller&#039;=&gt;&#039;Friends&#039;))?&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;div id=&quot;content&quot;&gt;
&lt;?php echo $content_for_layout ?&gt;
&lt;/div&gt;
&lt;div id=&quot;footer&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>You&#8217;ll notice this looks like a pretty normal basic page skeleton, with a few extra bits of PHP inserted. The $title_for_layout, $scripts_for_layout and $content_for_layout variables are filled in by Cake automatically depending on what the current page request is and the title and content are fairly self-explanitory.  The scripts variable lets you specify scripts on a per-page basis but still include them in the &lt;head&gt; section.  The $html-&gt;xxx code snippets are part of the <a href="http://book.cakephp.org/view/206/Inserting-Well-Formatted-elements">Cake HtmlHelper</a>. This allows you to insert well formatted elements easily &#8211; the $html-&gt;css(&#8216;default&#8217;) includes the stylesheet &#8220;css/default.css&#8221; (this is stored in the your_app_dir/app/webroot/css directory), and the $html-&gt;link lines let you point to different parts of your app easily. You could just add normal links, such as &lt;a href=&#8221;/news/&#8221;&gt;, but pointing to the controller allows a bit of flexibility if you want to change anything further down the line.</p>
<h3>Adding a splash page</h3>
<p>As it was an art portfolio website, it was decided a splash page would be useful to have, to give a good first impact when entering the site and the ability to show off a bit of artwork right away. Cake uses its built-in pages controller to handle static pages, and the different pages are stored in the folder your_app_dir/app/views/pages. To view a page, you navigate to the URL your_app/pages/pagename. Here, the pages controller doesn&#8217;t take an action, so the additional directory level on the URL is an argument passed to the controller, in this case the name of the page to display.</p>
<p>Cake also automatically serves up a default page, called &#8220;home&#8221;, when a user requests the root of your_app. The name of this page is set by Cake&#8217;s router, and if we look in your_app_dir/app/config/routes.php, we see at the bottom, the lines:</p>
<pre class="brush: php">
/**
* Here, we are connecting &#039;/&#039; (base path) to controller called &#039;Pages&#039;,
* its action called &#039;display&#039;, and we pass a param to select the view file
* to use (in this case, /app/views/pages/home.ctp)...
*/
Router::connect(&#039;/&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;, &#039;home&#039;));
/**
* ...and connect the rest of &#039;Pages&#039; controller&#039;s urls.
*/
Router::connect(&#039;/pages/*&#039;, array(&#039;controller&#039; =&gt; &#039;pages&#039;, &#039;action&#039; =&gt; &#039;display&#039;));
</pre>
<p>The comments tell us what&#8217;s going on &#8211; this is what maps the pages to the locations I have talked about. You can add your own mappings here too if you like.  For our splash screen however, we can just make use of the already defined &#8220;home&#8221; page, so edit this to make it look how you want, you&#8217;ll find it in your_app_dir/app/views/pages/home.ctp. Mine looked like this:</p>
<pre class="brush: php">
&lt;?php $this-&gt;layout = &quot;splash&quot; ?&gt;
&lt;div id=&quot;splash&quot;&gt;
&lt;?php echo $html-&gt;image(&quot;splash.png&quot;,
array(&quot;alt&quot; =&gt; &quot;King Jon Illustration&quot;,
&quot;url&quot; =&gt; array(&quot;controller&quot; =&gt; &quot;news&quot;)));?&gt;
&lt;/div&gt;
</pre>
<p>A couple of things to note here. The first line $this-&gt;layout = &#8220;splash&#8221;, tells Cake not to use the &#8220;default&#8221; layout we created earlier, but to instead use one called &#8220;splash&#8221;.  I sneakily created a splash layout without telling you here, but it is in fact just an exact copy of the default layout with the navigation div removed, to give the page a more &#8220;splashy&#8221; feel.</p>
<p>Next, I used the image HtmlHelper to include an image called &#8220;splash.png&#8221; &#8211; this is located in my_app_dir/app/webroot/img, the location the image helper looks in. The second argument is an array of additional attributes, &#8220;alt&#8221; being the alt text, and &#8220;url&#8221; puts an &lt;a&gt; element around the image, creating a link to the specified address.</p>
<h3>Admin section authentication</h3>
<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/authentic-screen.png"><img class="alignleft size-medium wp-image-251" title="auth-screen" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/authentic-screen-300x187.png" alt="auth-screen" width="300" height="187" /></a>At the minute, all our sections are wide open for anyone to just stroll in and start adding news, posting works, and generally delete or edit existing pieces of data. This clearly isn&#8217;t ideal, so next on the agenda is sorting this out. We&#8217;ll use the <a href="http://book.cakephp.org/view/172/Authentication">Authentication component</a> for this.</p>
<p>First of all, we want all add/edit capabilities to be kept within the admin section, so the first step is to remove the non-admin versions of these. Go through all five of the your_app_dir/app/controllers/*_controller.php, and delete the functions &#8220;add&#8221; and &#8220;edit&#8221; that were automatically generated. Next, clean up the views associated with these functions &#8211; delete the two files your_app_dir/app/views/*/add.ctp and edit.ctp in all five of the view directories. This means now we can only add and edit our data by navigating to your_app/<strong>admin</strong>/controller/add etc.</p>
<p>We&#8217;re going to want to use authentication for all our controllers, as all of them have an admin section that we need to login for. Instead of telling each controller to use this component individually, we can tell the whole controller superclass that we want to use it, to save repetition. Open the file your_app_dir/app/app_controller.php and add the line in the class definition like so:</p>
<pre class="brush: php">

class AppController extends Controller {
var $components = array(&#039;Auth&#039;);
}
</pre>
<p>Now if you try and visit an admin page in your_app, you&#8217;ll be greeted with an error messages telling you there&#8217;s no login action in the Users controller, which is where the Auth component looks by default, so we&#8217;d better add this in. Edit the file your_app_dir/app/controllers/users_controller.php, and right at the bottom of the class definition, add these two functions:</p>
<pre class="brush: php">

function admin_login() {
}
function admin_logout() {
$this-&gt;Redirect($this-&gt;Auth-&gt;logout());
}
</pre>
<p>Now try and navigate to an admin section again. You&#8217;re told that there&#8217;s a missing view this time! Better do what Cake says and add one in. Create the new file your_app_dir/app/views/users/admin_login.ctp, and fill it with the following skeleton login form:</p>
<pre class="brush: php">

&lt;?php
if  ($session-&gt;check(&#039;Message.auth&#039;)) $session-&gt;flash(&#039;auth&#039;);
echo $form-&gt;create(&#039;User&#039;, array(&#039;action&#039; =&gt; &#039;admin_login&#039;));
echo $form-&gt;input(&#039;username&#039;);
echo $form-&gt;input(&#039;password&#039;);
echo $form-&gt;end(&#039;Login&#039;);
?&gt;
</pre>
<p>Now there are two problems: we&#8217;re greeted with a login for all the admin sections &#8211; a slight problem as we don&#8217;t have credentials&#8230; we&#8217;ve locked ourselves out of the whole website! There are also some error messages when we try and view the non-admin sections of the site, which seem to want us to login but can&#8217;t find a login() action (remember we only created admin_login, and didnt bother with login). Fortunately, we can get around these problems by adding exceptions to the authentication. Open up the users controller, your_app_dir/app/controllers/users_controller.php, and then add in the following <a href="http://book.cakephp.org/view/60/Callbacks">controller callback function</a> (I added it in near the top):</p>
<pre class="brush: php">

function beforeFilter() {
$this-&gt;Auth-&gt;allow(&#039;admin_add&#039;, &#039;admin_index&#039;);
}
</pre>
<p>This gives access to the admin add and index (which lists all users) actions of the users controller. So now, navigate to your_app/admin/users/add, and create a login for yourself! You&#8217;ll probably want to remove the allow line once you&#8217;ve added yourself to prevent anyone else creating a login for themselves when you&#8217;re not looking.</p>
<p>We&#8217;re still however stuck with the problem that none of the non-admin sections work, so we need to add an Auth exception to all non-admin sections. The best way to do this is by adding the following into the your_app_dir/app/app_controller.php AppController class definition, underneath where we told it to load the Auth component earlier:</p>
<pre class="brush: php">

function beforeFilter(){
$admin = Configure::read(&#039;Routing.admin&#039;);
if (isset($this-&gt;params[$admin]) and $this-&gt;params[$admin]){
//$this-&gt;layout = &#039;admin&#039;;
}
else {
$this-&gt;Auth-&gt;allow();
}
}
</pre>
<p>Now we should be able to navigate the site without any problems. The commented out line above allows the future addition of an admin.ctp layout file that will automatically be loaded when viewing admin sections &#8211; I haven&#8217;t done this yet though.</p>
<p>The next phase of the project is to go through and edit all the views, layouts &amp; CSS and get them looking how you want, and this is largely an exercise in usual web development &#8211; you can take a look at the default views to see how to include data provided by Cake  fairly easily. If I come across anything else I think might be of help while I&#8217;m building the rest of the site, I&#8217;ll make small posts for those too. Hopefully you&#8217;ve been able to follow this introduction to Cake so far, but if not drop me a line in the comments below and I&#8217;ll try and give you a hand where I can. Good luck!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-2-authentication/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>CakePHP Tutorial Part 1: Bake Utility</title>
		<link>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-1-bake-utility/</link>
		<comments>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-1-bake-utility/#comments</comments>
		<pubDate>Sat, 28 Mar 2009 17:42:35 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[bake]]></category>
		<category><![CDATA[cake]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[website]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=129</guid>
		<description><![CDATA[A friend of mine recently asked me to help him build an online portfolio for his illustration pieces, and I decided to use CakePHP 1.2 to get the back end up and running quickly. I thought someone might find a tutorial taking a simple website through from start to finish useful, so this tutorial series [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-130" title="cake-logo" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/cake-logo.png" alt="cake-logo" width="180" height="180" />A friend of mine recently asked me to help him build an online portfolio for his illustration pieces, and I decided to use <a href="http://cakephp.org/" target="_blank">CakePHP 1.2</a> to get the back end up and running quickly. I thought someone might find a tutorial taking a simple website through from start to finish useful, so this tutorial series will do just that. This part of the series takes you through the first few steps I took to get the basic code together.  You&#8217;ll need a web server and database server such as MySQL, and some basic PHP and webserver management knowledge. We&#8217;ll be using Cake&#8217;s &#8220;bake&#8221; utility to create the basic code as well, so you&#8217;ll need console access to your webserver, and PHP&#8217;s command line utility (in Ubuntu/PHP5 you can just install the package php5-cli).</p>
<p><span id="more-129"></span></p>
<h3>Downloading and setting up CakePHP</h3>
<p>Create a new directory on your webserver where your cake website will reside (or just use the web root if this is going to be the main webpage).  Next, we&#8217;ll need to actually download CakePHP.  If you have shell access to your webserver, you can use SVN to get the latest stable release automatically: navigate to the directory and use the command (note the &#8220;.&#8221; at the end of the command)</p>
<pre>$ svn checkout https://svn.cakephp.org/repo/trunk/cake/1.2.x.x/ .</pre>
<p>to do so.  If you don&#8217;t know what any of this means, just download the latest stable release from the CakePHP website and extract the files into the directory you created &#8211; make sure the various .htaccess files don&#8217;t go astray in the process.</p>
<p>Some standard setup is also required: we need to tell cake how to connect to our database server, to do this follow the steps on <a href="http://book.cakephp.org/view/331/Cake-Database-Configuration">this page</a>. There&#8217;s also a couple of optional (but recommended) configuration steps <a href="http://book.cakephp.org/view/332/Optional-Configuration">here</a>. After this, you should be able to browse to the directory in a web browser and see the default page &#8211; there shouldn&#8217;t be any errors or warnings if all configuration has been completed correctly (N.B. if the default page looks a bit plain &#8211; no colours, CSS styles etc., then you probably have a mod_rewrite issue, check out <a href="http://book.cakephp.org/view/333/A-Note-on-mod_rewrite">this page</a>).</p>
<p>Now we can begin work on the site.</p>
<h3>Bake a cake</h3>
<p>Cake&#8217;s bake utility is a handy way of generating the basic code structure for a web application, saving a lot of the tedious grunt work that often comes with setting up a new project. The general idea is often seen in frameworks that take advantage of the MVC (model-view-controller) programming pattern (such as Ruby on Rails, and others). It involves creating a database structure that describes the various data entites &#8211; or &#8220;models&#8221; &#8211; of our application, then running a script that reads this structure and generates the framework code for the models. It can then generate standard interfaces (or &#8220;views&#8221;) for displaying the data, and &#8220;controllers&#8221; which tie our interfaces and models together, allowing data to be input and manipulated. Of course, these standard pieces of generated code probably won&#8217;t be exactly what we want, but they can provide a great starting point to work from and then tweak.</p>
<p>First of all, we&#8217;ll create our database structure. I&#8217;m using an empty database for this project, although if you&#8217;re using a database with tables from other projects in, you can set Cake to work with a table prefix fairly easily. Let&#8217;s get to work building the tables.</p>
<p>The first model will be &#8220;News&#8221;, containing data for a news section where the owner can post updates and information onto the site.  To represent this, I created a table &#8220;news&#8221;, with four fields:</p>
<ul>
<li><strong>id</strong> &#8211; type: int &#8211; extra: auto_increment &#8211; primary key <em>(A unique identifier for each record)</em></li>
<li><strong>date</strong> &#8211; type: date</li>
<li><strong>title</strong> &#8211; type: text</li>
<li><strong>body</strong> &#8211; type: text</li>
</ul>
<p>The next model is for representing finished works placed onto the site &#8211; the main part of the portfolio. Create a table called &#8220;works&#8221; with the four fields:</p>
<ul>
<li><strong>id</strong> &#8211; type: int &#8211; extra: auto_increment &#8211; primary key</li>
<li><strong>date</strong> &#8211; type: date</li>
<li><strong>title</strong> &#8211; type: text</li>
<li><strong>desc</strong> &#8211; type: text</li>
</ul>
<p>Next up, a sketches model. This is pretty much the same as &#8220;works&#8221; but will contain sketches as opposed to finished pieces. Create a table called &#8220;sketches&#8221; with the same four fields as above.</p>
<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-1.png"><img class="alignright size-medium wp-image-153" title="database-screenshot" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-1-300x187.png" alt="database-screenshot" width="300" height="187" /></a>A friends model for a page that will contain links to websites belonging to friends of the owner, along with a thumbnail and description. Create the table &#8220;friends&#8221;, with the fields:</p>
<ul>
<li><strong>id</strong> &#8211; type: int &#8211; extra: auto_increment &#8211; primary key</li>
<li><strong>name</strong> &#8211; type: text</li>
<li><strong>url</strong> &#8211; type:  text</li>
<li><strong>desc</strong> &#8211; type:  text</li>
</ul>
<p>There is one last model we&#8217;ll need: &#8220;users&#8221;. By creating a table with a username/password, we can let the owner login to manage the site, add new works, sketches and friends. Multiple users will mean we can also have a login to test out the site. So create the &#8220;users&#8221; table, with fields:</p>
<ul>
<li><strong>id</strong> &#8211; type: int &#8211; extra: auto_increment &#8211; primary key</li>
<li><strong>username</strong> &#8211; type: varchar(20)</li>
<li><strong>password</strong> &#8211; type:  varchar(50)</li>
<li><strong>displayname</strong> &#8211; type:  varchar(20) (Name shown when making posts etc &#8211; can be different from login name)</li>
</ul>
<p>Now all our tables are created, we can get to baking. In a console, navigate to yourdir/cake/console, and then run the command</p>
<pre>$ ./cake bake</pre>
<p>and you&#8217;ll be presented with:</p>
<pre><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-2.png"><img class="alignright size-medium wp-image-154" title="console-screenshot" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-2-300x187.png" alt="console-screenshot" width="300" height="187" /></a>Welcome to CakePHP v1.2.2.8120 Console
---------------------------------------------------------------
App : app
Path: /home/dave/public_html/kingjon/app
---------------------------------------------------------------
Interactive Bake Shell
---------------------------------------------------------------
[D]atabase Configuration
[M]odel
[V]iew
[C]ontroller
[P]roject
[Q]uit
What would you like to Bake? (D/M/V/C/P/Q)
&gt;</pre>
<p>at this point, if you haven&#8217;t setup your database configuration yet, you can create it with the &#8220;[D]atabase Configuration&#8221; option. We&#8217;ll be choosing the &#8220;[M]odel&#8221; option however:</p>
<pre>&gt; m
---------------------------------------------------------------
Bake Model
Path: /home/dave/public_html/kingjon/app/models/
---------------------------------------------------------------
Possible Models based on your current database:
1. Friend
2. News
3. Sketch
4. User
5. Work
Enter a number from the list above, type in the name of another model, or 'q' to exit
[q] &gt;</pre>
<p>notice our database tables have been read, and cake has automatically figured out that an entry in &#8220;works&#8221; will be a &#8220;Work&#8221;,  &#8220;sketches&#8221; give a &#8220;Sketch&#8221; and so on, but &#8220;news&#8221; is still &#8220;News&#8221;.  We may as well start with the first entry, so enter 1, and hit enter. You&#8217;ll be asked the following:</p>
<pre>[q] &gt; 1
Would you like to supply validation criteria for the fields in your model? (y/n)
[y] &gt;</pre>
<p>Cake has a set of predefined validation criteria to make sure that data entered for a model is correct. We may as well take advantage of these, so hit &#8220;y&#8221; and press return.</p>
<p>Next Cake goes through each of the fields in our table, and asks what validation criteria we want for each. <strong>id</strong> is first, and I chose &#8220;blank&#8221; (number 3 in my case, athough I guess this number may change depending on which version of cake you&#8217;re using). This ensures that no data is entered for the id, which is what we want as the field is auto generated by mySQL&#8217;s auto_increment. For <strong>name</strong> I chose &#8220;Do not do any validation on this field&#8221; as the name can contain any text. For <strong>url</strong> I chose the rather fitting &#8220;url&#8221; (number 27) validation type. Finally, for <strong>desc</strong> I chose &#8220;Do not do any validation on this field&#8221; as well.</p>
<p>A final couple of questions now pop up: model associations &#8211; for this I just hit &#8220;n&#8221; as our model is simple and has no relational properties &#8211; and a confirmation to check your settings are ok:</p>
<pre>---------------------------------------------------------------
The following Model will be created:
---------------------------------------------------------------
Name:       Friend
Validation: Array
(
    [id] =&gt; blank
    [url] =&gt; url
)

Associations:
---------------------------------------------------------------
Look okay? (y/n)
[y] &gt;</pre>
<p>Confirm this and there&#8217;s a final question about SimpleTest and unit test files. This is to do with Cake&#8217;s testing framework which I personally haven&#8217;t tried, and as this is just a simple project I won&#8217;t other using it, so just hit &#8220;n&#8221; here.  Congratulations, you&#8217;ve successfully baked your first model!</p>
<p>Continue the process now, and bake the other models with appropriate validation criteria (I used &#8220;blank&#8221; for all the IDs, &#8220;date&#8221; for the date fields, and no validation for all the title/description fields &#8211; although for the users table, I chose &#8220;notEmpty&#8221; for the username, password and displayname fields as blank entries here would cause problems).</p>
<p>Next up, time to bake some controllers. I&#8217;ll show you the output from my run through first including the options I chose, and explain to you afterwards what some of them mean and why I chose them:</p>
<pre>What would you like to Bake? (D/M/V/C/P/Q)
&gt; c
---------------------------------------------------------------
Bake Controller
Path: /home/dave/public_html/kingjon/app/controllers/
---------------------------------------------------------------
Possible Controllers based on your current database:
1. Friends
2. News
3. Sketches
4. Users
5. Works
Enter a number from the list above, type in the name of another controller, or 'q' to exit
[q] &gt; 1
---------------------------------------------------------------
Baking FriendsController
---------------------------------------------------------------
Would you like to build your controller interactively? (y/n)
[y] &gt; y
Would you like to use scaffolding? (y/n)
[n] &gt; n
Would you like to include some basic class methods (index(), add(), view(), edit())? (y/n)
[n] &gt; y
Would you like to create the methods for admin routing? (y/n)
[n] &gt; y
Would you like this controller to use other helpers besides HtmlHelper and FormHelper? (y/n)
[n] &gt; n
Would you like this controller to use any components? (y/n)
[n] &gt; n
Would you like to use Sessions? (y/n)
[y] &gt; y
You need to enable Configure::write('Routing.admin','admin') in /app/config/core.php to use admin routing.
What would you like the admin route to be?
Example: www.example.com/admin/controller
What would you like the admin route to be?
[admin] &gt; 

---------------------------------------------------------------
The following controller will be created:
---------------------------------------------------------------
Controller Name:  Friends
---------------------------------------------------------------
Look okay? (y/n)
[y] &gt;

Creating file /home/dave/public_html/kingjon/app/controllers/friends_controller.php
Wrote /home/dave/public_html/kingjon/app/controllers/friends_controller.php
SimpleTest is not installed.  Do you want to bake unit test files anyway? (y/n)
[y] &gt; n</pre>
<p>Ok, I started by building the controller for the friends section again. Building interactively gives you access to more options in the setup, so I went for that. <a href="http://book.cakephp.org/view/105/Scaffolding">Scaffolding</a> is basically a flag you set in your controller telling cake that you want basic skeleton app behaviour to be created at runtime. By baking we are given the advantage of pre-generating code that does more or less the same thing, but that we can also edit later, so choosing &#8220;n&#8221; for scaffolding is a wise plan in our case. The next question about basic methods is where our pre-generated skeleton code comes from, so choose &#8220;y&#8221; here. Admin routing creates an admin section for adding/deleting/modifying records. As we don&#8217;t want visitors to the website to be able to do this, but the portfolio owner will be wanting to do this, an admin section is a good idea, so &#8220;y&#8221; to this question as well. We are now asked about <a href="http://book.cakephp.org/view/181/Core-Helpers">helpers</a>. Helpers are libraries built into cake that add functionality and generally make your life easier. At the minute we&#8217;ll just use the default two, so choose &#8220;n&#8221;, although more can be added later easily if we need them. Next up are <a href="http://book.cakephp.org/view/170/Core-Components">components</a> which are similar to helpers, although these are more at a behind-the-scenes level, and helpers are used more for displaying and formatting data on the interface side of things. Again we may use some of these later, but at the minute just hit &#8220;n&#8221; for components. Finally hit &#8220;y&#8221; for sessions, and I agreed to the default name for the admin section, &#8220;admin&#8221;, although you may wish to change this.  Hit &#8220;y&#8221; for the confirmation, and then &#8220;n&#8221; for the testing question again.</p>
<p>Repeat this for the other controllers.</p>
<p>Finally we have to make some views, so here we go again, although this step is a lot quicker. Choose &#8220;[V]iew&#8221; from the main menu, and I&#8217;m starting off with Friends again. The first question it asks is seemly about the scaffolding again:</p>
<pre>Would you like to create some scaffolded views (index, add, view, edit) for this controller?
NOTE: Before doing so, you'll need to create your controller and model classes (including associated models). (y/n)
[n] &gt; y</pre>
<p>Before we wanted nothing to do with scaffolding, but here we hit &#8220;y&#8221;: this generates the views for the basic class methods we agreed to in the controller generation. We&#8217;re then asked about admin routing views, and we press &#8220;y&#8221; again, and the script tells us it&#8217;s generated the files we need.</p>
<p>Repeat this process for the other views, and then we&#8217;re done with baking.</p>
<h3>Let&#8217;s see what we&#8217;ve done so far&#8230;</h3>
<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot.png"><img class="alignleft size-medium wp-image-143" title="defaut-news-screenshot" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/screenshot-300x187.png" alt="defaut-news-screenshot" width="300" height="187" /></a>Now what exactly has all that baking achieved? If you go to the index page of your app directory in the web browser, you&#8217;ll just be greeted with the same welcome page. But try navigating to your_app_folder/news or your_app_folder/works and a new page comes up. You can give adding a piece of a news a go with the &#8220;New News&#8221; link on the news page. A form pops up letting you fill in the date, title and post body, and you&#8217;ll notice the entry form lets you fill in the date correctly and so on.  We aren&#8217;t prompted to enter an ID because our validation criteria said we wanted this to be blank as it would be generated automatically. Once the post has been added, an entry comes up on the main page, letting us view the individual post, edit it or delete it.</p>
<p>In fact, if you&#8217;ve been keeping an eye on the URLs, you&#8217;ll have noticed that they take the form your_app_folder/controller/action. The actions were generated automatically by our baking process, and we&#8217;ll take a look at them in a bit more detail later on.</p>
<p>You&#8217;ll notice you can also go to your_app_folder/admin/news to get the same page &#8211; this is our admin routing. At the minute there is no difference between the two sections, but we&#8217;ll edit it so that you wont be able to add/edit/delete thing unless you&#8217;re in the admin section, and logged in correctly.</p>
<p>As you can see, baking has set up all the basic logic for our various sections, we just need to tweak it and glue it together a bit, and I&#8217;ll deal with that in the <a href="http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-2-authentication/">next part of the tutorial</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/03/cakephp-tutorial-part-1-bake-utility/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Using Lightbox with Apache directory listings as an image gallery</title>
		<link>http://www.actionshrimp.com/2009/03/using-lightbox-with-apache-directory-listings-as-an-image-gallery/</link>
		<comments>http://www.actionshrimp.com/2009/03/using-lightbox-with-apache-directory-listings-as-an-image-gallery/#comments</comments>
		<pubDate>Sun, 01 Mar 2009 21:48:22 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[directory]]></category>
		<category><![CDATA[gallery]]></category>
		<category><![CDATA[lightbox]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=79</guid>
		<description><![CDATA[As you may know, if it can&#8217;t find an index.html the apache web server will show a list of files in the current directory. I was browsing through lists of images on my file server the other day and I thought, wouldn&#8217;t it be nice to have a next button? So I started digging around. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/lightbox.jpg"><img class="alignleft size-medium wp-image-114" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/03/lightbox-300x184.jpg" alt="Screenshot" width="300" height="184" /></a>As you may know, if it can&#8217;t find an <code>index.html</code> the apache web server will show a list of files in the current directory. I was browsing through lists of images on my file server the other day and I thought, wouldn&#8217;t it be nice to have a next button? So I started digging around.</p>
<p>In the end I used a wonderful little script called <a href="http://www.lokeshdhakar.com/projects/lightbox2/">Lightbox 2</a> and a bit of JavaScript <a href="http://prototypejs.org">Prototype</a> magic to produce <a href="http://files.mattjbray.com/lightbox_images">this</a> (try clicking on the image files).</p>
<p>The directory listings are provided by an apache module going by the name of <code>mod_autoindex</code>. This module allows you to insert a custom header and footer through the directives <code>HeaderName</code> and <code>ReadmeName</code>. The plan is to insert some HTML that includes the Lightbox code and tags all the links to images with the <code>rel=lightbox</code> attribute that Lightbox uses to function.</p>
<p><span id="more-79"></span></p>
<p>Create a directory called <code>lightbox</code> in your server&#8217;s document root. Download <a href="http://www.lokeshdhakar.com/projects/lightbox2/#download">Lightbox 2</a> and extract it to that directory (go to http://www.yourwebsite.com/lightbox to try it out). To get the Lightbox &#8216;loading&#8217; and &#8216;next&#8217; images to show up, you need to edit a couple of lines in the configuration section of <code>js/lightbox.js</code> that comes with Lightbox. Change the following</p>
<blockquote>
<pre>LightboxOptions = Object.extend({
    fileLoadingImage:        'images/loading.gif',
    fileBottomNavCloseImage: 'images/closelabel.gif',</pre>
</blockquote>
<p>to look like</p>
<blockquote>
<pre>LightboxOptions = Object.extend({
    fileLoadingImage:        '/lightbox/images/loading.gif',
    fileBottomNavCloseImage: '/lightbox/images/closelabel.gif',</pre>
</blockquote>
<p>I also adjusted <code>resizeSpeed</code> to 9 to make it feel a little snappier, change this to your taste.</p>
<p>Now create a new file called <code>lightbox.html</code> in your <code>/lightbox</code> directory and copy and paste the following:</p>
<blockquote>
<pre>&lt;script src="/lightbox/js/prototype.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="/lightbox/js/scriptaculous.js?load=effects,builder" type="text/javascript"&gt;&lt;/script&gt;
&lt;script src="/lightbox/js/lightbox.js" type="text/javascript"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;&lt;!--
    // Insert the lightbox stylesheet into &lt;head&gt;
    var stylesheet = new Element('link', {  'rel': 'stylesheet',
                                            'href': '/lightbox/css/lightbox.css',
                                            'type': 'text/css',
                                            'media': 'screen'
                                         });
    $$('head')[0].appendChild(stylesheet);

    // Check for links preceded by the image icon provided by mod_autoindex.
    // On my setup the src attribute in the img tag preceding a link to an image
    // is "/icons/image2.gif". This is used to identify links to images.
    $$("a").each( function(elmt) {
            // The default output is tabular, so check the previous cell for the img tag
            imgelmt = elmt.up().previous().down()
            // If the FancyIndexes option is set, the output is formatted differently
            if (imgelmt == undefined) { imgelmt = elmt.previous('img') }
            if (imgelmt.readAttribute('src') == "/icons/image2.gif")
            {
                elmt.setAttribute('rel', 'lightbox[images]');

                // As ps suggested, provide a link to the image in the lightbox description
                link = "&lt;a href='" + elmt.readAttribute('href') + "'&gt;" +
                        elmt.innerHTML.stripScripts().stripTags() + "&lt;/a&gt;";
                elmt.setAttribute('title', link );
            }
        } );
// --&gt;&lt;/script&gt;</pre>
</blockquote>
<p>Now all you have to do is tell apache to include this file in its directory listing page. Simply paste the following two lines into a file named <code>.htaccess</code> and copy it to any directory that you want Lightbox to appear in.</p>
<blockquote>
<pre>Options Indexes
ReadmeName /lightbox/lightbox.html</pre>
</blockquote>
<p>Et voila! No php, no databases to maintain. Image galleries don&#8217;t get much simpler than that.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/03/using-lightbox-with-apache-directory-listings-as-an-image-gallery/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Installing awesome Window Manager on Ubuntu Intrepid</title>
		<link>http://www.actionshrimp.com/2009/02/installing-awesome-window-manager-on-ubuntu-intrepid/</link>
		<comments>http://www.actionshrimp.com/2009/02/installing-awesome-window-manager-on-ubuntu-intrepid/#comments</comments>
		<pubDate>Mon, 02 Feb 2009 21:33:08 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[awesome]]></category>
		<category><![CDATA[awm]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[window]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=52</guid>
		<description><![CDATA[Quick Note: This post was originally published on 02/02/2009, so is probably a bit outdated now. Today I had a go at installing awesome window manager. awesome is a great tiling window manager, useful if you have a large monitor and are fed up with having one window taking up all the space when it [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Quick Note: This post was originally published on 02/02/2009, so is probably a bit outdated now.</strong></p>
<p>Today I had a go at installing <a href="http://awesome.naquadah.org/">awesome window manager</a>. awesome is a great tiling window manager, useful if you have a large monitor and are fed up with having one window taking up all the space when it doesn&#8217;t really need it all. For example, having firefox maximised on a 1920&#215;1200 resolution monitor can mean you end up with very large sentences that spread across the screen, decreasing readability. Unfortunately the version of awesome in the Interpid repos is 2.3.2-1, which is now deprecated, and the current stable release is version 3.1-1.</p>
<p><img class="aligncenter size-full wp-image-67" title="awesomescreenmini" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/02/awesomescreenmini.png" alt="awesomescreenmini" width="200" height="98" /></p>
<p>The website suggests building from source &#8211; I attempted this but there are currently a couple of issues with compilation mentioned in the wiki, and even with the fix suggested I couldn&#8217;t quite get it to work &#8211; although I didn&#8217;t try too hard it must be said; instead I found another method which I will walk you through now.</p>
<p><span id="more-52"></span></p>
<h2>Installing and Trying It Out</h2>
<p>The method I ended up using (thanks to my buddy Matt for figuring this out) revolves using binaries from the Debian experimental repository, which seem to work perfectly. First, you can download the awesome 3.1-1 package (N.B. The binaries I&#8217;m linking to here from Debian&#8217;s website are for i386, for others just search for them on the site), and try and install it with:</p>
<pre>wget http://ftp.uk.debian.org/debian/pool/main/a/awesome/awesome_3.1-1_i386.deb
sudo dpkg -i awesome_3.1-1_i386.deb</pre>
<p>However, it will spit out a list of dependencies it couldn&#8217;t manage &#8211; these are packages that are also outdated in the current Ubuntu repos. So next, fetch the ones you need which are listed below:</p>
<pre>wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-atom1_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-aux0_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-event1_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-icccm1_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-keysyms0_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-property1_0.3.2-1_i386.deb
wget http://ftp.uk.debian.org/debian/pool/main/x/xcb-util/libxcb-render-util0_0.3.2-1_i386.deb</pre>
<p>Then try and install them all with dpkg:</p>
<pre>sudo dpkg -i awesome_3.1-1_i386.deb libxcb-atom1_0.3.2-1_i386.deb libxcb-aux0_0.3.2-1_i386.deb \
libxcb-event1_0.3.2-1_i386.deb libxcb-icccm1_0.3.2-1_i386.deb libxcb-property1_0.3.2-1_i386.deb \
libxcb-render-util0_0.3.2-1_i386.deb libxcb-keysyms0_0.3.2-1_i386.deb</pre>
<p>At this point, it might spit out that it needs some extra packages &#8211; these are packages that you should just be able to install normally with synaptic or apt: I had to install menu for example,  you may have to install some others as I had a few other dependencies installed from trying to build from source earlier on.  Once you have all the packages, run the above command again to install awesome.</p>
<p>Once awesome is installed, we need a configuration file. A default config file is provided, so go ahead and copy it to your home dir:</p>
<pre>mkdir ~/.config/awesome
cp /etc/xdg/awesome/rc.lua ~/.config/awesome/rc.lua</pre>
<p>Now we can see if awesome works &#8211; kill your current window manager (in my case compiz), then fire up awesome:</p>
<pre>killall compiz.real &amp;&amp; awesome&amp;</pre>
<p>Hopefully everything has gone to plan, and awesome should now be running! Hooray! Have a little play around with it, mess with the config file a bit and see if you like it. Some useful key-bindings are:</p>
<ul>
<li>Win + Enter &#8211; launch a terminal</li>
<li>Win + F1 &#8211; run a command</li>
<li>Win + J/K &#8211; switch windows (à la vim)</li>
<li>Win + H/L &#8211; resize major/minor divide</li>
<li>Win + Shift + J/K &#8211; move windows</li>
<li>Win + Space &#8211; change layout</li>
<li>Win + Ctrl + r &#8211; restart awesome, for example to update if you change the config file</li>
</ul>
<p>There are loads more keybindings that you can find/change in the config file if you wanna know what they all do exactly.</p>
<p>If after using awesome for a while you decide you want to keep it, there are a few loose ends to tie up.</p>
<h2>Setting awesome as the Default Window Manager</h2>
<p>First, fire up gconf-editor:</p>
<pre>gconf-editor</pre>
<p>On the list on the left, goto:</p>
<pre> desktop &gt; gnome &gt; session</pre>
<p>First of all, we&#8217;ll get rid of the gnome-panels &#8211; awesome already has its own. On the right, there is a <strong>name/value pair</strong> with name &#8216;required_components_list&#8217;, containing &#8220;[windowmanager, panel, filemanager]&#8220;. Remove panel, so it becomes &#8220;[windowmanager, filemanager]&#8220;.</p>
<p>Next we actually tell gnome to load in awesome instead of compiz. On the list on the left, choose the <strong>folder</strong> required_components. Change the windowmanager field from &#8221;compiz&#8217; to &#8216;awesome&#8217;.</p>
<p>Finally, you&#8217;ll probably wan&#8217;t to disable nautilus&#8217;s desktop (where the desktop icons live etc.) as it can do funny things, and with your magical new tiling windows you will probably never see the desktop. To do this, from the list on the left choose</p>
<pre>apps &gt; nautilus &gt; preferences</pre>
<p>and when here, uncheck show_desktop.</p>
<p>Now you can kiss sweet goodbye to all the remnants of your old desktop &#8211; log out of your system and log back in again to see it take effect. WARNING: If something has gone wrong and awesome doesn&#8217;t load (maybe you mispelt it in gconf-editor or something), you should still be able to find a way to edit the gconf preferences, but it took me a while to figure out how to logout when the normal gnome logout button had disappeared. To logout in this situation, type gnome-session-save &#8211;kill.</p>
<h2>Customising and Configuring</h2>
<p>Due to the highly keyboard oriented nature of awesome, you may now want to install a launcher. A couple of good ones are Gnome-Do (if you opt for this, you will have to change the binding from Win+Space in the awesome preferences, or reconfigure awesome&#8217;s binding for this combination), an all singing all dancing affair which I used for a while, or dmenu which is quite a lot simpler and I&#8217;ve opted for in this case.</p>
<p>To install dmenu:</p>
<pre>sudo apt-get install dmenu</pre>
<p>Next we setup a keybinding for it to launch in the awesome config file. Underneath the line:</p>
<pre>-- {{{ Keybindings</pre>
<p>Add (here it is mapped to Win+P &#8211; change this if you like):</p>
<pre>-- dmenu
keybinding({ modkey }, "p", function () awful.util.spawn("`dmenu_path | dmenu -b`") end):add()</pre>
<p>Also, as awesome is aimed at uber geeks the time is displayed by default as&#8230;. unix time_t. Unless you&#8217;re some kind of magician, hunt down the section in the config file that looks like this, and comment/uncomment accordingly:</p>
<pre>-- For unix time_t lovers
--mytextbox.text = " " .. os.time() .. " time_t "
-- Otherwise use:
mytextbox.text = " " .. os.date() .. " "</pre>
<p>Finally, I missed my CPU monitor. There is however a set of widgets you can get that adds functionality like this called wicked.</p>
<p>Install wicked:</p>
<pre>git clone git://git.glacicle.com/awesome/wicked.git
sudo cp wicked/wicked.lua /usr/share/awesome/lib/
sudo cp wicked/wicked.7.gz /usr/share/man/man7/</pre>
<p>in config file, underneath:</p>
<pre>-- {{{ Wicked Widgets</pre>
<p>Add in:</p>
<pre>-- {{{ Wicked Widgets
-- CPU Usage Graph
cpugraphwidget = widget({
type = 'graph',
name = 'cpugraphwidget',
align = 'left'
})
cpugraphwidget.height = 0.85
cpugraphwidget.width = 45
cpugraphwidget.bg = '#333333'
cpugraphwidget.border_color = '#0a0a0a'
cpugraphwidget.grow = 'right'

cpugraphwidget:plot_properties_set('cpu', {
fg = '#AEC6D8',
fg_center = '#285577',
fg_end = '#285577',
vertical_gradient = false
})
wicked.register(cpugraphwidget, wicked.widgets.cpu, '$1', 1, 'cpu')</pre>
<p>Then add in the cpugraphwidget into the mywibox[s].widgets line:</p>
<pre>mywibox[s].widgets = { mylauncher,
mytaglist[s],
mytasklist[s],
mypromptbox[s],
cpugraphwidget,
mytextbox,
mylayoutbox[s],</pre>
<p>For full instructions on <a href="http://awesome.naquadah.org/wiki/index.php?title=Wicked">how to use wicked</a>, and configure awesome, check out the <a href="http://awesome.naquadah.org/wiki/index.php?title=Main_Page">awesome wiki</a>. Have fun!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2009/02/installing-awesome-window-manager-on-ubuntu-intrepid/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Logitech QuickCam E2500 on Ubuntu Skype</title>
		<link>http://www.actionshrimp.com/2008/08/logitech-quickcam-e2500-on-ubuntu-skype/</link>
		<comments>http://www.actionshrimp.com/2008/08/logitech-quickcam-e2500-on-ubuntu-skype/#comments</comments>
		<pubDate>Wed, 13 Aug 2008 00:12:57 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[e2500]]></category>
		<category><![CDATA[quickcam]]></category>
		<category><![CDATA[skype]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=8</guid>
		<description><![CDATA[I recently discovered the wonders of skype, and tried to get my new webcam working with it under linux, and of course this proved to be quite tricky. After much fiddling I eventually got it to work, hopefully these steps will work for you too. The gspca drivers are available from here, I was using [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-127 alignleft" title="193818" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2008/08/193818.jpg" alt="193818" width="170" height="170" />I recently discovered the wonders of skype, and tried to get my new webcam working with it under linux, and of course this proved to be quite tricky. After much fiddling I eventually got it to work, hopefully these steps will work for you too.</p>
<p><span id="more-8"></span></p>
<p>The gspca drivers are available from <a href="http://mxhaard.free.fr/download.html">here</a>, I was using a specific version dated 20071224 to work with a patch file I found &#8211; many thanks to <a href="http://forums.quickcamteam.net/showthread.php?tid=310">redeye on the QuickCam team forums</a>. If you use a different version of the drivers, you can just examine the patch file and insert the changes manually.</p>
<p>First, download the drivers and the patch:</p>
<pre>wget http://mxhaard.free.fr/spca50x/Download/gspcav1-20071224.tar.gz
wget http://forums.quickcamteam.net/attachment.php?aid=86 -O patch.tar.gz</pre>
<p>Then extract and apply the patch:</p>
<p>(UPDATE: For Ubuntu 8.10 users, this patch may no longer work. Try downloading the patch <a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2009/01/gspcapatch.gz">here</a> instead, and then extract it using gzip -d gspcapatch.gz. Apply the extracted file in the same was as below, just neglect the -p1 switch, (so do: patch &lt; gspcapatch), you can just ignore the tar -xvf patch.tar.gz command).</p>
<pre>tar -xvf gspcav1-20071224.tar.gz
tar -xvf patch.tar.gz
cd gspcav1-20071224
patch -p1 &lt; ../quickcamE2500.diff</pre>
<p>There&#8217;s a handy build script included with the drivers so just run that (requires root):</p>
<pre>sudo ./gspca_build</pre>
<p>This generates the file</p>
<pre>gspca.ko</pre>
<p>which we use to replace the old gspca module.<br />
Check to see if the old module is loaded, you should see something like:</p>
<pre>dave@baracus:~$ lsmod | grep gspca
gspca                 680656  0
videodev               29440  1 gspca
usbcore               146028  9 gspca,snd_usb_audio,snd_usb_lib,usb_storage,usbhid,libusual,ehci_hcd,ohci_hcd</pre>
<p>We want to find out where it is, so do the following:</p>
<pre>sudo rmmod gspca
sudo modprobe -v gspca</pre>
<p>You should see something like:</p>
<pre>insmod /lib/modules/2.6.24-20-generic/ubuntu/media/gspcav1/gspca.ko</pre>
<p>That is the location of the file we&#8217;re looking for, so, replacing where appropriate with what was output for you above, type:</p>
<pre>sudo rmmod gspca
sudo rm /lib/modules/2.6.24-20-generic/ubuntu/media/gspcav1/gspca.ko
sudo mv gspca.ko /lib/modules/2.6.24-20-generic/ubuntu/media/gspcav1/
sudo modprobe gspca</pre>
<p>This should have loaded the new module in place of the old one. See if you have a video device:</p>
<pre>dave@baracus:~$ ls /dev/video*
/dev/video0</pre>
<p>You can try and run Skype now, and in fact, if you&#8217;re not using the camera for Skype, this may well be enough. But for the Skype users: see if you get any picture by testing in the video devices option menu (be warned, it can take a little while to show up there after skype loads, and a little while for the picture to show when you press the test button, so be patient). If anything show&#8217;s up at all that&#8217;s a plus. (UPDATE: If you&#8217;re using Ubuntu 8.10, and have used the alternative patch I posted in the other &#8220;UPDATE:&#8221; bracket above, the webcam may still not work in Skype at this point. There seems to be some issue with permissions in this version of the driver, so you may need to run skype as root if it doesn&#8217;t appear to be working. In a terminal type &#8220;sudo skype&#8221; and hit enter. It&#8217;ll ask for your root password, then launch skype. See if the webcam works now).</p>
<p>Originally, I had a black image, so I assumed the camera wasn&#8217;t working, but I soon realised that the image was there, just very dark &#8211; shining a light on it showed this was the case. I tried fiddling around with gstfakevideo for a while to try and alter the output, but there was a much simpler solution. The gspca driver itself can take options, and an autoexposure setting was ruining my lighting. To fix this, edit the file /etc/modprobe.d/options, and add a line at the bottom:</p>
<pre>options gspca gamma=1 autoexpo=0</pre>
<p>The gamma=1 may not be necessary, but if it still appears too dark or too light for your taste you can change this parameter as you like. Finally, reload the module:</p>
<pre>sudo rmmod gspca
sudo modprobe gspca</pre>
<p>and try out skype again. Hopefully it works!</p>
<p>I ran into quite a lot of other problems while I was trying this out, so if you come across any errors, drop a comment below and I&#8217;ll try and get back to you asap.</p>
<p><strong>UPDATE</strong>: I found a large problem when using the camera in Skype was that CPU usage would shoot up to 100%, causing things to freeze up and conversations to crash after a while. I had played around with <a href="http://code.google.com/p/gstfakevideo">gstfakevideo</a> a bit when trying to get the camera to work originally, and it seems using this when the camera already &#8216;works&#8217; means it uses up far less CPU. I haven&#8217;t had a chance to test it for a long period yet but it seems like it should do the trick. Here&#8217;s what I did:</p>
<p>First, download gstfakevideo using subversion (you may need to install the subversion package, sudo apt-get subversion probably does the trick, and then the command below will make a directory called gstfakevideo in your current location, so make sure it&#8217;s somewhere nice), then compile and install it:</p>
<pre>svn checkout http://gstfakevideo.googlecode.com/svn/trunk/ gstfakevideo
cd gstfakevideo
make
sudo make install</pre>
<p>gstfakevideo creates a new video stream using your webcam, which is formatted differently and skype seems to get along with it more. The only problem is, it outputs its stream to /dev/video0 which is where our webcam currently lives. So we have to move the webcam, but this is easy enough:</p>
<pre>sudo mv /dev/video0 /dev/video1</pre>
<p>(Actually, gstfakevideo seems to work for me with lower CPU without moving this &#8211; but try it moved first anyway). Watch out though, every time you reboot, your webcam will probably go to /dev/video0 by default, assuming you have no other video devices, so you will have to move stuff about to make a space in video0 each time. Now we see if it works:</p>
<pre>gstfakevideo v4lsrc device=/dev/video1 ! ffmpegcolorspace</pre>
<p>What this does is runs gstfakevideo, telling it that the source we&#8217;re using is a v4l source, and its from /dev/video1. The ffmpegcolorspace argument seems to be for making the stream YUV instead of RGB for some cameras so may not be necessary. It then launches skype, with hopefully the output below:</p>
<pre>dave@baracus:~$ gstfakevideo v4lsrc device=/dev/video1 ! ffmpegcolorspace
gst.c create_pipeline (155): pipeline created
gst.c create_pipeline (159): pipeline linked</pre>
<p>If you look in the skype video options now there will be no camera listed. You have to wait a while (it can take 30s or so), until you get some output, ending with something like:</p>
<pre>gst.c shim_ioctl (201): request=803c7601 nr 1
gst.c shim_ioctl (208): VIDIOCGCAP
gst.c shim_ioctl (313): result=0 error=0 Success</pre>
<p>Now a camera should show up in the video menu in skype, with a name like GStreamer fake video (/dev/video0). Try it out, and compare your CPU performance to before. Also try exiting skype, and moving your video source from /dev/video1 back to video0, and running gstfakevideo again, only with device=/dev/video0, and see if it works (and let me know your findings below!).</p>
<p>Finally if gstfakevideo works, we can clean it up so the command isn&#8217;t so long to type. The script should be stored in:</p>
<pre>/usr/local/bin/gstfakevideo</pre>
<p>(Can check this using):</p>
<pre>dave@baracus:~$ whereis gstfakevideo
gstfakevideo: /usr/local/bin/gstfakevideo</pre>
<p>So we edit this file (requires root):</p>
<pre>sudo gedit /usr/local/bin/gstfakevideo</pre>
<p>Now, find the line that looks like this:</p>
<pre>export GST_PIPE="videotestsrc is-live=true ! video/x-raw-yuv,width=640,height=480,framerate=10/1 ! videoscale ! ffmpegcolorspace ! vertigotv ! ffmpegcolorspace"</pre>
<p>and change it to (remember where you put your webcam source &#8211; if you moved it back to /dev/video0, change the device parameter accordingly):</p>
<pre>export GST_PIPE="v4lsrc device=/dev/video1 ! ffmpegcolorspace"</pre>
<p>and finally look a bit further down, and delete the line:</p>
<pre>export GST_PIPE="$*"</pre>
<p>Now Skype will launch with your faked video stream, just from the command gstfakevideo. Good luck! Let me know how you get on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2008/08/logitech-quickcam-e2500-on-ubuntu-skype/feed/</wfw:commentRss>
		<slash:comments>127</slash:comments>
		</item>
		<item>
		<title>jsvi and TiddlyWiki</title>
		<link>http://www.actionshrimp.com/2008/05/jsvi-and-tiddlywiki/</link>
		<comments>http://www.actionshrimp.com/2008/05/jsvi-and-tiddlywiki/#comments</comments>
		<pubDate>Tue, 13 May 2008 15:26:28 +0000</pubDate>
		<dc:creator>Dave</dc:creator>
				<category><![CDATA[TiddlyWiki]]></category>
		<category><![CDATA[integration]]></category>
		<category><![CDATA[jsvi]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.actionshrimp.com/?p=6</guid>
		<description><![CDATA[Note: This is a bit out of date now, but Chris Peplin has built a proper plugin for tiddlywiki which does this for the latest versions of everything. So check it out! If you&#8217;re still interested in the old way then read on&#8230; When adding posts to my TiddlyWiki, I oft found myself craving vi, [...]]]></description>
			<content:encoded><![CDATA[<p><i>Note: This is a bit out of date now, but Chris Peplin has built <a href="http://github.com/peplin/jsvim-tiddly">a proper plugin</a> for tiddlywiki which does this for the latest versions of everything. So check it out! If you&#8217;re still interested in the old way then read on&#8230;</i></p>
<p style="text-align: left;">When adding posts to my TiddlyWiki, I oft found myself craving <a title="vi" href="http://en.wikipedia.org/wiki/Vi" target="_blank">vi</a>, rather than a simple textarea. There were a few options that involved using a plugin for Firefox such as mozEx, and using an external program to edit textareas. However, I found a nice &#8216;integrated&#8217; option instead.</p>
<p style="text-align: left;"><span id="more-6"></span></p>
<p style="text-align: left;"><a title="jsvi" href="http://gpl.internetconnection.net/vi/" target="_blank">jsvi</a> is an excellent javascript implementation of vi. I decided to try and integrate it into my TiddlyWiki, and the steps I took are shown below. To try out the final result, use the edit mode on my <a title="PhysiWiki" href="http://www.actionshrimp.com/physiwiki/" target="_blank">wiki</a>.</p>
<p style="text-align: center;"><a href="http://www.actionshrimp.com/wordpress/wp-content/uploads/2008/05/jsvi.png"><img class="size-medium wp-image-7" title="jsvi" src="http://www.actionshrimp.com/wordpress/wp-content/uploads/2008/05/jsvi-300x225.png" alt="jsvi in action on my wiki" width="300" height="225" /></a></p>
<p style="text-align: left;"><em><strong>Be warned:</strong></em> <em>this is a bit of a dirty hack, and requires a few files external to the TiddlyWiki file, which makes TiddlyWiki a bit less portable. At some point it&#8217;d be nice if this was build as a TiddlyWiki plugin instead, but at the minute I&#8217;m not experienced enough with writing plugins for TW. There is also a slight bug which means you can&#8217;t scroll up while editing. </em></p>
<p style="text-align: left;">First of all, I installed the <a title="iFrameEditorPlugin" href="http://visualtw.ouvaton.org/old/VisualTW.old.html#iFrameEditorPlugin" target="_blank">iFrameEditorPlugin</a> from an old version of the <a title="VisualTW" href="http://visualtw.ouvaton.org/VisualTW.html" target="_blank">VisualTW</a> site. I don&#8217;t think VisualTW uses the plugin anymore, and has instead changed it&#8217;s wysiwig editors to using plugins rather than iFrames &#8211; a far superior solution, but one I didn&#8217;t have the time or ability for. The plugin alone is not quite enough though, and a few changes to it are required.</p>
<p style="text-align: left;">iFrameEditorPlugin loads an iFrame containing your editor, passes the editor the text from the body of the tiddler, you edit it, and then when you save the page, the plugin gets your changes and saves them to the tiddler. However, it expects you to use a custom field rather than the default text field, which is a slight problem in our case. The function getContent() is what actually performs this:</p>
<pre style="text-align: left;">getContent=function(tiddler, field) {
    var t,f;
    t=store.getTiddler(tiddler);
    f = t ? t.fields[field] : "";
    f = f ? f : "";
    return f;
}</pre>
<p style="text-align: left;">As you can see, it reads the field of the tiddler with t.fields[field]. To read the default text field instead, I added a new function to the plugin:</p>
<pre style="text-align: left;">getContentText=function(tiddler) {
 var t,f;
 t=store.getTiddler(tiddler);
 f = t ? t.text : "";
 f = f ? f : "";
 return f;
}</pre>
<p style="text-align: left;">Great. So that&#8217;s set up. There&#8217;s also another problem with the plugin &#8211; it was originally intended for use with wysiwig html style editors, but I enjoy editing my wiki content raw. Also, the content has to be passed in a URL to the editor, so strange characters in the URL will mess it up, so there were problem with escaping html entities and things like that. To get around this, I found a handy javascript function that converted html entities back to their original form, and added this to the top of the plugin (thanks to The JavaScript Source):</p>
<pre style="text-align: left;">/* This script and many more are available free online at
The JavaScript Source!! http://javascript.internet.com
Created by: Ultimater | http://webdeveloper.com/forum/member.php?u=30185 */
function html_entity_decode(str) {
  var ta=document.createElement("textarea");
  ta.innerHTML=str.replace(/&lt;/g,"&lt;").replace(/&gt;/g,"&gt;");
  return ta.value;
}</pre>
<p style="text-align: left;">Ok, now we actually have to use this function, so we edit the plugin a bit more. Look for the line that reads the data back from the iFrame:</p>
<pre style="text-align: left;">if(f) fields[f] = e.contentWindow.getContent();</pre>
<p style="text-align: left;">and change it to:</p>
<pre style="text-align: left;">if(f) fields[f] = html_entity_decode(e.contentWindow.getContent());</pre>
<p style="text-align: left;">The plugin is all ready to go now, so we have to make the actual external editor that&#8217;s gonna go in the iFrame, using jsvi. Download these three files, and put them in the same folder as your TiddlyWiki html file.</p>
<blockquote style="text-align: left;"><p><a href="http://gpl.internetconnection.net/vi/vi.js" target="_blank">vi.js</a><br />
<a title="jsvi css file" href="http://gpl.internetconnection.net/vi/vi.css" target="_blank">vi.css</a><br />
<a title="editor" href="http://www.actionshrimp.com/physiwiki/editor.html" target="_blank">editor.html</a></p></blockquote>
<p style="text-align: left;">The first two are the actual jsvi javascript file and it&#8217;s style sheet, the second is my own editor iFrame. Let&#8217;s have a look at the important lines of the <em>editor.html</em> file:</p>
<pre style="text-align: left;">&lt;script type="text/javascript" src="vi.js"&gt;&lt;/script&gt;</pre>
<p style="text-align: left;">This includes the jsvi javascript file.</p>
<pre style="text-align: left;">&lt;textarea style="width: 99%" name="theEditor" onfocus="editor(this);"&gt;
&lt;/textarea&gt;</pre>
<p style="text-align: left;">This builds the actual textarea that&#8217;s gonna be edited by jsvi. Ok, now the javascript &#8220;meat&#8221; of the page:</p>
<pre style="text-align: left;">var oEditor = document.getElementsByName('theEditor')[0];
function getContent() {return oEditor.value;}
tiddlers=/[\?&amp;]tiddler=([^&amp;#]*)/.exec(unescape(window.location.href));
fields=/[\?&amp;]field=([^&amp;#]*)/.exec(unescape(window.location.href));
if (tiddlers&amp;&amp;fields) oEditor.value = parent.getContentText(tiddlers[1]);
oEditor.focus();</pre>
<p style="text-align: left;">All that happens here is we write the getContent() function that the iFrameEditorPlugin calls to read your changes. The tiddlers line reads the URL to get which tiddler you&#8217;re editing, and the fields line does the same for the field (actually this isn&#8217;t even necessary with our getContentText() function). The last two lines read the tiddler&#8217;s content, so we can edit it, and set the focus to the textarea to launch jsvi automatically when the iFrame loads.</p>
<p style="text-align: left;">That&#8217;s everything setup now, so all we need to do is tell Tiddlywiki when we want to make our edits with the iFrameEditor instead of with it&#8217;s default text field. I made a plugin (based on code from VisualTW&#8217;s EasyEditPlugin &#8211; thanks a lot!). <a title="jsviPlugin" href="http://www.actionshrimp.com/physiwiki/#jsviPlugin">You can view the plugin here</a>. Hopefully it should add a &#8216;vi&#8217; button next to the edit button on each tiddler. If no button appears, add &#8216;jsvi&#8217; to the first line of the ViewTemplate tiddler to look like this:</p>
<pre>&lt;div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler jsvi &gt; fields syncing ....</pre>
<p style="text-align: left;">To make jsvi the default, remove the + from in front of editTiddler and put it in front of jsvi.</p>
<p style="text-align: left;">Now when you press the vi button, you should be presented with a rather gorgeous vi interface! <em><strong>One note, when you&#8217;re done editing a tiddler with jsvi, you must save it using the usual vi write command, :w, or press the &#8220;Save and Close&#8221; button. Otherwise the textarea does not get updated, and the iFrameEditorPlugin cannot read your changes. Also beware editing config shadow tiddlers with jsvi, as the line &#8220;macro=stuff&#8221; in some of the tooldbars etc. is interpreted by jsvi as it&#8217;s own command and it can end up destroying certain things.<br />
</strong></em></p>
<p style="text-align: left;">Update: I found a small problem with focusing using this in Firefox (didn&#8217;t test in other platforms) &#8211; after editing a post I was unable to select other fields and items in the window. This was fixed by changing one line in the vi.js file, line <strong>3588</strong>, which needs to be uncommented (the comment line before even refers to a bug in Firefox, possibly in an older version?) to look like this:</p>
<pre>document.body.removeChild(backing);</pre>
<p style="text-align: left;">Now it should work perfectly, apart from a few kinks: being able to edit the tiddler title the first time jsvi launches. Save and close vi, and it&#8217;s editable again, and still editable when you relaunch jsvi by clicking on the text area. If you cant get focus back on jsvi, right click it.</p>
<p style="text-align: left;">Hope you enjoy this as much as I do, and hopefully at some point soon when I have a bit more free time, I&#8217;ll have it in plugin format so it&#8217;s all incorporated into TW. Any problems, leave a comment and I&#8217;ll try and get back to you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.actionshrimp.com/2008/05/jsvi-and-tiddlywiki/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

