<?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>Coopology: All things Coop.</title>
	<atom:link href="http://coopology.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://coopology.com</link>
	<description>Tweaks, tools, scripts, and rants.</description>
	<lastBuildDate>Wed, 27 Feb 2013 14:48:37 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Building SOAP services on Google App Engine in Java: Part 1 &#8211; The Servlet</title>
		<link>http://coopology.com/2013/02/building-soap-services-on-google-app-engine-in-java/</link>
		<comments>http://coopology.com/2013/02/building-soap-services-on-google-app-engine-in-java/#comments</comments>
		<pubDate>Wed, 27 Feb 2013 14:22:22 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[Web Applications]]></category>
		<category><![CDATA[Axis2]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Web Application]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=147</guid>
		<description><![CDATA[Background Google App Engine (GAE) is an interesting platform that aims to allow for the development and hosting of Java, Python, and Go web applications.  The pricing scheme is particularly nice:  low-usage applications are hosted for free, pricing is solely dependent on resource usage (with the ability to set budgets and limits), and the minimum charge [...]]]></description>
				<content:encoded><![CDATA[<h2>Background</h2>
<p><a href="https://developers.google.com/appengine/" target="_blank">Google App Engine</a> (GAE) is an interesting platform that aims to allow for the development and hosting of Java, Python, and Go web applications.  The <a href="https://developers.google.com/appengine/docs/billing" target="_blank">pricing scheme</a> is particularly nice:  low-usage applications are hosted for free, pricing is solely dependent on resource usage (with the ability to set budgets and limits), and the minimum charge is only $2.10 per week.  No, I&#8217;m not affiliated with or being compensated by Google, but I do think this platform has some potential.</p>
<p>Google supplies a nice <a href="https://developers.google.com/appengine/docs/java/tools/eclipse" target="_blank">Eclipse plugin</a> for use with the <a href="https://developers.google.com/web-toolkit/" target="_blank">Google Web Toolkit</a> and the App Engine, which allows for pretty easy construction of your standard web applications.  I&#8217;ve heard that it&#8217;s fairly easy to construct user interfaces, JSP pages, etc., but that&#8217;s not what we&#8217;re talking about here.</p>
<h2>The Task</h2>
<p>How can we build an application that uses the Google App Engine which uses SOAP for an API?  The primary problem (for me) is that one cannot use the Axis2 libraries (on the server side) due to permission issues, so things must be done a little more manually.</p>
<p>Google has <a href="https://developers.google.com/appengine/articles/soap" target="_blank">an article</a> covering the topic, but I wanted to do things slightly differently.  Specifically, I wanted to be able to create my service class in Java, generate the WSDL (with appropriately named fields in the XML types &#8211; not Parameter1,2,&#8230;), generate XML types which will be shared between the server and client projects, and to do it in such a way that I do not have to worry about keeping track of QNAMEs or other low-level details.</p>
<h2>Requirements</h2>
<p>For this project, I use:</p>
<p style="padding-left: 30px;">• Eclipse for development, with the <a href="https://developers.google.com/appengine/docs/java/tools/eclipse" target="_blank">Eclipse plugin</a> for GAE</p>
<p style="padding-left: 30px;">• Axis2 for the client class (also for the java2wsdl and wsdl2java tools)</p>
<p style="padding-left: 30px;">• JAXB for XML types (auto-generated by Axis2)</p>
<h2>The Server</h2>
<h3>Overview of the Process</h3>
<p>Here&#8217;s the logic flow for the server:</p>
<p style="padding-left: 30px;">1. SOAP request arrives via Post into a HttpServlet.</p>
<p style="padding-left: 30px;">2. HttpServlet builds a SOAPMessage for the request, and passes it to the SoapHandler class.</p>
<p style="padding-left: 30px;">3. SoapHandler unmarshalls the XML message object, detects its type, and passes a specific application request to the ServiceAdapter class.</p>
<p style="padding-left: 30px;">4. ServiceAdapter translates from the XML request message (in a safe fashion) to the Service method call.</p>
<p style="padding-left: 30px;">5. Service method is run, business logic is performed, all the magic happens.</p>
<p style="padding-left: 30px;">6. ServiceAdapter translates Service method response to XML response message.</p>
<p style="padding-left: 30px;">7. SoapHandler builds SOAPMessage response (including catching thrown exceptions and turning them into SOAP Fault messages).</p>
<p style="padding-left: 30px;">8. HttpServlet writes response to client.</p>
<p>All of that seems like a lot of work, but it&#8217;s pretty straightforward.  The best part?  I&#8217;ll give you the skeleton for all of this; there&#8217;s not much application-specific content in all of this.  The process for adding a method to your service class is: implement service class method, run Axis2 generators, modify/fix Axis2 client (the same every time, some auto-gen code must be changed), add 2 lines to SoapHandler, add an adaption method to SoapAdapter, and add a method to the client class.  It&#8217;s easier than it sounds.</p>
<h2>Part 1 &#8211; The HttpServlet</h2>
<p>Good news!  There&#8217;s no service specific code here.  I&#8217;ll just post the relevant parts of what I use:</p>
<pre class="brush: java; title: SOAPServerServlet.java; notranslate">
public class SOAPServerServlet extends HttpServlet {
	public static final String URL = &quot;http://ms4models.appspot.com/service&quot;;

	private static final Logger log = Logger
		.getLogger(SOAPServerServlet.class.getName());
	private static MessageFactory messageFactory;
	private static ServiceSOAPHandler soapHandler;

	static {
		try {
			messageFactory = MessageFactory.newInstance();
			soapHandler = new ServiceSOAPHandler();
		} catch (Exception ex) {
			throw new RuntimeException(ex);
		}
	}

	@Override
	public void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		log.info(&quot;SOAPAction: &quot; + req.getHeader(&quot;SOAPAction&quot;));
		log.entering(&quot;SOAPServerServlet&quot;, &quot;doPost&quot;, new Object[] {
				req, resp });
		try {
			// Get all the headers from the HTTP request
			MimeHeaders headers = getHeaders(req);

			// Construct a SOAPMessage from the XML in the request body
			InputStream is = req.getInputStream();
			SOAPMessage soapRequest = messageFactory.createMessage(headers, is);

			ByteArrayOutputStream out = new ByteArrayOutputStream();
			soapRequest.writeTo(out);
			String strMsg = new String(out.toByteArray());

			log.finer(&quot;SOAP request: &quot; + strMsg);

			// Handle soapReqest
			SOAPMessage soapResponse = soapHandler
					.handleSOAPRequest(soapRequest);

			// Write to HttpServeltResponse
			resp.setStatus(HttpServletResponse.SC_OK);
			resp.setContentType(&quot;text/xml;charset=\&quot;utf-8\&quot;&quot;);
			OutputStream os = resp.getOutputStream();
			soapResponse.writeTo(os);
			os.flush();
		} catch (SOAPException e) {
			throw new IOException(&quot;Exception while creating SOAP message.&quot;, e);
		}
		log.exiting(&quot;SOAPServerServlet&quot;, &quot;doPost&quot;);
	}

	@SuppressWarnings(&quot;rawtypes&quot;)
	static MimeHeaders getHeaders(HttpServletRequest req) {
		Enumeration headerNames = req.getHeaderNames();
		MimeHeaders headers = new MimeHeaders();
		while (headerNames.hasMoreElements()) {
			String headerName = (String) headerNames.nextElement();
			String headerValue = req.getHeader(headerName);
			StringTokenizer values = new StringTokenizer(headerValue, &quot;,&quot;);
			while (values.hasMoreTokens()) {
				headers.addHeader(headerName, values.nextToken().trim());
			}
		}
		return headers;
	}
}
</pre>
<p>Leave a comment if you have a question about what&#8217;s going on, I&#8217;ll not explain it for brevity&#8217;s sake (also: because I am lazy).</p>
<h2>Coming Soon &#8211; Part 2</h2>
]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2013/02/building-soap-services-on-google-app-engine-in-java/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Eclipse RCP: Setting P2 repositories (update sites) programmatically (for when p2.inf fails).</title>
		<link>http://coopology.com/2012/08/eclipse-rcp-setting-p2-repositories-update-sites-programmatically-for-when-p2-inf-fails/</link>
		<comments>http://coopology.com/2012/08/eclipse-rcp-setting-p2-repositories-update-sites-programmatically-for-when-p2-inf-fails/#comments</comments>
		<pubDate>Thu, 09 Aug 2012 14:33:50 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=118</guid>
		<description><![CDATA[When deploying a p2 enabled RCP product, you often want to set the update sites that can be used so that they include yours.  There are many resources that explain about using p2.inf to do this.  However, there is an issue when trying to do this with an application that will be installed into Program [...]]]></description>
				<content:encoded><![CDATA[<p>When deploying a p2 enabled RCP product, you often want to set the update sites that can be used so that they include yours.  There are many resources that explain about <a href="http://wiki.eclipse.org/Equinox/p2/Adding_Self-Update_to_an_RCP_Application#Configuring_the_user.27s_default_repositories">using p2.inf</a> to do this.  However, there is <a href="http://www.toedter.com/blog/?p=79">an issue</a> when trying to do this with an application that will be installed into Program Files (or any non-user-writable location) on the user&#8217;s machine.  p2.inf operates by writing the repository to disk the first time that the RCP application is run.  If the application is not user-writable, this will silently fail.</p>
<p>To set the repositories manually, you can use the same technique as the <a href="http://help.eclipse.org/helios/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/equinox/p2/ui/RepositoryManipulationPage.html">P2 property page</a>:</p>
<pre class="brush: java; title: ; notranslate">
import org.eclipse.equinox.internal.p2.ui.model.MetadataRepositoryElement;
import org.eclipse.equinox.internal.p2.ui.model.ElementUtils;

@SuppressWarnings(&quot;restriction&quot;)
public class P2Util {
  private static String UPDATE_SITE = &quot;http://www.example.com/update_site&quot;;

  public static void setRepositories() throws InvocationTargetException {
    try {
      final MetadataRepositoryElement element = new MetadataRepositoryElement(null, new URI(UPDATE_SITE), true);
      ElementUtils.updateRepositoryUsingElements(new MetadataRepositoryElement[] {element}, null);
    } catch (URISyntaxException e) {
      e.printStackTrace();
      throw new InvocationTargetException(e);
    }
  }
}
</pre>
<p>Note that you need all of the repositories to be present in the
<pre class="brush: java; title: ; notranslate">ElementUtils.updateRepositoryUsingElements</pre>
<p> call; repositories not in that array will be removed.</p>
]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2012/08/eclipse-rcp-setting-p2-repositories-update-sites-programmatically-for-when-p2-inf-fails/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Easily load Xtext files and objects in Eclipse plugin or RCP projects using adapters</title>
		<link>http://coopology.com/2011/06/easily-load-xtext-files-and-objects-in-eclipse-plugin-or-rcp-projects-using-adapters/</link>
		<comments>http://coopology.com/2011/06/easily-load-xtext-files-and-objects-in-eclipse-plugin-or-rcp-projects-using-adapters/#comments</comments>
		<pubDate>Fri, 03 Jun 2011 20:05:51 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[Eclipse]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Xtext]]></category>
		<category><![CDATA[adapter]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[pde]]></category>
		<category><![CDATA[rcp]]></category>
		<category><![CDATA[xtext]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=95</guid>
		<description><![CDATA[Motivation I&#8217;m currently working on a fairly involved Eclipse RCP project which makes heavy use of Xtext for grammar parsing.  One task that&#8217;s come up fairly often is that we need to be able to perform some action on a model object contained in an Xtext file.  For example, we want to provide context menu [...]]]></description>
				<content:encoded><![CDATA[<h1>Motivation</h1>
<p>I&#8217;m currently working on a fairly involved Eclipse RCP project which makes heavy use of Xtext for grammar parsing.  One task that&#8217;s come up fairly often is that we need to be able to perform some action on a model object contained in an Xtext file.  For example, we want to provide context menu commands to open up a view to display the structure of a model; to do this we need to load the file, parse it with Xtext, and pass the model object off to the view.</p>
<p>The Xtext FAQ provides instructions for doing this in a standalone Java <a href="http://wiki.eclipse.org/Xtext/FAQ#How_do_I_load_my_model_in_a_standalone_Java_application_.3F">here</a>, but it involves calling the StandaloneSetup method to create and obtain an injector, which isn&#8217;t the best for performance.  If we&#8217;re already in a RCP application that includes our Xtext language&#8217;s UI plugin, we can efficiently obtain the injector from the activator.  In addition to this, we can wrap the whole thing in a class that ties into Eclipse&#8217;s adapter manager framework so that other plugins can load our Xtext models without needing a direct dependency on the UI plugin (though of course they still need to depend on the plugin that  defines the model classes).</p>
<h1>The Eclipse adapter framework: IAdapterFactory, IAdaptable, and IAdapterManager</h1>
<p>In a nutshell, the Eclipse adapter framework works by letting plugins register &#8216;adapter factory&#8217; classes (that implement IAdapterFactory).  These classes are designed to attempt the singular task of taking and object of some source class and figuring out how to transform it into an object of another target class.  If the transformation is possible, the AdapterFactory must return an object that can be cast as an instance of the target class.  If it is not possible, the AdapterFactory must return null.  In addition, AdapterFactory classes implement a method that returns a list of all target classes supported by the factory, and their defining plugin must provide an extension to org.eclipse.core.runtime.adapters specifying what transformations can be performed.  Traditionally, objects that support being adapted implement the IAdaptable interface, but this is not strictly required.</p>
<p>Once an adapter has been registered that can perform a transformation, any plugin can use this with a simple call:</p>
<pre class="brush: java; title: ; notranslate">
final TargetObjType target = (TargetObjType)Platform.getAdapterManager().getAdapter(sourceObject, TargetObjType.class);
if (target==null) { /* Adaptation failed */ }
</pre>
<p>The caller is guaranteed that getAdapter will either return null or an object that can be cast as TargetObjType.</p>
<h1>The ModelLoadingAdapter</h1>
<p>To create a ModelLoadingAdapter, we must implement the code to load domain models from files and register this in plugin.xml.  As an easy extension we will also let the same adapter handle selections and structured selections (allowing us to directly adapt a list selection to a domain model, if the item selected is a file).  After this is done, any plugin can easily load Xtext DSL models from files with a minimum performance hit.</p>
<p>For this example we&#8217;re going to assume the projects are called &#8220;org.xtext.example.mydsl&#8221; and &#8220;org.xtext.example.mydsl.ui&#8221;, the language is called &#8220;org.xtext.example.mydsl.MyDsl&#8221;,  it uses files with extension &#8220;mydsl&#8221;, and the root model of a document is a DslModel.</p>
<h2>The IAdapterFactory</h2>
<p>Our actual adapter must do three things:  Obtain the Injector for our DSL, use the injector to obtain a properly initialized XtextResourceSet, and use the resource set to load the file.</p>
<h3>Obtaining the domain-specific language injector</h3>
<p>Update:  From the comments below, the easy/correct way to use injection in Eclipse RCP/plugin projects is to make use of the ExecutableExtensionFactory class.  If you specify, in plugin.xml, the name of your AdapterFactory class as &#8220;ExecutableExtensionFactory:AdapterFactory&#8221; then you do not need to manually get the injector.  You can just specify a private class variable using &#8220;@Inject<br />
	private XtextResourceSetProvider resourceSetProvider;&#8221;</p>
<p>When Xtext generates the .ui project, it creates an activator for this plugin that is responsible for creating and storing the Injector for this language.  We can retrieve the injector from this class using the getInjector method, which takes the name of the language as an argument and either returns the injector or null.  The code for this would be</p>
<pre class="brush: java; title: ; notranslate">final private static Injector injector = MyDslActivator.getInstance().getInjector(&quot;org.xtext.example.mydsl.MyDsl&quot;);</pre>
<h3>Loading the model</h3>
<p>This is very similar to the FAQ&#8217;s instructions, we just omit the creation of the injector and use the one that we retrieve from the activator.</p>
<pre class="brush: java; title: ; notranslate">
XtextResourceSet resourceSet = (XtextResourceSet) injector
	.getInstance(XtextResourceSetProvider.class)
	.get(file.getProject());
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
Resource resource = resourceSet.getResource(URI.createURI(file.getLocationURI().toString()),true);
DslModel model = (DslModel) resource.getContents().get(0);
</pre>
<h3>Putting it all together</h3>
<p>The only details we&#8217;re missing are relatively minor: error checking, transforming selections to files, and the format required by IAdapterFactory.  Our complete class ends up looking like this:</p>
<pre class="brush: java; title: ; notranslate">
package org.xtext.example.mydsl.util;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.resource.XtextResourceSet;
import com.google.inject.Injector;
import org.xtext.example.mydsl.myDsl.DslModel;
import org.xtext.example.mydsl.ui.internal.MyDslActivator;
/* Author: Robert Coop
* See: http://coopology.com/2011/06/easily-load-xtext-files-and-objects-in-eclipse-plugin-or-rcp-projects-using-adapters/
*/
@SuppressWarnings(&quot;rawtypes&quot;)
public class ModelLoadingAdapter implements IAdapterFactory {
	private static org.apache.log4j.Logger log = org.apache.log4j.Logger
		.getLogger(ModelLoadingAdapter.class);
	final private static Injector injector = MyDslActivator
		.getInstance().getInjector(&quot;org.xtext.example.mydsl.MyDsl&quot;);

	@Override
	public Object getAdapter(Object adaptableObject, Class adapterType) {
		if (adapterType == DslModel.class) {
			if (injector==null) {
				log.error(&quot;Could not obtain injector for MyDsl&quot;);
				return null;
			}

			if (adaptableObject instanceof ISelection) {
				final ISelection sel = (ISelection)adaptableObject;
				if (!(sel instanceof IStructuredSelection)) return null;
				final IStructuredSelection selection = (IStructuredSelection) sel;
				if (!(selection.getFirstElement() instanceof IFile))
					return null;
				adaptableObject = (IFile)selection.getFirstElement();
			}
			if (adaptableObject instanceof IFile) {
				final IFile file = (IFile)adaptableObject;
				if (!file.getFileExtension().toLowerCase().equals(&quot;mydsl&quot;)) return null;

				XtextResourceSet resourceSet = (XtextResourceSet) injector
					.getInstance(XtextResourceSetProvider.class)
					.get(file.getProject());
				resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
				Resource resource = resourceSet.getResource(URI.createURI(file.getLocationURI().toString()),true);
				DslModel model = (DslModel) resource.getContents().get(0);
				return model;
			}
		}

		return null;
	}

	@Override
	public Class[] getAdapterList() {
		return new Class[] { DslModel.class };
	}
}
</pre>
<h2>Finishing Up</h2>
<p>To tie everything together, we just need to modify plugin.xml to tell Eclipse about the adapter, then we can use it to load models easily.  Add the following to plugin.xml</p>
<pre class="brush: xml; title: ; notranslate">
&lt;extension point=&quot;org.eclipse.core.runtime.adapters&quot;&gt;
      &lt;factory adaptableType=&quot;org.eclipse.core.resources.IFile&quot; class=&quot;org.xtext.example.mydsl.util.ModelLoadingAdapter&quot;&gt;
         &lt;adapter type=&quot;org.xtext.example.mydsl.myDsl.DslModel&quot; /&gt;
      &lt;/factory&gt;
      &lt;factory adaptableType=&quot;org.eclipse.jface.viewers.ISelection&quot; class=&quot;org.xtext.example.mydsl.util.ModelLoadingAdapter&quot;&gt;
         &lt;adapter type=&quot;org.xtext.example.mydsl.myDsl.DslModel&quot; /&gt;
      &lt;/factory&gt;
&lt;/extension&gt;
</pre>
<h2>Using our new adapter</h2>
<p>Using the adapter from any plugin is very simple.  Given any IFile or ISelection object representing a mydsl file, we can obtain a DslModel using this code</p>
<pre class="brush: java; title: ; notranslate">
DslModel target = (DslModel)Platform.getAdapterManager().getAdapter(sourceObject, DslModel.class);
if (target==null) { /* Adaptation failed */ }
</pre>
<h1>Final Thoughts</h1>
<p>This technique can be applied to any adapter with the advantage of not needing direct dependencies on the plugin providing the adapter factory.  Hopefully this will prove useful to you either because it demonstrates a good way to load Xtext files or it demonstrates some of the adapter framework uses.  Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2011/06/easily-load-xtext-files-and-objects-in-eclipse-plugin-or-rcp-projects-using-adapters/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Howto:  Mount your Android SD card under linux via wifi</title>
		<link>http://coopology.com/2011/05/howto-mount-your-android-sd-card-under-linux-via-wifi/</link>
		<comments>http://coopology.com/2011/05/howto-mount-your-android-sd-card-under-linux-via-wifi/#comments</comments>
		<pubDate>Mon, 16 May 2011 22:24:20 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[samba]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=76</guid>
		<description><![CDATA[This guide will get you from having an Android phone with a Samba sharing app installed (such as the one I currently use: https://market.android.com/details?id=com.funkyfresh.samba) and an Ubuntu (or any generic Linux) machine with Samba installed to being able to mount your SD card via WiFi. We will do this by: setting the computer to use [...]]]></description>
				<content:encoded><![CDATA[<p>This guide will get you from having an Android phone with a Samba sharing app installed (such as the one I currently use: https://market.android.com/details?id=com.funkyfresh.samba) and an Ubuntu (or any generic Linux) machine with Samba installed to being able to mount your SD card via WiFi.  We will do this by: setting the computer to use netbios names for IP address resolution, testing the mount with mount.cifs, and then adding a permanent entry to /etc/fstab.</p>
<p>My setup:  HTC Inspire 4g, rooted running Cyanomodgen 7; Samba Filesharing on Android app (from marketplace, free, version 110130-market); Ubuntu 11.04 (with samba package installed)</p>
<h1>Prerequisites</h1>
<p>First, you need a Samba server app for your phone (I&#8217;m using https://market.android.com/details?id=com.funkyfresh.samba, which seems to work well enough), then you need to go into your Samba app on the Android and set a netbios name for your phone (e.g. I&#8217;m using &#8220;bcoop-android&#8221;, so replace that with whatever name you set). For security reasons, you also want to set a user (e.g. &#8220;bcoop&#8221;) and a password required to access the share.  If you have the option, you need to give the shared directory a name (on my app the name is fixed as &#8220;sdcard&#8221;).  You&#8217;ll also need to make sure that your computer has a samba client installed (this can be installed in Ubuntu by installing the smbclient package).</p>
<h1>Using Netbios for IP address resolution</h1>
<p>Secondly, we need to tell the computer to try to perform DNS lookups using netbios names if all else fails.  You can tell if you need this step by running the command &#8220;ping bcoop-android&#8221; (making sure your phone is connected to the same network as the desktop via wireless and that the Samba app on the phone is running).  If you receive a &#8220;unknown host&#8221; error, then the desktop is not able to look up names via netbios, which is a simple fix.  Run the command</p>
<pre class="brush: bash; title: ; notranslate">sudo gedit /etc/nsswitch.conf</pre>
<p>and look for the line that starts with <code>hosts:</code>.  At the end of this line, add <code>wins</code>.  You should end up with the line looking something like:<br />
<code>hosts:          files [...] wins</code></p>
<p>This will tell your machine to use Netbios name lookup if all else fails.  You want to make sure to add wins at the end of the string of methods so that it does not check this before other methods.  Save the file and close gedit.</p>
<p><em>Update: </em>After an hour or so, my connection started timing out and I couldn&#8217;t remount the share.  I was confused about what was going on, but noticed that when I tried to ping the netbios name I suddenly got a response from a 209.XXX.XXX.XXX IP address, and not from my phone.  Long story short, it turns out that my lovely ISP (Comcast) has a policy of hijacking domain names that don&#8217;t exist so that they can redirect browsers to a search page with ads.  A side effect of this is that all DNS resolution requests are answered, regardless of whether they exist or not.  This causes the computer to assume that the request has been answered and not to look at the wins netbios name for a possible IP address.  The solution to this was to put wins just before the dns entry in the hosts line.</p>
<p>You should now be able to run the ping command and have the computer try to ping an IP address (it doesn&#8217;t matter if you receive a response or not, we&#8217;re just checking to see that the computer can translate the netbios name to the ip address of the phone).</p>
<p><em>Note:</em> If you&#8217;re not able to get this to work, you can still move on, but just use the phone&#8217;s IP address instead of netbios name for the server.  It will be necessary to either continually change the IP address to the phone&#8217;s IP, tell your router to assign the phone the same IP address always, or to use some other method to ensure that the phone&#8217;s IP address remains correct.</p>
<h1>Testing things out: Temporarily mounting the phone</h1>
<p>To test things out, we need to create a directory to use as a mount point.  Run the command <code>sudo mkdir /media/android</code> to do this (using a different directory if you&#8217;d prefer).  Now, we want to manually mount the phone in this directory.  There are a couple different ways to do this, depending on how you want the file permissions to work.  I&#8217;ll list the different commands you can use, and you can see the below section for further discussion about which might be best.  You will need to modify this command with some specifics for your setup, see the section immediately afterwards.</p>
<h3>To not allow any other users to access your files (the recommended method)</h3>
<pre class="brush: bash; title: ; notranslate">sudo mount -t cifs //bcoop-android/sdcard/ /media/android  -o user=bcoop,uid=bcoop,gid=bcoop,nounix,file_mode=0770,dir_mode=0770</pre>
<h3>To avoid using &#8216;nounix&#8217;, but allow others to read (but not write) your files</h3>
<pre class="brush: bash; title: ; notranslate">sudo mount -t cifs //bcoop-android/sdcard/ /media/android  -o user=bcoop,uid=nobody,gid=bcoop</pre>
<h3>To disable permission checking entirely (anyone can read/write your files)</h3>
<pre class="brush: bash; title: ; notranslate">sudo mount -t cifs //bcoop-android/sdcard/ /media/android  -o user=bcoop,noperm</pre>
<h2>For all methods</h2>
<p>You&#8217;ll need to replace some parts of this command with your setup information:</p>
<ul>
<li>//bcoop-android/sdcard should be your phone&#8217;s netbios name (or IP address) followed by the share name:  //NETBIOS_NAME/SHARE_NAME</li>
<li>/media/android should be your mount point directory</li>
<li>user=bcoop should be the user name that you set up on the phone for the Samba share:  user=PHONE_SAMBA_USER</li>
<li>uid=bcoop,gid=bcoop should be your computer user&#8217;s name and group (these are likely the same on a typical setup): uid=COMPUTER_USER,gid=COMPUTER_GROUP</li>
<li>uid=nobody should be the name of a fake user on your computer</li>
</ul>
<p>After running the command, you&#8217;ll need to enter your sudo password, then your password for the phone&#8217;s samba share.  If all goes well, you should see no error messages then be able to run</p>
<pre class="brush: bash; title: ; notranslate">ls /media/android</pre>
<p>and see the contents of your phone.  In that case, you&#8217;re ready to set the share up permanently.  If you don&#8217;t mind running the mount command every time, you can just stop here.</p>
<h2>Notes regarding file permissions</h2>
<p><em>(This section can safely be skipped if you&#8217;re not interested in knowing any background about how things work behind the scene&#8230;)</em></p>
<p>When I was trying this out, the thing that took the most amount of time to figure out is the file permissions used on the phone.  When mounting a SMB (Samba) share, there are a few options when it comes to file permissions: accept the uid/gid (user and group owner id) from the phone, force the uid/gid to map to specific users/groups on the computer, or ignore the permissions reported by the phone entirely.</p>
<p>The most convenient option is to ignore the permissions entirely, but it is also the least secure: it would allow any program or user on your computer to have full access to the files on the phone when it is mounted.  The typical approach is to map the user and group from the phone to be equivalent to your computer user.  However, I noticed something odd about the way the permissions are reported on my setup.  I&#8217;m not positive if this is just some eccentricity of my specific setup, but the permissions reported by my phone have the user set with no read/write/execute permission, the group set with full read/write/execute permission, and everyone else set with just read/execute permission.  (For comparison, the typical setup is user with full permission, group with either full or read/execute permission, and everyone else with either read/execute permission or no permissions at all.)  So, if one maps the uid/gid to the computer user&#8217;s uid/gid then the result is that the current user will have no permissions at all.  One solution is to map the gid to the computer user&#8217;s gid, but to map the uid to some fake/unused user (I used &#8216;nobody&#8217;, which is a standard and safe bet).  This results in you having full access to the phone and other users being able to read but not modify the contents, and has the advantage of retaining the maximum amount of functionality (i.e. it doesn&#8217;t disable some behind-the-scenes filesystem functionality).  An alternative solution is to disable &#8216;CIFS Unix Extensions&#8217; and manually set the file/directory permissions as well as the uid/gid.  This has the advantage of allowing you to explicitly remove read permission from other users if desired, but has the possible disadvantage of disabling something that is required (though I have no idea if that is likely to happen or even really possible; please leave a comment if you know something about this that I don&#8217;t).</p>
<h1>Setting things up permanently</h1>
<p>To permanently save these settings, we need to create a credentials file to safely hold your samba share&#8217;s username and password and we also need to add the mount information to /etc/fstab so that the system is aware of the settings.  To safely store your credentials, we want to create a file that only your user can read which holds your username and password.  To do that, run</p>
<pre class="brush: bash; title: ; notranslate">gedit ~/.android_credentials</pre>
<p>and add the following to this file:</p>
<pre>username=YOUR_USERNAME
password=YOUR_PASSWORD</pre>
<p>Save the file, close gedit, and run the command</p>
<pre class="brush: bash; title: ; notranslate">chmod 0600 ~/.android_credentials</pre>
<p>to make sure that only you can read that file.</p>
<p>Now, to save the information into fstab, run</p>
<pre class="brush: bash; title: ; notranslate">sudo gedit /etc/fstab</pre>
<p>and add the following line to the file:</p>
<pre class="brush: plain; title: ; notranslate">//bcoop-android/sdcard/	/media/android	cifs	credentials=/home/bcoop/.android_credentials,uid=bcoop,gid=bcoop,nounix,file_mode=0770,dir_mode=0770,user,noauto	0	0</pre>
<p>(Note that you may need to change the options if you&#8217;d like something other than the recommended method from above, and you&#8217;ll need to replace credentials=/home/bcoop/.android_credentials with the correct path to your credentials file.  Also note that the trailing slash on //bcoop-android/sdcard/ is very important.  If you forget this trailing slash then you cannot unmount the share as a regular user.)</p>
<p>&nbsp;</p>
<p>If all goes well you should now be able to run</p>
<pre class="brush: bash; title: ; notranslate">mount /media/android</pre>
<p>and access your phone&#8217;s SD card contents in /media/android.  Remember that you need to unmount this by running</p>
<pre class="brush: bash; title: ; notranslate">umount /media/android</pre>
<p>when done.  Enjoy!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2011/05/howto-mount-your-android-sd-card-under-linux-via-wifi/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using Log4J in Eclipse RCP (and forcing all other plugins to use it too!)</title>
		<link>http://coopology.com/2011/04/using-log4j-in-eclipse-rcp-and-forcing-all-other-plugins-to-use-it-too/</link>
		<comments>http://coopology.com/2011/04/using-log4j-in-eclipse-rcp-and-forcing-all-other-plugins-to-use-it-too/#comments</comments>
		<pubDate>Tue, 19 Apr 2011 14:12:30 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[log4j]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[rcp]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=64</guid>
		<description><![CDATA[There are many resources out there that describe the process (and headache!) of using Apache&#8217;s Log4J http://logging.apache.org/log4j/ logging framework within an Eclipse rich client platform (RCP) project.  After digesting all the resources that the internet has to offer (my favorite links at the end) and adding log4j to the RCP project that I am currently working [...]]]></description>
				<content:encoded><![CDATA[<p>There are many resources out there that describe the process (and headache!) of using Apache&#8217;s Log4J <a href="http://logging.apache.org/log4j/">http://logging.apache.org/log4j/</a> logging framework within an Eclipse rich client platform (RCP) project.  After digesting all the resources that the internet has to offer (my favorite links at the end) and adding log4j to the RCP project that I am currently working on, the most common problems seem to be:</p>
<ul>
<li>Getting log4j into the environment</li>
<li>Classloader errors caused by different versions of log4j classes being loaded by different plugins</li>
<li>Problems accessing/locating the log4j.properties file</li>
</ul>
<p>I also had a problem where I wanted to use <em>only</em> Log4J for logging, so I wanted to be sure that all log messages from all plugins in my RCP project were being picked up by the logging framework.</p>
<p>A log4j bundle is available in the Eclipse Orbit builds (<a href="http://download.eclipse.org/tools/orbit/downloads/drops/R20100519200754/">http://download.eclipse.org/tools/orbit/downloads/drops/R20100519200754/</a>); so, actually getting log4j into the RCP environment just involves downloading that bundle and requiring it in the RCP project.  However, there is still the potential for classloader problems and dependency issues when multiple plugins are developed as part of a project and each brings its own log4j package to the table.  The solution is somewhat simple:  designate one plugin project to initialize and supply the logging bundle, and have all the other plugins rely on this.  The choice of the master plugin is usually fairly simple;  for my project it is the RCP project itself, which actually initializes the application environment and has a dependency on the feature plugins.  That master plugin should have the log4j as a bundle dependency (Required Plug-ins), and the other plugins should simply list org.apache.log4j as an imported package.</p>
<p>To configure the logger using a .properties file, a bit of additional work is needed.  Many resources seem to imply there is a way to accomplish this that results in Log4j automatically loading the properties (because it will search for the log4j.properties file at startup if no config is provided), but I wasn&#8217;t able to get that to work and didn&#8217;t want to spend that much time one it.  My solution was to include log4j.properties in the project directory of the RCP plugin, <em>make sure</em> to add this file to the binary build under build configuration, and initialize the logger using this properties file when the application starts.  This initialization is done by adding the following to your Activator class in the master plugin:</p>
<pre class="brush: java; title: ; notranslate">
import java.net.URL;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.eclipse.core.runtime.FileLocator;

final private static Logger log = Logger.getLogger(Activator.class);

public void start(final BundleContext context) throws Exception {
	// [...]
	// Setup logging
	URL confURL = getBundle().getEntry(&quot;log4j.properties&quot;);
	PropertyConfigurator.configure( FileLocator.toFileURL(confURL).getFile());
	log.info(&quot;Logging using log4j and configuration &quot; + FileLocator.toFileURL(confURL).getFile());
	hookPluginLoggers(context); // You need to add this method to hook other plugins, described later...
	// [...]
}</pre>
<p>That will load and configure the logger using the properties file.  The properties file can be modified without needing a re-compile.  To actually log from any class in any plugin now, just add the following:</p>
<pre class="brush: java; title: ; notranslate">

public class MyClassInAnyPlugin {
	private static org.apache.log4j.Logger log = org.apache.log4j.Logger
			.getLogger(MyClassInAnyPlugin.class);
	void someMethod() {
		log.debug(&quot;A debug message&quot;);
		log.warn(&quot;A warning message&quot;);
	}
}
</pre>
<p>A description of all the log methods and levels can be found in the log4j docs at the official site.  At this point, you should have logging up and running in your project, but we have yet to ensure that _all_ log messages will be sent through log4j.  In particular, other Eclipse plugins use the Eclipse logging framework; without special hooking, these messages will be missed by log4j.  To accomplish that, I used the PluginLogListener class described at <a href="http://www.ibm.com/developerworks/library/os-eclog/">http://www.ibm.com/developerworks/library/os-eclog/</a> in order to add a log listener to each loaded plugin.  To add a listener for each plugin, we need to add the following method (and field):</p>
<pre class="brush: java; title: ; notranslate">
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.Platform;

final private List&lt;PluginLogListener&gt; pluginLogHooks = new ArrayList&lt;PluginLogListener&gt;();

// Hook all loaded bundles into the log4j framework
private void hookPluginLoggers(final BundleContext context) {
	for (Bundle bundle : context.getBundles()){
		ILog pluginLogger = Platform.getLog(bundle);
		pluginLogHooks.add(new PluginLogListener(pluginLogger,
				Logger.getLogger(bundle.getSymbolicName())));
		log.trace(&quot;Added logging hook for bundle: &quot; + bundle.getSymbolicName());
	}
}
</pre>
<p>Even though we don&#8217;t ever need to read the contents of the pluginLogHooks list, it&#8217;s very important to store the PluginLogListener instances we create; without persistent storage they will be reclaimed by the garbage collection process and their logging hooks will be removed.  After adding this method, when your application starts up, you should see something like this:</p>
<pre>0    [main] INFO  com.rtsync.devs.rcp.Activator  (Activator.java:76): Logging using log4j and configuration [...]/my.project.rcp/log4j.properties
3    [main] TRACE com.rtsync.devs.rcp.Activator  (Activator.java:103): Added logging hook for bundle: org.eclipse.osgi
4    [main] TRACE com.rtsync.devs.rcp.Activator  (Activator.java:103): Added logging hook for bundle: com.ibm.icu
5    [main] TRACE com.rtsync.devs.rcp.Activator  (Activator.java:103): Added logging hook for bundle: org.apache.commons.logging
5    [main] TRACE com.rtsync.devs.rcp.Activator  (Activator.java:103): Added logging hook for bundle: org.eclipse.ant.core
6    [main] TRACE com.rtsync.devs.rcp.Activator  (Activator.java:103): Added logging hook for bundle: org.eclipse.compare.core
6    [main] TRACE com.rtsync.devs.rcp.Activator  (Activator.java:103): Added logging hook for bundle: org.eclipse.core.commands[...]</pre>
<p>Now, any regular log message created by any plugin in your RCP project will be caught and interpreted by the log4j framework, which looks like this:</p>
<pre>!ENTRY org.eclipse.core.resources 2 10035 2011-04-19 10:02:03.710!MESSAGE The workspace exited with unsaved changes in the previous session; refreshing workspace to recover changes.
819  [main] WARN  org.eclipse.core.resources  (PluginLogListener.java:91): org.eclipse.core.resources - 10035 - The workspace exited with unsaved changes in the previous session; refreshing workspace to recover changes.</pre>
<p>Note that as long as the -consoleLog option is used with Eclipse (which is added by default to your run/debug configurations) you&#8217;ll see the original plugin log message and then the Log4J log message.  Now you have the entire environment using the same logging framework, whether it wants to or not!</p>
<p>Good in-depth explanations of logging in Eclipse RCP:</p>
<ul>
<li><a href="http://www.ibm.com/developerworks/library/os-eclog/">http://www.ibm.com/developerworks/library/os-eclog/</a></li>
<li><a href="http://www.eclipsezone.com/articles/franey-logging/">http://www.eclipsezone.com/articles/franey-logging/</a></li>
</ul>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2011/04/using-log4j-in-eclipse-rcp-and-forcing-all-other-plugins-to-use-it-too/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Increase your productivity in Linux by 200% or more with a single command!</title>
		<link>http://coopology.com/2011/03/increase-productivity-in-linux-with-one-comman/</link>
		<comments>http://coopology.com/2011/03/increase-productivity-in-linux-with-one-comman/#comments</comments>
		<pubDate>Tue, 22 Mar 2011 17:06:34 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[reddit]]></category>
		<category><![CDATA[slashdot]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=59</guid>
		<description><![CDATA[I found an amazing way to increase productivity by a large amount with one simple command! Simply run this command: sudo bash -c "echo -e \"### Sorry guys, I'll return when I have less deadlines\n127.0.0.1 reddit.com\n127.0.0.1 www.reddit.com\n127.0.0.1 slashdot.org\" &#62;&#62; /etc/hosts" I&#8217;m not quite sure what it is about this, but I immediately noticed work was [...]]]></description>
				<content:encoded><![CDATA[<p>I found an amazing way to increase productivity by a large amount with one simple command!  Simply run this command:<br />
<code><br />
sudo bash -c "echo -e \"###  Sorry guys, I'll return when I have less deadlines\n127.0.0.1 reddit.com\n127.0.0.1 www.reddit.com\n127.0.0.1 slashdot.org\" &gt;&gt; /etc/hosts"<br />
</code></p>
<p>I&#8217;m not quite sure what it is about this, but I immediately noticed work was getting done much sooner!</p>
<p><em>A note for those not familiar with hosts and other sarcasm-deficient folks: </em>This command makes the computer use localhost for the IP address of Reddit and slashdot, preventing you from accessing those sites.  In a pinch, this command can help people like me that suffer from a lack of self-control when it comes to online distractions&#8230;  I&#8217;ll return some day&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2011/03/increase-productivity-in-linux-with-one-comman/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>BSEC 2011 Poster</title>
		<link>http://coopology.com/2011/03/bsec-2011-poster/</link>
		<comments>http://coopology.com/2011/03/bsec-2011-poster/#comments</comments>
		<pubDate>Thu, 17 Mar 2011 02:23:21 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[publications]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=54</guid>
		<description><![CDATA[A poster that I presented at the 3rd annual Oak Ridge National Lab Biomedical Science and Engineering Conference. Functional analysis and prediction of tumor growth Abstract: Based on a modified logistic model, simulated growth trajectories of brain tumors are prepared. Simulation trajectories track the number of cancer cells within each 3-dimensional area (voxel) in a [...]]]></description>
				<content:encoded><![CDATA[<p>A poster that I presented at the 3rd annual Oak<br />
Ridge National Lab Biomedical Science and Engineering Conference.</p>
<p><a href="http://coopology.com/wp-content/uploads/2011/03/vuiis_2011_poster.pdf">Functional analysis and prediction of tumor growth</a></p>
<p><!-- 		@page { margin: 0.79in } 		P { margin-bottom: 0.08in } -->Abstract:</p>
<p>Based on a modified logistic model, simulated growth trajectories of brain tumors are prepared. Simulation trajectories track the number of cancer cells within each 3-dimensional area (voxel) in a 128&#215;128 grid. A novel functional analysis procedure is developed which uses a genetic algorithm combined with systems theory principles in order to determine, for a given voxel, which neighboring voxels have the greatest predictive power when compared to the neighborhood as a whole. The predictive power of these groups, or functional masks, are given a fitness measure based on their relative Shannon entropy and the frequency with which observations occur.</p>
<p>This functional analysis procedure is performed over the simulated trajectories; the functional mask discovered is used to perform growth prediction. The functional mask discovered is used as the basis for probabilistic parameter estimation and prediction of tumor growth. In this fashion, growth predictions are made with significant accuracy in a very general fashion; no domain knowledge about tumor growth or the model being used is incorporated in the analysis and prediction procedure.</p>
<p>Robert Coop is a PhD student at the University of Tennessee in the Machine Intelligence Laboratory. His research interests include machine learning, artificial intelligence algorithms, genetic algorithms, and discrete event system simulation. His work is primarily focused on machine learning methodologies as applied to abstract non-linear domains, and other applications of adaptive optimization methods to problem domains with high dimensionality. Robert Coop holds a B.S. in computer science and a M.S. in electrical engineering from the University of Tennessee and is a student member of the IEEE.</p>
<p>James Nutaro is a member of the Modeling and Simulation Group in the Computational Sciences and Engineering Division at Oak Ridge National Laboratory. His research interests include discrete event and hybrid systems, parallel discrete event simulation, modeling methodologies, and event based numerical methods. This work covers a broad range of application domains, with particular emphasis on control systems operating over IP-based communication links, communication and control in electric power systems, simulating of large transportation systems, and modeling and simulation of wireless communication networks. James Nutaro has authored or coauthored over 25 papers in the open literature. He holds a B.S., M.S., and Ph.D. in computer engineering from the University of Arizona and is a member of the IEEE.</p>
]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2011/03/bsec-2011-poster/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Use an Accurate Satellite View of the Earth as your GNOME Background</title>
		<link>http://coopology.com/2010/10/use-an-accurate-satellite-view-of-the-earth-as-your-gnome-background/</link>
		<comments>http://coopology.com/2010/10/use-an-accurate-satellite-view-of-the-earth-as-your-gnome-background/#comments</comments>
		<pubDate>Sun, 31 Oct 2010 21:24:58 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[background]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[desktop]]></category>
		<category><![CDATA[gnome]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=46</guid>
		<description><![CDATA[This site provides an accurate satellite view of the Earth; you can see the current areas that are in sunlight and darkness, as well as being able to see the current weather patterns (updated from actual satellite weather imagery). Here&#8217;s a script that will download the latest image and set it as your GNOME background. [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://coopology.com/wp-content/uploads/2010/10/earth.jpg"><img class="alignnone size-medium wp-image-50" title="earth" src="http://coopology.com/wp-content/uploads/2010/10/earth-300x166.jpg" alt="" width="300" height="166" /></a></p>
<p><a href="http://coopology.com/wp-content/uploads/2010/10/earth.jpg"></a><a href="http://www.die.net/earth/">This site</a> provides an accurate satellite view of the Earth;  you can see the current areas that are in sunlight and darkness, as well as being able to see the current weather patterns (updated from actual satellite weather imagery).  Here&#8217;s a script that will download the latest image and set it as your GNOME background.<br />
<span id="more-46"></span><br />
Note:  You can set this script as a cron job and have the background update automatically, but be courteous.  The site hosting this image will not be able to continue to do so if everyone sets their computer to update every 5 minutes.  The actual site only updates once every few hours, so I would recommend not setting the update to more often than once every 2/3 hours or so.</p>
<p>Here&#8217;s the script: update_earth_background</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
gconftool-<span style="color: #000000;">2</span> <span style="color: #660033;">--type</span> string <span style="color: #660033;">--set</span> <span style="color: #000000; font-weight: bold;">/</span>desktop<span style="color: #000000; font-weight: bold;">/</span>gnome<span style="color: #000000; font-weight: bold;">/</span>background<span style="color: #000000; font-weight: bold;">/</span>picture_options <span style="color: #ff0000;">&quot;none&quot;</span>
gconftool-<span style="color: #000000;">2</span> <span style="color: #660033;">--type</span> string <span style="color: #660033;">--set</span> <span style="color: #000000; font-weight: bold;">/</span>desktop<span style="color: #000000; font-weight: bold;">/</span>gnome<span style="color: #000000; font-weight: bold;">/</span>background<span style="color: #000000; font-weight: bold;">/</span>picture_filename <span style="color: #ff0000;">&quot;&quot;</span>
<span style="color: #c20cb9; font-weight: bold;">wget</span>  http:<span style="color: #000000; font-weight: bold;">//</span>static.die.net<span style="color: #000000; font-weight: bold;">/</span>earth<span style="color: #000000; font-weight: bold;">/</span>mercator<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">1600</span>.jpg <span style="color: #660033;">-O</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>bcoop<span style="color: #000000; font-weight: bold;">/</span>Pictures<span style="color: #000000; font-weight: bold;">/</span>Backgrounds<span style="color: #000000; font-weight: bold;">/</span>earth.jpg
gconftool-<span style="color: #000000;">2</span> <span style="color: #660033;">--type</span> string <span style="color: #660033;">--set</span> <span style="color: #000000; font-weight: bold;">/</span>desktop<span style="color: #000000; font-weight: bold;">/</span>gnome<span style="color: #000000; font-weight: bold;">/</span>background<span style="color: #000000; font-weight: bold;">/</span>picture_filename <span style="color: #ff0000;">&quot;/home/bcoop/Pictures/Backgrounds/earth.jpg&quot;</span>
gconftool-<span style="color: #000000;">2</span> <span style="color: #660033;">--type</span> string <span style="color: #660033;">--set</span> <span style="color: #000000; font-weight: bold;">/</span>desktop<span style="color: #000000; font-weight: bold;">/</span>gnome<span style="color: #000000; font-weight: bold;">/</span>background<span style="color: #000000; font-weight: bold;">/</span>picture_options <span style="color: #ff0000;">&quot;scaled&quot;</span></pre></td></tr></table></div>

<p>You&#8217;ll need to change the path to be something that is valid for your user and machine, but this should give you all the information you need to make it happen&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2010/10/use-an-accurate-satellite-view-of-the-earth-as-your-gnome-background/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Reboot or Hibernate into Windows from Ubuntu Easily</title>
		<link>http://coopology.com/2010/10/reboot-or-hibernate-into-windows-from-ubuntu-easily/</link>
		<comments>http://coopology.com/2010/10/reboot-or-hibernate-into-windows-from-ubuntu-easily/#comments</comments>
		<pubDate>Sat, 30 Oct 2010 20:42:43 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[dual boot]]></category>
		<category><![CDATA[hibernate]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[ubuntu]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=38</guid>
		<description><![CDATA[It&#8217;s often the case that I&#8217;m working on something in Ubuntu and need to switch over to Windows. For whatever reason, I got it in my head that it was too difficult to select hibernate or reboot from the power menu, wait for the system to power down, select Windows from the boot menu list, [...]]]></description>
				<content:encoded><![CDATA[<p>It&#8217;s often the case that I&#8217;m working on something in Ubuntu and need to switch over to Windows.  For whatever reason, I got it in my head that it was too difficult to select hibernate or reboot from the power menu, wait for the system to power down, select Windows from the boot menu list, and wait for Windows to boot up.  I wanted to be able to click on an icon, go get a sandwich, and walk back to a Windows login.</p>
<p>So, here are two scripts that accomplish this.  When run, they will locate the boot entry for your Windows system, select that as the default boot entry, and either reboot or hibernate (with a restart after hibernation).<br />
<span id="more-38"></span><br />
There are a couple preliminary things that must be done to allow this to happen.  First, the hibernate script requires &#8216;s2disk&#8217; in order to be able to instruct the system to hibernate and reboot afterwards.  This is in the &#8216;uswsusp&#8217; package and can be installed with <code>sudo apt-get install uswsusp</code>.</p>
<p>Secondly, in order to avoid needing a password prompt to reboot the machine, you need to add permissions for the user to run some commands without needing a password.  This is accomplished by adding some lines to the /etc/sudoers file.  <em>Note: <strong>Editing the /etc/sudoers file is a potentially dangerous thing.</strong> If you get any reported syntax errors from visudo when you save and exit the editor, do not ignore them!  If you mess up the /etc/sudoers file you may end up with a system that will not allow you to use sudo, and this can only be fixed by booting from a live-cd.</em></p>
<p>To edit the sudoers file, run <code>sudo visudo</code>.  It is very important that you use this method;  it checks the syntax of the file when you save it, and will prevent you from messing up your ability to use sudo (which can happen if you ignore error messages or edit /etc/sudoers directly).</p>
<p>So, open up the file and add these lines</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="text" style="font-family:monospace;"># Needed for hibernate script
user ALL=NOPASSWD: /usr/sbin/grub-reboot
user ALL=NOPASSWD: /usr/sbin/s2disk
user ALL=NOPASSWD: /sbin/reboot</pre></td></tr></table></div>

<p>This will allow &#8216;user&#8217; to run those three commands with sudo without needing a password.  Then, put the following scripts into /usr/local/bin</p>
<p>reboot_to_windows</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #007800;">WINDOWS_ENTRY</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">grep</span> menuentry <span style="color: #000000; font-weight: bold;">/</span>boot<span style="color: #000000; font-weight: bold;">/</span>grub<span style="color: #000000; font-weight: bold;">/</span>grub.cfg  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">--line-number</span> Windows<span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">MENU_NUMBER</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$WINDOWS_ENTRY</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/:.*//&quot;</span><span style="color: #000000; font-weight: bold;">`</span> - <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #660033;">-n</span> grub-reboot <span style="color: #007800;">$MENU_NUMBER</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> reboot</pre></td></tr></table></div>

<p>hibernate_to_windows</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #007800;">WINDOWS_ENTRY</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">grep</span> menuentry <span style="color: #000000; font-weight: bold;">/</span>boot<span style="color: #000000; font-weight: bold;">/</span>grub<span style="color: #000000; font-weight: bold;">/</span>grub.cfg  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">--line-number</span> Windows<span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">MENU_NUMBER</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#40;</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #007800;">$WINDOWS_ENTRY</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">sed</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;s/:.*//&quot;</span><span style="color: #000000; font-weight: bold;">`</span> - <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #660033;">-n</span> grub-reboot <span style="color: #007800;">$MENU_NUMBER</span>
gnome-screensaver-command <span style="color: #660033;">--lock</span>
<span style="color: #c20cb9; font-weight: bold;">sudo</span> <span style="color: #660033;">-n</span> s2disk <span style="color: #660033;">--parameter</span> <span style="color: #ff0000;">&quot;shutdown method=reboot&quot;</span></pre></td></tr></table></div>

<p>Then, all you need to do is add a launcher icon to the desktop, and when run the system will shutdown or hibernate, set the default entry to Windows, and reboot!</p>
]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2010/10/reboot-or-hibernate-into-windows-from-ubuntu-easily/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Converting WMA files to MP3 on Linux (specifically Ubuntu) and retain tag information</title>
		<link>http://coopology.com/2010/10/converting-wma-files-to-mp3-on-linux-specifically-ubuntu/</link>
		<comments>http://coopology.com/2010/10/converting-wma-files-to-mp3-on-linux-specifically-ubuntu/#comments</comments>
		<pubDate>Fri, 29 Oct 2010 15:59:21 +0000</pubDate>
		<dc:creator>Bobby Coop</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[conversion]]></category>
		<category><![CDATA[lame]]></category>
		<category><![CDATA[mp3]]></category>
		<category><![CDATA[mplayer]]></category>
		<category><![CDATA[mutagen]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[wma]]></category>

		<guid isPermaLink="false">http://coopology.com/?p=5</guid>
		<description><![CDATA[I recently needed to convert a bunch of (DRM-free) WMA files to MP3 format on Ubuntu, and there&#8217;s no good tool out there to do it.  There are plenty of tutorials that tell you how to convert from WMA to WAV with Lame, then from WAV to MP3 with mplayer, but none of these tutorial [...]]]></description>
				<content:encoded><![CDATA[<p>I recently needed to convert a bunch of (DRM-free) WMA files to MP3 format on Ubuntu, and there&#8217;s no good tool out there to do it.  There are plenty of tutorials that tell you how to convert from WMA to WAV with Lame, then from WAV to MP3 with mplayer, but none of these tutorial talk about how that will cause you to lose all the WMA artist/album/title data.  I needed a tool that would keep the tagged data;  so, I made one.  It requires mplayer, lame, and mutagen-inspect, all of which are available from aptitude.</p>
<p>So, here&#8217;s my script: wma2mp3<br />
<span id="more-5"></span><br />
Usage: wma2mp3 in-wma out-mp3</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #007800;">IN</span>=<span style="color: #007800;">$1</span>
<span style="color: #007800;">O</span>=<span style="color: #800000;">${2-${IN%\.wma}</span><span style="color: #7a0874; font-weight: bold;">&#125;</span>
<span style="color: #007800;">OUT</span>=<span style="color: #800000;">${O%\.mp3}</span>.mp3
<span style="color: #007800;">TEMP</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">mktemp</span> <span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>convert.XXXXX.wav<span style="color: #000000; font-weight: bold;">`</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> Converting <span style="color: #000000; font-weight: bold;">\&quot;</span><span style="color: #007800;">$IN</span><span style="color: #000000; font-weight: bold;">\&quot;</span> to <span style="color: #000000; font-weight: bold;">\&quot;</span><span style="color: #007800;">$TEMP</span><span style="color: #000000; font-weight: bold;">\&quot;</span>
<span style="color: #c20cb9; font-weight: bold;">mplayer</span> <span style="color: #660033;">-vc</span> null <span style="color: #660033;">-vo</span> null <span style="color: #660033;">-ao</span> pcm:waveheader:fast:<span style="color: #007800;">file</span>=<span style="color: #000000; font-weight: bold;">%`</span><span style="color: #c20cb9; font-weight: bold;">expr</span> length <span style="color: #ff0000;">&quot;<span style="color: #007800;">$TEMP</span>&quot;</span><span style="color: #000000; font-weight: bold;">`%</span><span style="color: #ff0000;">&quot;<span style="color: #007800;">$TEMP</span>&quot;</span>  <span style="color: #ff0000;">&quot;<span style="color: #007800;">$IN</span>&quot;</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">echo</span> Converting <span style="color: #007800;">$TEMP</span> to <span style="color: #007800;">$OUT</span>
<span style="color: #c20cb9; font-weight: bold;">lame</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$TEMP</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$OUT</span>&quot;</span>
<span style="color: #c20cb9; font-weight: bold;">rm</span> <span style="color: #007800;">$TEMP</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> Fixing ID3 tags
<span style="color: #007800;">ARTIST</span>=<span style="color: #000000; font-weight: bold;">`</span>mutagen-inspect <span style="color: #ff0000;">&quot;<span style="color: #007800;">$IN</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span>  <span style="color: #c20cb9; font-weight: bold;">grep</span> WM<span style="color: #000000; font-weight: bold;">/</span>AlbumArtist  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-E</span> <span style="color: #660033;">--only-matching</span> <span style="color: #ff0000;">&quot;[^=]+$&quot;</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">ALBUM</span>=<span style="color: #000000; font-weight: bold;">`</span>mutagen-inspect <span style="color: #ff0000;">&quot;<span style="color: #007800;">$IN</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span>    <span style="color: #c20cb9; font-weight: bold;">grep</span> WM<span style="color: #000000; font-weight: bold;">/</span>AlbumTitle  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-E</span> <span style="color: #660033;">--only-matching</span> <span style="color: #ff0000;">&quot;[^=]+$&quot;</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">NUM</span>=<span style="color: #000000; font-weight: bold;">`</span>mutagen-inspect <span style="color: #ff0000;">&quot;<span style="color: #007800;">$IN</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span>    <span style="color: #c20cb9; font-weight: bold;">grep</span> WM<span style="color: #000000; font-weight: bold;">/</span>TrackNumber  <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-E</span> <span style="color: #660033;">--only-matching</span> <span style="color: #ff0000;">&quot;[^=]+$&quot;</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #007800;">TITLE</span>=<span style="color: #000000; font-weight: bold;">`</span>mutagen-inspect <span style="color: #ff0000;">&quot;<span style="color: #007800;">$IN</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span>   <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-E</span> <span style="color: #ff0000;">&quot;^Title=&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-E</span> <span style="color: #660033;">--only-matching</span> <span style="color: #ff0000;">&quot;[^=]+$&quot;</span><span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> Artist = <span style="color: #000000; font-weight: bold;">\&quot;</span><span style="color: #007800;">$ARTIST</span><span style="color: #000000; font-weight: bold;">\&quot;</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> Album = <span style="color: #000000; font-weight: bold;">\&quot;</span><span style="color: #007800;">$ALBUM</span><span style="color: #000000; font-weight: bold;">\&quot;</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> Track Number = <span style="color: #000000; font-weight: bold;">\&quot;</span><span style="color: #007800;">$NUM</span><span style="color: #000000; font-weight: bold;">\&quot;</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> Title = <span style="color: #000000; font-weight: bold;">\&quot;</span><span style="color: #007800;">$TITLE</span><span style="color: #000000; font-weight: bold;">\&quot;</span>
mp3info <span style="color: #660033;">-a</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$ARTIST</span>&quot;</span> <span style="color: #660033;">-l</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$ALBUM</span>&quot;</span>    <span style="color: #660033;">-n</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$NUM</span>&quot;</span> <span style="color: #660033;">-t</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$TITLE</span>&quot;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$OUT</span>&quot;</span>
<span style="color: #7a0874; font-weight: bold;">echo</span> Done<span style="color: #000000; font-weight: bold;">!</span></pre></td></tr></table></div>

<p>Edit:  Thanks to a post over on <a href="http://www.reddit.com/r/linux/comments/dyauj/converting_wma_files_to_mp3_on_linux_while/c13v419">reddit</a>, here&#8217;s an update that makes better use of shell scripting:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/sh</span>
&nbsp;
<span style="color: #007800;">in</span>=<span style="color: #007800;">$1</span>
<span style="color: #007800;">out</span>=<span style="color: #800000;">${in%.[Ww][Mm][Aa]}</span>.mp3
&nbsp;
mutagen-inspect <span style="color: #ff0000;">&quot;<span style="color: #007800;">$in</span>&quot;</span> <span style="color: #000000; font-weight: bold;">|</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #007800;">IFS</span>= <span style="color: #c20cb9; font-weight: bold;">read</span> <span style="color: #660033;">-r</span> tag; <span style="color: #000000; font-weight: bold;">do</span>
        <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #007800;">$tag</span> <span style="color: #000000; font-weight: bold;">in</span>
        WM<span style="color: #000000; font-weight: bold;">/</span>AlbumArtist<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
            <span style="color: #007800;">ARTIST</span>=<span style="color: #800000;">${tag#*=}</span>
            <span style="color: #000000; font-weight: bold;">;;</span>
        WM<span style="color: #000000; font-weight: bold;">/</span>AlbumTitle<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
            <span style="color: #007800;">ALBUM</span>=<span style="color: #800000;">${tag#*=}</span>
            <span style="color: #000000; font-weight: bold;">;;</span>
        WM<span style="color: #000000; font-weight: bold;">/</span>TrackNumber<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
            <span style="color: #007800;">NUM</span>=<span style="color: #800000;">${tag#*=}</span>
            <span style="color: #000000; font-weight: bold;">;;</span>
        <span style="color: #007800;">Title</span>=<span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
            <span style="color: #007800;">TITLE</span>=<span style="color: #800000;">${tag#*=}</span>
            <span style="color: #000000; font-weight: bold;">;;</span>
        <span style="color: #000000; font-weight: bold;">esac</span>
    <span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
    <span style="color: #c20cb9; font-weight: bold;">mplayer</span> <span style="color: #660033;">-vc</span> null <span style="color: #660033;">-vo</span> null <span style="color: #660033;">-ao</span> pcm:waveheader:fast:<span style="color: #007800;">file</span>=<span style="color: #000000; font-weight: bold;">/</span>dev<span style="color: #000000; font-weight: bold;">/</span>stdout <span style="color: #000000; font-weight: bold;">|</span>
    <span style="color: #c20cb9; font-weight: bold;">lame</span> <span style="color: #660033;">--tt</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$TITLE</span>&quot;</span> <span style="color: #660033;">--ta</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$ARTIST</span>&quot;</span> <span style="color: #660033;">--tl</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$ALBUM</span>&quot;</span>  <span style="color: #660033;">--tn</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$NUM</span>&quot;</span> - <span style="color: #ff0000;">&quot;<span style="color: #007800;">$out</span>&quot;</span>
<span style="color: #7a0874; font-weight: bold;">&#125;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://coopology.com/2010/10/converting-wma-files-to-mp3-on-linux-specifically-ubuntu/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.606 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2013-05-22 22:37:23 -->

<!-- Compression = gzip -->