<?xml version="1.0" encoding="UTF-8"?>
<!--Generated by Squarespace Site Server v5.9.2 (http://www.squarespace.com/) on Thu, 11 Mar 2010 18:54:03 GMT--><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rss="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:cc="http://web.resource.org/cc/"><rss:channel rdf:about="http://www.noisyair.com/blog/"><rss:title>Noisy Air Software</rss:title><rss:link>http://www.noisyair.com/blog/</rss:link><rss:description>Could be many things. Most likely stuff relating to Mac development, but I make no guarantees.</rss:description><dc:language>en-US</dc:language><dc:date>2010-03-11T18:54:03Z</dc:date><admin:generatorAgent rdf:resource="http://www.squarespace.com/">Squarespace Site Server v5.9.2 (http://www.squarespace.com/)</admin:generatorAgent><rss:items><rdf:Seq><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/12/14/maven-users-update-your-webxml-files-to-24-to-use-jstl-tags.html"/><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/12/13/high-speed-internet-in-canada-sucks.html"/><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/10/9/visualizing-marsyas-data-with-quartz-coposer.html"/><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/9/21/environment-variables-available-in-xcode.html"/><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/9/9/quick-notes-on-jailbreaking-the-iphone.html"/><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/9/9/quick-notes-on-building-a-hackintosh.html"/><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/7/29/marsyas-and-iphone-os.html"/><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/7/29/marsyas-scripting-cocoa-based-gui-applications-with-python.html"/><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/7/29/marsyas-and-cocoa-bridging-objective-c-and-c-code.html"/><rdf:li rdf:resource="http://www.noisyair.com/blog/2009/7/29/creating-a-hello-world-application-with-marsyas-and-xcode.html"/></rdf:Seq></rss:items></rss:channel><rss:item rdf:about="http://www.noisyair.com/blog/2009/12/14/maven-users-update-your-webxml-files-to-24-to-use-jstl-tags.html"><rss:title>Maven Users: Update Your web.xml files to 2.4 to use JSTL Tags</rss:title><rss:link>http://www.noisyair.com/blog/2009/12/14/maven-users-update-your-webxml-files-to-24-to-use-jstl-tags.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-12-14T19:32:27Z</dc:date><dc:subject>Java Java Maven Web Development</dc:subject><content:encoded><![CDATA[<p>I came across a tricky problem today.&nbsp; I had used Maven to create a simple Java web application that I have been building upon.&nbsp; I got to the point where I wanted to use some JSTL tags in my presentation layer.&nbsp; Oddly enough the raw tags were being ignored and showing up in the HTML output.&nbsp;&nbsp; The problem turned out to be the usage of an older version of the web.xml file that Maven had generated.&nbsp; The 2.3 version uses a Doctype, and does not support the JSTL tags:</p>

<pre class="brush: xml;">
&lt;!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" &gt;
</pre>

<p>If you want your web app to process JSTL tags, you should update this file to use a 2.4 syntax instead.  The 2.4 version uses an XML schema instead of DTD to validate, so remove the above mentioned section and replace with the following:</p>

<pre class="brush: xml;">
&lt;web-app id="myApp" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"&gt;
</pre>]]></content:encoded></rss:item><rss:item rdf:about="http://www.noisyair.com/blog/2009/12/13/high-speed-internet-in-canada-sucks.html"><rss:title>High Speed Internet in Canada Sucks</rss:title><rss:link>http://www.noisyair.com/blog/2009/12/13/high-speed-internet-in-canada-sucks.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-12-13T23:59:20Z</dc:date><dc:subject>General - Tech broadband internet</dc:subject><content:encoded><![CDATA[<p>We received a letter from Telus last month telling us that we had exceeded our monthly data consumption quota.&nbsp; They informed us that if we exceeded this quota again, we would be suspended for 30 days.&nbsp; I had always assumed there was some sort of limit, but I never thought we would ever exceed it.&nbsp; I would say I'm a fairly heavy internet consumer; mong downloading the occasional large file (I like to try the new Linux distros), watching some internet video, online gaming, Skyping my parents, and general web browsing, I make full use of my internet privelages.&nbsp; I should also mention we pay top dollar to Telus to do so. We subscribe to the second best available plan.&nbsp;</p>
<p>I did a bit of research online to see just how much monthly data consumption we are allotted.&nbsp; The result was shocking and pathetic - a measly 60 gigabytes.&nbsp; I'll iterate again that we have the second best plan you can buy.&nbsp; What a joke.</p>
<p>Telus' best plan offers an unimpressive 100 gigabytes.&nbsp;</p>
<p>I would like to take a sentence or two to complain specifically about Telus.&nbsp; Their plans are underwhelming and their customer support is mediocre.&nbsp; It is my opinion (based on my past relationship with them as a provider) that they have minimal regard for their customers.&nbsp; They take full advantage of the near-monopolistic situation in Canada at the present.&nbsp;</p>
<p>That really is my main gripe however: the stagnant, optionless market we Canadians have when choosing mobile and broadband services.&nbsp; We have three main companies: Telus, Bell and Shaw, which are pretty much the only choices available for broadband connectivity (I know, there are some little guys too).&nbsp; After poking around on Bell's and Shaw's websites, I concluded that their offerings aren't much better.&nbsp; Have a look at the minitable I've compiled.&nbsp; Don't consider this information perfectly correct; it's what I could find after some basic browsing.&nbsp; I've also included two American providers for perspective.&nbsp;</p>
<p><span class="full-image-block ssNonEditable"><span><img style="width: 650px;" src="http://www.noisyair.com/storage/post-images/internetProviders.png?__SQUARESPACE_CACHEVERSION=1260754000973" alt="" /></span></span></p>
<p>In terms of monthly download capacity and bandwidth, Verizon and Comcast offer much better plans for the same price.&nbsp; Maybe this comment is unpatriotic but, please, Verizon and Comcast, come north and compete with the mediocrity we have going on at the moment.&nbsp;</p>]]></content:encoded></rss:item><rss:item rdf:about="http://www.noisyair.com/blog/2009/10/9/visualizing-marsyas-data-with-quartz-coposer.html"><rss:title>Visualizing Marsyas Data With Quartz Coposer</rss:title><rss:link>http://www.noisyair.com/blog/2009/10/9/visualizing-marsyas-data-with-quartz-coposer.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-10-09T23:08:30Z</dc:date><dc:subject>Audio Programming Mac OS Marsyas Marsyas audio</dc:subject><content:encoded><![CDATA[<p><a href="http://marsyas.sness.net">Steven Ness at sness.net</a> created a really cool application for visualizing several dimensions of an audio file.&nbsp; Here is a screencast of the awesomeness:</p>
<p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/X2rfyW6MVJ0&color1=0xb1b1b1&color2=0xcfcfcf&hl=en&feature=player_embedded&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowScriptAccess" value="always"></param><embed src="http://www.youtube.com/v/X2rfyW6MVJ0&color1=0xb1b1b1&color2=0xcfcfcf&hl=en&feature=player_embedded&fs=1" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="425" height="344"></embed></object></p>
<p>This was created using <a href="http://sourceforge.net/projects/marsyas/files/">Marsyas, an open-source audio processing framework</a>.&nbsp; I have posted a few tutorials about <a href="http://www.noisyair.com/marsyas/">getting up and running with Marsyas on the Mac</a>.&nbsp; I wanted to do something cool like this, unfortunately I wasn't gifted with Steve's sweet openGL skills.&nbsp; Instead I turned to an application called Quartz Composer.&nbsp; <a href="http://developer.apple.com/graphicsimaging/quartz/quartzcomposer.html">Quartz Composer</a> is a Mac (built in) application that provides the user with a visual programming environment, allowing for the creation of rich graphics and animations:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://www.noisyair.com/storage/post-images/qcBasic.png?__SQUARESPACE_CACHEVERSION=1255130794690" alt="" width="603" height="369" /></span></span></p>
<p>The user is presented with a canvas and a library of processing units called nodes.&nbsp; Producer nodes generate data, processing nodes perform some calucation on the data, and consumer nodes render the data.&nbsp;&nbsp; Ouputs are listed along the right edge of the node, and inputs are listed along the left.&nbsp; Nodes are connected by dragging a line from the output of one node to the input of another.&nbsp;</p>
<p>Previous versions of OSX limited the user to the set of built in producer nodes.&nbsp; Snow Leopard, however, allows for the creation of custom nodes, written in Objective-C.&nbsp; This is there Marsyas fits in.&nbsp;</p>
<h3>Briding the Explicit / Implicit Patching Divide</h3>
<p>The above diagram of Quartz Composer illustrates what's known as an <strong>explicit patching</strong> model.&nbsp; Patches - the connections between components - are explicitely created by the user.&nbsp; Marsyas on the other hand uses an <strong>implicit patching</strong> model.&nbsp; Connections among Marsyas nodes are implicitely established based on the order in which components are added to the network.&nbsp;</p>
<p>This project sees the Marsyas functionality, which is implemented in C++ and Objective-C, encapsulated in a producer node within Quartz Composer.&nbsp; An unlimited number of ports can be published for use in Quartz Composer, whcih are really representing any output from Marsyas. The following figure shows the use of a custom Marsyas producer node, and how it's output can be used to drive a graphical rendering:</p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://www.noisyair.com/storage/post-images/MarGraphFull.png?__SQUARESPACE_CACHEVERSION=1255134987979" alt="" width="592" height="361" /></span></span></p>
<p><span class="full-image-block ssNonEditable"><span><img src="http://www.noisyair.com/storage/MarGraphCloseUp.png?__SQUARESPACE_CACHEVERSION=1255135052763" alt="" width="587" height="414" /></span></span></p>
<p>These figures show a simple document where a Marsyas node is providing some information to a rotating cube.&nbsp; The example isn't too exciting ( I plan to do more useful things soon), but it does show what is possible.&nbsp; In this case, the Marsyas node has a fileInfo output port.&nbsp; This port pushes out data in the form of a dictionary.&nbsp; The keys in the dictionary represent some basic values about the file Marsyas is processing including sampleRate, numberOfChannels, lengthInSamples and lengthInSeconds.&nbsp; Here is a video of the results:</p>
<p><object width="445" height="364"><param name="movie" value="http://www.youtube.com/v/rZpp11-tf5Q&hl=en&fs=1&rel=0&color1=0x234900&color2=0x4e9e00&border=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/rZpp11-tf5Q&hl=en&fs=1&rel=0&color1=0x234900&color2=0x4e9e00&border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="445" height="364"></embed></object></p>
<p>Like I said, the data in this example isn't too exciting, but there are a few cool things going on.&nbsp; You will notice that the audio is playing back while the graphic is rendering.&nbsp; This isn't normal behavior in Quartz Composer, but I placed the audio playback on a separate thread.&nbsp; Also, it is possible to publish pretty much any type of data that Marsyas is capable of producing to Quartz Composer.&nbsp; Once in Quartz Composer, anything can be done with the data.&nbsp; In other words, the visualization and data are kept separate can be implemented at separate times.&nbsp;</p>
<h3>Future Work</h3>
<p>The next step in this project is to rethink the threading model I'm using.&nbsp; Right now I have two separate threads running: one to play the audio and one to periodically write the audio information to the output ports.&nbsp; You may notice some crackling in the audio and choppiness in the video. I think this is because I'm locking some common data structures too often.&nbsp;</p>
<p>I also want to publish more data to Quartz Composer such as amplitude, panning, centroid, etc.</p>]]></content:encoded></rss:item><rss:item rdf:about="http://www.noisyair.com/blog/2009/9/21/environment-variables-available-in-xcode.html"><rss:title>Environment Variables Available in xCode</rss:title><rss:link>http://www.noisyair.com/blog/2009/9/21/environment-variables-available-in-xcode.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-09-21T19:13:05Z</dc:date><dc:subject>Mac OS development environment variables xCode</dc:subject><content:encoded><![CDATA[<p>I like this awesome tip from <a href="http://codeendeavor.com/archives/626">Aaron Smith at Code Endeavor</a>.&nbsp; It talks about creating a reference list of all environment variables avaible when building a project with xCode.&nbsp; It is pretty simple: Create a run script build phase in your project and set the script instructions as:</p>
<pre class="brush: bash;">
env &gt; ENVIRONMENT_VAR_LIST
</pre>
<p>This will create a text file in your build directory with all of the available environment variables.&nbsp;</p>]]></content:encoded></rss:item><rss:item rdf:about="http://www.noisyair.com/blog/2009/9/9/quick-notes-on-jailbreaking-the-iphone.html"><rss:title>Quick Notes on Jailbreaking the iPhone</rss:title><rss:link>http://www.noisyair.com/blog/2009/9/9/quick-notes-on-jailbreaking-the-iphone.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-09-09T20:24:36Z</dc:date><dc:subject>Apple Jailbreak iPhone iPhone</dc:subject><content:encoded><![CDATA[<p>iClarify has the best tutorials I've seen to do this ( <a href="http://www.iclarified.com/entry/index.php?enid=4254">link</a> ).&nbsp; They should soon have one for the 3.1 update.&nbsp;</p>]]></content:encoded></rss:item><rss:item rdf:about="http://www.noisyair.com/blog/2009/9/9/quick-notes-on-building-a-hackintosh.html"><rss:title>Quick Notes on Building a Hackintosh</rss:title><rss:link>http://www.noisyair.com/blog/2009/9/9/quick-notes-on-building-a-hackintosh.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-09-09T19:52:40Z</dc:date><dc:subject>Hackintosh Mac Mac OS OSX</dc:subject><content:encoded><![CDATA[<p>The best guide I've found for building a Hackintosh can be found at Lifehacker ( <a href="http://lifehacker.com/5351485/how-to-build-a-hackintosh-with-snow-leopard-start-to-finish">link</a> ).&nbsp; There is also a comprehensive hardware compatibility resource avialble ( <a href="http://wiki.osx86project.org/wiki/index.php/Main_Page">link</a> ).&nbsp;</p>]]></content:encoded></rss:item><rss:item rdf:about="http://www.noisyair.com/blog/2009/7/29/marsyas-and-iphone-os.html"><rss:title>Marsyas and iPhone OS</rss:title><rss:link>http://www.noisyair.com/blog/2009/7/29/marsyas-and-iphone-os.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-07-29T17:39:40Z</dc:date><dc:subject>Audio Programming Mac OS Mac OS Marsyas Marsyas audio iPhone iPhone music information retrieval</dc:subject><content:encoded><![CDATA[<p>Apple has gone to great lengths to mirror the Mac OSX frameworks when designing iPhone OS. This makes the transition from the desktop to iPhone easier for Mac developers accustomed to naming conventions and runtime system of OSX. That said, there are several differences between the two that have serious consequences for portability. The most impacting is the differing CPU architecture; Macs are running on Intel or PowerPC CPUs, while iPhones are using ARM processors. Each CPU uses its own instruction set, requiring developers to compile their projects to the specific architecture they wish to target. <br /><br />This chapter will focus on how to build Marsyas for the ARM processor, and other differences between Mac OS and iPhone OS that will impact Marsyas.</p>
<h3>Implications and Scope of Marsyas on the iPhone</h3>
<p>Before getting into the details of using Marsyas on the iPhone, one must determine if the reduced functionality of the framework will meet the needs of the application. Most notably, the iPhone implementation of CoreAudio is so different from the Mac version, it does not meet the requirements of Marsyas. This means Marsyas must be built without audio IO support. This may be a deal breaker for several types of applications. Further CoreMIDI does not yet exist on iPhone OS, so that is out too. These differences should imply that Marsyas is best used for analysis of audio, and actual MIDI or Audio IO should be implemented natively by the developer using CoreAudio and CoreMIDI. The example project in this chapter details this role.</p>
<h3>Building a FAT libmarsyas</h3>
<p>As previously mentioned, the most challenging aspect of using Marsyas on the iPhone is targeting the AR processor in the build process. Further complicating matters is the iPhone Simulator. Being a simulator (as opposed to an emulator), the iPhone simulator uses x86 (Intel) instructions. This means that testing an application in the simulator requires the project to be targeted at an x86 processor, while deploying to the actual device requires it to be targeted at the ARM processor. To achieve this, two versions of libmarsyas will be created: one with x86 instructions and one with ARM instructions. The two libraries will be merged into a single "FAT" library using the <strong>lipo</strong> tool. This FAT library is universal and can be included into projects targeted at both x86 and ARM processors. The drawback is that the library is twice as big as it needs to be for any single architecture. <br /><br />The approach taken in this tutorial is to alter the Marsyas cmake settings in two iterations, first to build for ARM, then to build for x86. Finally the two libraries are combined into a single lib. Read the following subsections to understand this process or simply copy the following python script and execute it in the <strong>marsyas</strong> main directory.</p>
<p><code> </code></p>
<pre>#!/usr/bin/python<br />import os<br />import sys<br /><br /># A script to set some CMake variables when building marsyas.<br /># We wish to target the iphone simulator (x86) / iphone device (arm)<br /><br /><br /># Parameters: Adjust these as required!<br /><br />DEVROOT_PHONE = "/Developer/Platforms/iPhoneOS.platform/Developer"<br />DEVROOT_SIMULATOR = "/Developer/Platforms/iPhoneSimulator.platform/Developer"<br /><br />## update this export with your most current version of the iPhone SDK<br />SDKROOT_PHONE = DEVROOT_PHONE + "/SDKs/iPhoneOS3.0.sdk"<br />SDKROOT_SIMULATOR = DEVROOT_SIMULATOR + "/SDKs/iPhoneSimulator3.0.sdk"<br />LIB_OUT_DIR = "fatLibraryOUTPUT"<br /><br />## configures CMake to build for the arm iphone device<br />## and runs make to do so<br />def buildForIPhoneDevice(cleanAndRemake=False, withAudio=True):<br /> print "---------------------------------------"<br /> print "Building Marsyas for iPhone Device\n"<br /> <br /> if(cleanAndRemake):<br /> print "Removing old buildIphoneDevice build files"<br /> os.system("rm -rf buildIphoneDevice")<br /> <br /> ## create a new build dir for this build and cd into it<br /> os.mkdir("buildIphoneDevice")<br /> os.chdir("buildIphoneDevice")<br /> <br /> ## build up the custom arguments for cmake:<br /> cmake = "cmake "<br /># Compiler / linker etc<br /> cmake += " -D CMAKE_CXX_COMPILER:FILEPATH="+ DEVROOT_PHONE + "/usr/bin/c++ "<br /> cmake += " -D CMAKE_CXX_FLAGS:STRING=-arch\ armv6\ -pipe\ -no-cpp-precomp\ -isysroot\ "+ SDKROOT_PHONE + "\ -I" + SDKROOT_PHONE + "/usr/lib/gcc/arm-apple-darwin9/4.2.1/include/\ -I"+ SDKROOT_PHONE + "/usr/include/\ " <br /> cmake += " -D CMAKE_AR:FILEPATH=/usr/bin/ar "<br /> cmake += " -D CMAKE_C_COMPILER:FILEPATH="+ DEVROOT_PHONE + "/usr/bin/gcc "<br /> cmake += " -D CMAKE_C_FLAGS:STRING=-arch\ armv6\ -pipe\ -no-cpp-precomp\ -isysroot\ "+ SDKROOT_PHONE + "\ -I" + SDKROOT_PHONE + "\ -I" + SDKROOT_PHONE + "/usr/lib/gcc/arm-apple-darwin9/4.2.1/include/\ -I"+ SDKROOT_PHONE + "/usr/include/ "<br /> cmake += " -D CMAKE_EXE_LINKER_FLAGS:STRING=--host=arm-apple-darwin "<br /> cmake += " -D CMAKE_MODULE_LINKER_FLAGS:STRING= "<br /> cmake += " -D CMAKE_LINKER:FILEPATH="+ DEVROOT_PHONE + "/usr/bin/ld "<br /> cmake += " -D CMAKE_OSX_ARCHITECTURES:STRING=armv6 " ## from i386<br /> #isysroot used for universal binary support<br /> cmake += " -D CMAKE_OSX_SYSROOT:PATH=" + DEVROOT_PHONE + "/SDKs/iPhoneOS3.0.sdk " # from /Developer/SDKs/MacOSX10.5.sdk<br /><br /># Differences exist between Mac and iPhone CoreAudio.frameworks. be warned. <br /> cmake += " -D COREAUDIO_LIBRARY:FILEPATH=" + SDKROOT_PHONE + "/System/Library/Frameworks/CoreAudio.framework "<br /> if withAudio:<br /> cmake += " -D MARSYAS_AUDIOIO:BOOL=ON "<br /> else:<br /> cmake += " -D MARSYAS_AUDIOIO:BOOL=OFF "<br /> <br /> cmake += " -D COREFOUNDATION_LIBRARY:FILEPATH=" + SDKROOT_PHONE + "/System/Library/Frameworks/CoreFoundation.framework "<br /># Apple has not implemented Core MIDI on iphone yet:<br /># cmake += " -D COREMIDI_LIBRARY:FILEPATH=" + SDKROOT_PHONE + "/System/Library/Frameworks/CoreMidi.framework "<br /> cmake += " -D MARSYAS_MIDIIO:BOOL=OFF " # enable to ON when implemented<br /> cmake += " -D MARSYAS_BUILD_APPS:BOOL=OFF "<br /># Open GL for iPhone is questionable, it only supports a subset of options...<br /># replace OpenGL.framework with OpenGLES.framework. AGL.framework not implemented on iPHone...<br /> cmake += " -D OPENGL_INCLUDE_DIR:PATH=" + SDKROOT_PHONE + "/System/Library/Frameworks/OpenGLES.framework "<br /> cmake += " -D OPENGL_gl_LIBRARY:FILEPATH=" + SDKROOT_PHONE + "/System/Library/Frameworks/OpenGLES.framework "<br /># cmake += " -D OPENGL_glu_LIBRARY:FILEPATH=" + SDKROOT_PHONE + "/System/Library/Frameworks/AGL.framework " enable when ready<br /> cmake += " -D WITH_OPENGL:BOOL=OFF " # endable when ready<br /># MP3 support needs the libmad library compiled for arm on the iphone device:<br /> cmake += " -D WITH_MAD:BOOL=OFF "<br /> cmake += " -D WITH_PNG:BOOL=OFF "<br /> cmake += " -D WITH_QT:BOOL=OFF "<br /> cmake += " -D WITH_SWIG:BOOL=OFF "<br /> cmake += " -D WITH_VAMP:BOOL=OFF "<br /> cmake += " -D WITH_VORBIS:BOOL=OFF "<br /> <br /> cmake += " ../src"<br /> <br /> ## execute cmake to generate the makefiles:<br /> print "generating makefiles with cmake"<br /> os.system(cmake)<br /> <br /> ## run make to build marsyas<br /> print "Making marsyas"<br /> os.system("make marsyas")<br /> <br /> ## move the generated lib file to a safe place<br /> os.system("mv lib/libmarsyas.a ../" + LIB_OUT_DIR + "/libmarsyas.a.arm")<br /> <br /> ## go back to the original working directory:<br /> os.chdir("..")<br /> <br /> <br />## configures CMake to build for the x86 iphone simulator<br />## and runs make to do so <br />def buildForIPhoneSimulator(cleanAndRemake=False, withAudio=True):<br /> print "---------------------------------------"<br /> print "Building Marsyas for iPhone Simulator\n"<br /> <br /> if(cleanAndRemake):<br /> print "Removing old buildIphoneSimulator build files"<br /> os.system("rm -rf buildIphoneSimulator")<br /> <br /> ## create a new build dir for this build and cd into it<br /> os.mkdir("buildIphoneSimulator")<br /> os.chdir("buildIphoneSimulator")<br /> <br /> ## build up the custom arguments for cmake:<br /> cmake = "cmake "<br /># Compiler / linker etc<br /> cmake += " -D CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ "<br /> cmake += " -D CMAKE_CXX_FLAGS:STRING= " <br /> cmake += " -D CMAKE_AR:FILEPATH=/usr/bin/ar "<br /> cmake += " -D CMAKE_C_FLAGS:STRING= "<br /> cmake += " -D CMAKE_C_COMPILER:FILEPATH=/usr/bin/gcc "<br /> cmake += " -D CMAKE_EXE_LINKER_FLAGS:STRING= "<br /> cmake += " -D CMAKE_MODULE_LINKER_FLAGS:STRING= "<br /> cmake += " -D CMAKE_LINKER:FILEPATH=/usr/bin/ld "<br /> cmake += " -D CMAKE_OSX_ARCHITECTURES:STRING=i386 "<br /> #isysroot used for universal binary support<br /> cmake += " -D CMAKE_OSX_SYSROOT:PATH=/Developer/SDKs/MacOSX10.5.sdk "<br /><br /># Differences exist between Mac and iPhone CoreAudio.frameworks. be warned. <br /> cmake += " -D COREAUDIO_LIBRARY:FILEPATH=" + SDKROOT_SIMULATOR + "/System/Library/Frameworks/CoreAudio.framework "<br /> if withAudio:<br /> cmake += " -D MARSYAS_AUDIOIO:BOOL=ON "<br /> else:<br /> cmake += " -D MARSYAS_AUDIOIO:BOOL=OFF "<br /> cmake += " -D COREFOUNDATION_LIBRARY:FILEPATH=" + SDKROOT_SIMULATOR + "/System/Library/Frameworks/CoreFoundation.framework "<br /># Apple has not implemented Core MIDI on iphone yet:<br /># cmake += " -D COREMIDI_LIBRARY:FILEPATH=" + SDKROOT_SIMULATOR + "/System/Library/Frameworks/CoreMidi.framework "<br /> cmake += " -D MARSYAS_MIDIIO:BOOL=OFF " # enable to ON when implemented<br /> cmake += " -D MARSYAS_BUILD_APPS:BOOL=OFF "<br /># Open GL for iPhone is questionable, it only supports a subset of options...<br /># replace OpenGL.framework with OpenGLES.framework. AGL.framework not implemented on iPHone...<br /> cmake += " -D OPENGL_INCLUDE_DIR:PATH=" + SDKROOT_SIMULATOR + "/System/Library/Frameworks/OpenGLES.framework "<br /> cmake += " -D OPENGL_gl_LIBRARY:FILEPATH=" + SDKROOT_SIMULATOR + "/System/Library/Frameworks/OpenGLES.framework "<br /># cmake += " -D OPENGL_glu_LIBRARY:FILEPATH=" + SDKROOT_SIMULATOR + "/System/Library/Frameworks/AGL.framework " enable when ready<br /> cmake += " -D WITH_OPENGL:BOOL=OFF " # endable when ready<br /># MP3 support needs the libmad library compiled for arm on the iphone device:<br /> cmake += " -D WITH_MAD:BOOL=OFF "<br /> cmake += " -D WITH_PNG:BOOL=OFF "<br /> cmake += " -D WITH_QT:BOOL=OFF "<br /> cmake += " -D WITH_SWIG:BOOL=OFF "<br /> cmake += " -D WITH_VAMP:BOOL=OFF "<br /> cmake += " -D WITH_VORBIS:BOOL=OFF "<br /> <br /> cmake += " ../src"<br /> <br /> ## execute cmake to generate the makefiles:<br /> print "generating makefiles with cmake"<br /> os.system(cmake)<br /> <br /> ## run make to build marsyas<br /> print "Making marsyas"<br /> os.system("make marsyas")<br /> <br /> ## move the generated lib file to a safe place<br /> os.system("mv lib/libmarsyas.a ../" + LIB_OUT_DIR + "/libmarsyas.a.i386")<br /> <br /> ## go back to the original working directory:<br /> os.chdir("..")<br /> <br />## creates one fat static library with the contents of the arm<br />## and x86 versions of libmarsyas.a<br />def createFatStaticLibrary():<br /> print "Creating the 'fat' marsyas library for i386 and arm "<br /> os.system(DEVROOT_PHONE + "/usr/bin/lipo -arch arm " + LIB_OUT_DIR + "/libmarsyas.a.arm -arch i386 " + LIB_OUT_DIR + "/libmarsyas.a.i386 -create -output " + LIB_OUT_DIR + "/libmarsyas.a")<br /><br /><br />## main body:<br />if __name__ == '__main__':<br /> os.system("mkdir " + LIB_OUT_DIR)<br /> buildForIPhoneDevice(cleanAndRemake=True, withAudio=False)<br /> buildForIPhoneSimulator(cleanAndRemake=True, withAudio=True)<br /> createFatStaticLibrary()<br /></pre>
<p>&nbsp;</p>
<h4>Scripting Multiple cmake builds</h4>
<p>The script defines three functions:</p>
<p><code> </code></p>
<pre>if __name__ == '__main__':<br /> os.system("mkdir " + LIB_OUT_DIR)<br /> buildForIPhoneDevice(cleanAndRemake=True, withAudio=False)<br /> buildForIPhoneSimulator(cleanAndRemake=True, withAudio=True)<br /> createFatStaticLibrary()<br /></pre>
<p>&nbsp;</p>
<p>The script creates a new directory to hold the three versions of libmarsyas (ARM, x86 and combined). Each function creates the respective version of the library. At this point, <strong>withAudio</strong> may as well be set to false since Marsyas is not able to use the iPhone version of CoreAudio (runtime errors will result if it is attempted).</p>
<p><code> </code></p>
<pre>DEVROOT_PHONE = "/Developer/Platforms/iPhoneOS.platform/Developer"<br />DEVROOT_SIMULATOR = "/Developer/Platforms/iPhoneSimulator.platform/Developer"<br />## update this export with your most current version of the iPhone SDK<br />SDKROOT_PHONE = DEVROOT_PHONE + "/SDKs/iPhoneOS3.0.sdk"<br />SDKROOT_SIMULATOR = DEVROOT_SIMULATOR + "/SDKs/iPhoneSimulator3.0.sdk"<br /></pre>
<p>&nbsp;</p>
<p>Four constants are also set. These help the script find the tools needed by cmake / make to build Marsyas. These constants should be altered to reflect the current system. <br /><br />The <strong>buildForIphoneSimulator</strong> functions is fairly straightforward. First several cmake variables are set that reflect the reduced functionality of the iPhone SDK. Read through the parameters to get a sense of what is available and what is not (e.g no openGL, CoreAudio, CoreMIDI, mp3 support). Next <strong>cmake &lt;varlist&gt; ../src </strong>is called to create the <strong>CMakeCache.txt</strong> file and various build scripts for the simulator. Finally make <strong>marsyas</strong> is called to build the Marsyas library. <br /><br />The <strong>buildForIphoneDevice</strong> function is more interesting, but works pretty much the same as the previous function. The only differences are the changes to the compiler and linker flags. The script instructs cmake to use the iPhone gcc compiler and to set the target architecture to armv6. Again reading through the set variables, and referencing the gcc / cmake documentation should make its intent clear. <br /><br />The script concludes by calling <strong>lipo</strong> to create a FAT static library containing both instruction sets. This final library can be found in the <strong>marsyas/FATlibraryOUTPUT</strong> directory.</p>
<h3>Create an iPhone Project</h3>
<p>The example project will be another selection from the Marsyas documentation that shows how to extract data from the MarSystem network. Notice how the role of Marsyas has changed here. It is being used for audio analysis, not so much for actual playback. Marsyas should be relied on for these types of features, while any actual audio playback / recording should be separately implemented using CoreAudio and AudioToolbox frameworks. <br /><br />Begin by creating a new iPhone project template. Select the <strong>View Based Application</strong>:</p>
<p>Take the usual steps to incorporate Marsyas into a project:</p>
<ul>
<li> Link against CoreFoundation (CoreAudio does not work properly, and CoreMIDI does not exist).</li>
<li>Link against the FAT libmarsyas.a created to target both x86 and ARM.</li>
<li>Update the header search path to include the Marsyas header files.</li>
</ul>
<h3>Implement the ViewController</h3>
<p>The project template will have created a default ViewController: <strong>&lt;projectName&gt;ViewController.m</strong>. Rename this file to <strong>&lt;projectName&gt;ViewController.mm </strong>to let the compiler know that there will be C++ code as well as Objective-C code. Update the header and implementation files with the following code:</p>
<p><code> </code></p>
<pre>// MarsyasIphoneViewController.h<br /><br />#import <br /><br />@interface MarsyasIphoneViewController : UIViewController {<br /> IBOutlet UILabel* filenameLabel;<br /> NSString* filename;<br />}<br /><br />@property(nonatomic, retain) IBOutlet UILabel* filenameLabel;<br />@property(nonatomic, retain) NSString* filename;<br /><br />-(IBAction)printData:(id)sender;<br /><br />@end<br /></pre>
<p>&nbsp;</p>
<p><code> </code></p>
<pre>// MarsyasIphoneViewController.mm<br /><br />#import "MarsyasIphoneViewController.h"<br />#import <br />#include "MarSystemManager.h"<br /><br />using namespace Marsyas;<br />using namespace std;<br /><br />@implementation MarsyasIphoneViewController<br /><br />@synthesize filename;<br />@synthesize filenameLabel;<br /><br />#pragma mark lifecycle methods<br /><br />-(void)viewDidLoad{<br /> std::string aString = "Hello World";<br /> std::cout &lt;&lt; aString &lt;&lt; std::endl;<br /> self.filename = [[NSBundle mainBundle] pathForResource:@"song" ofType:@"wav"];<br /> [filenameLabel setText:filename];<br />}<br /><br />- (void)dealloc {<br /> self.filename = nil;<br /> self.filenameLabel = nil;<br /> [super dealloc];<br />}<br /><br />#pragma mark actions<br /><br />-(IBAction)printData:(id)sender{<br /> <br /> string sfName = [filename UTF8String];<br /> <br /> MarSystemManager mng;<br /> MarSystem* pnet = mng.create("Series", "pnet");<br /> // standard network<br /> pnet-&gt;addMarSystem(mng.create("SoundFileSource", "src"));<br /> pnet-&gt;updctrl("SoundFileSource/src/mrs_string/filename", sfName);<br /> pnet-&gt;addMarSystem(mng.create("Spectrum","spk"));<br /> pnet-&gt;addMarSystem(mng.create("Gain", "g2"));<br /> <br /> while ( pnet-&gt;getctrl("SoundFileSource/src/mrs_bool/notEmpty")-&gt;to() )<br /> {<br /> pnet-&gt;tick();<br /> // gets data from the Spectrum for read only!<br /> const realvec&amp; processedData =<br /> pnet-&gt;getctrl("Spectrum/spk/mrs_realvec/processedData")-&gt;to();<br /> cout &lt;&lt; "Original Spectrum = " &lt;&lt; processedData &lt;&lt; endl;<br /> <br /> <br /> // if we need to get the Spectrum and modify it, here is the way<br /> // to do it. Notice that we must open a new scope using curly<br /> // brackets so that MarControlAccessor is automatically destroyed<br /> // when we are finished modifing the realvec control.<br /> {<br /> MarControlAccessor<br /> acc(pnet-&gt;getctrl("Spectrum/spk/mrs_realvec/processedData"));<br /> realvec&amp;<br /> processedData2 = acc.to();<br /> <br /> // we can now write to processedData without worries of<br /> // breaking encapsulation<br /> processedData2 *= 2.0;<br /> cout &lt;&lt; "Modified Spectrum = " &lt;&lt; processedData2 &lt;&lt; endl;<br /><br /> }<br /> }<br /> delete pnet;<br />}<br /><br />@end<br /></pre>
<p>&nbsp;</p>
<h3>Wire the NIB file in Interface Builder</h3>
<p>Open the corresponding <strong>&lt;projectName&gt;ViewController.xib</strong> file in Interface Builder. Create an interface similar to the following:</p>
<p>Wire the <strong>UILabel</strong> to the <strong>File Owner's</strong> <strong>filenameLabel</strong> outlet, and wire the <strong>UIButton</strong> to the <strong>printData</strong> action. Let the label take up a large space and set it to show several lines of text (at least 5).</p>
<h3>Add an Audio Resource</h3>
<p>Find some small wav file from the internet and drag it into the project's resources folder. Select the <strong>copy</strong> option and set the reference type to <strong>relative to project</strong>. Give the wav file the name<strong> song.wav</strong>.</p>
<h3>Build and Test the Program</h3>
<p>Finally, click the <strong>Build and Go</strong> hammer. The iPhone simulator should launch and present the UI that was created. Clicking on button should print out the <strong>MarSystem</strong> output to the console. While this example is somewhat impractical, it shows how to build for the iPhone and how to make use of the data generated by Marsyas. It also shows how to work the Marsyas C++ code into an Objective-C environment.</p>]]></content:encoded></rss:item><rss:item rdf:about="http://www.noisyair.com/blog/2009/7/29/marsyas-scripting-cocoa-based-gui-applications-with-python.html"><rss:title>Marsyas: Scripting Cocoa-based GUI Applications with Python</rss:title><rss:link>http://www.noisyair.com/blog/2009/7/29/marsyas-scripting-cocoa-based-gui-applications-with-python.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-07-29T17:16:14Z</dc:date><dc:subject>Audio Programming Mac OS Mac OS Marsyas Marsyas Python Python audio music information retrieval</dc:subject><content:encoded><![CDATA[<p>Various bridges have been created that allow developers to create Cocoa applications without writing them in Objective-C. Scripting languages such as <a href="http://www.ruby-lang.org/en/">Ruby</a> and <a href="http://www.python.org/">Python</a>, as well as production languages like Java are supported. Prototyping an application in an interpreted language such as Python can greatly speed up development time because the sourcecode does not require compilation. Further, the interactive interpreter allows for the quick testing of code snippets. Libraries exist that allow Python to create GUIs with other graphics toolkits like <a href="http://en.wikipedia.org/wiki/Tk\_(computing">Tkinter</a> or <a href="http://www.qtsoftware.com/products/">Qt</a>, however this is a Mac specific tutorial so it will focus on Cocoa. Furthermore, the GUI classes (AppKit) are but a small subset of the available functionality within Cocoa. There are likely many more classes within Foundation.framework that may of use through the bridge. <br /><br />Marsyas can also be scripted in several other languages through the use of SWIG (Simple Wrapper and Interface Generator) bindings. <a href="http://www.swig.org/">SWIG</a> is a tool that creates bindings from C++ projects for other programming languages. This chapter will describe the steps in building a scripted, Cocoa-based GUI application, using Python and the SWIG-generated Marsyas bindings.</p>
<p>Note that details regarding several of this chapter's topics are beyond the scope of this document. One should refer to the appropriate Python or other project documentation if required (links will be provided in the appropriate sections).</p>
<h3>Configure Python and PyObjC</h3>
<p>Python has been known to exhibit somewhat <a href="http://jessenoller.com/2009/03/16/so-you-want-to-use-python-on-the-mac/">strange behavior</a> on the Mac platform. This has to do with the way it has been pre-installed on the platform. To make a long story short, be sure to use the standard MacPython version that came installed by default. This should be Python version 2.5, which is generally appropriate for Python programming. If this version is not used, a common error that may likely emerge is the <strong>Python fatal exception: Possible version conflict?</strong> error. This error arises when more than one version of Python is installed. The system becomes confused about future libraries that need to be installed. <br /><br /><a href="http://pyobjc.sourceforge.net/">PyObjC</a> is the project that implements the Python-ObjectivC bindings. As well it wraps up the many Cocoa frameworks so that they may also be called from Python. These bindings allow developers to create native Cocoa applications by instantiating <strong>Foundation</strong> and <strong>AppKit</strong> framework classes through the Python-ObjectiveC bridge. <br /><br />Ensure that MacPython is the current version with the terminal command:</p>
<p>python --version</p>
<p>This should return version 2.5.x (assuming MacOS 10.5.7 Leopard. it may be different with newer versions of Mac OS). Next, test for the existence of PyObjC. Begin the Python interpreter:</p>
<p>python</p>
<p>Try to import the PyObjC modules:</p>
<p>import Foundation</p>
<p>If an error results, then PyObjC is not installed. Visit the <a href="http://pyobjc.sourceforge.net/">PyObjC website</a> to grab the sourcecode. Build PyObjC according to the included documentation. PyObjC may also be installed with MacPorts. Whatever the route taken to install PyObjC, do not proceed unless the import error above is corrected.</p>
<h3>Build Marsyas with SWIG</h3>
<p>Marsyas needs to be rebuild, this time enabling SWIG. First ensure that SWIG is installed by using MacPorts:</p>
<p>sudo port install swig</p>
<p>With SWIG installed, rebuild Marsyas with the SWIG-Python bindings enabled. Refer to the prior chapter on how to build Marsyas. Note that after enabling SWIG in the ccmake GUI, press c to reconfigure and see new options related to SWIG. Ensure that SWIG-PYTHON is enabled, then build Marsyas as usual.</p>
<p>After the project is build, navigate into the <strong>&lt;buildDir&gt;/swig</strong> directory and install the SWIG bindings:</p>
<p>sudo make install</p>
<p>This will move the Python bindings into the Python directory so they can be found with Python import statements. The default install directory is <strong>/Library/Python/2.5/site-packages/</strong>. If everything has gone successfully, test by importing the Marsyas module in a python interpreter. Begin a Python session and import marsyas:</p>
<p>python<br />import marsyas</p>
<p>The marsyas module should import without a hitch. If this is not the case, refer to the <a href="http://marsyas.sness.net/docs/manual/marsyas-user/index.html">Marsyas user documentation</a> or some other <a href="http://www.python.org/community/">Python help resource</a>.</p>
<h3>Create a Simple Application</h3>
<p>With these two modules installed, all the tools are in place to build Marsyas-Cocoa applications in Python. The easiest way to begin is by copying one of the simple example applications included in the<strong> /Developer</strong> directory. Copy the <strong>/Developer/Examples/Python/PyObjC/Cocoa/AppKit/ClassBrowser/</strong> project folder to the Desktop (or any other desired working directory).</p>
<p>To create the application, open a terminal the example application's working directory and type:</p>
<p>python setup.py py2app -A</p>
<p>The <strong>-A </strong>creates symbolic links to Python executables so that building takes much less time. This option should be removed when creating a production version of the application because the python executables will be included to create a truly stand-alone product. <br /><br />This creates the application executable. Attempting to run the application will likely result in an error. This is because PyObjC does not play well with NIB files. This tutorial will use this example application as a shell, but the GUI will be built entirely in code. <br /><br /><strong>ClassBrowser.py</strong> and <strong>ClassBrowser.nib </strong>files to <strong>MarPlayer.py</strong> and <strong>MarPlayer.nib</strong>. Open the <strong>setup.py</strong> script and change all of the <strong>ClassBrowser</strong> references to <strong>MarPlayer</strong>. <br /><br />Next, open the <strong>MarPlayer.nib</strong> file and delete the <strong>ClassBrowserDelegate</strong>, <strong>NSTextField</strong> and <strong>NSSplitView</strong>. The only objects remaining should be:</p>
<ul>
<li>First Responder</li>
<li>Files Owner</li>
<li>NSWindow</li>
<li>NSView (the window's subview)</li>
<li>NSApplication</li>
<li>NSMenu</li>
</ul>
<p>This creates an empty NIB shell. The tutorial will programatically add to the window's subview.</p>
<p>Replace the contents of MarPlayer.py with the following:<br /><code> </code></p>
<pre>import os<br />import sys<br />from PyObjCTools import AppHelper<br />from  objc import *<br />from Foundation import *<br />from AppKit import *<br /><br />from marsyas import *<br /><br />## will be set to a global instance of controller<br />controller = None<br />## update to an audio file on your machine:<br />audioFilename = "/Users/darren/Desktop/song.wav"<br /><br />class MarSystemAppController(NSObject):<br />	<br />	def playAudio_(self, sender):		<br />		#set up marsyas to play back an audio file<br />		gain = 1.0<br />		marManager = MarSystemManager()<br />		marPlayer = marManager.create("Series", "playbacknet")<br />		<br />		marPlayer.addMarSystem(marManager.create("SoundFileSource", "src"))<br />		marPlayer.addMarSystem(marManager.create("Gain", "gt"))<br />		marPlayer.addMarSystem(marManager.create("AudioSink", "dest"))<br />		<br />		marPlayer.updControl("SoundFileSource/src/mrs_string/filename", MarControlPtr.from_string(audioFilename))<br />		marPlayer.updControl("Gain/gt/mrs_real/gain", MarControlPtr.from_real(gain))<br />		marPlayer.updControl("AudioSink/dest/mrs_bool/initAudio", MarControlPtr.from_bool(True))<br />		<br />		while marPlayer.getControl("SoundFileSource/src/mrs_bool/notEmpty").to_bool():<br />			marPlayer.tick()<br />		<br />		<br />	def stopAudio_(self, sender):<br />		print "not implemented, keep listeing!"<br /><br />def initThisApp():<br />	global controller<br /><br />	## create an instance of the app Controller:<br />	controller = MarSystemAppController.alloc().init()<br />	<br />	## grab a refernce to the main window<br />	window = NSApplication.sharedApplication().orderedWindows().objectAtIndex_(0)<br />	frame = NSMakeRect(400.0, 400.0, 250.0, 150.0)<br />	window.setFrame_display_animate_(frame, False, True)<br />	<br />	## create the play and stop buttons<br />	frame = NSMakeRect(50.0, 40.0, 150.0, 20.0)<br />	playButton = NSButton.alloc().initWithFrame_(frame)<br />	playButton.setTitle_("Play Audio")<br />	playButton.setTarget_(controller)<br />	playButton.setAction_(NSSelectorFromString("playAudio:"))<br />	frame = NSMakeRect(50.0, 70.0, 150.0, 20.0)<br />	stopButton = NSButton.alloc().initWithFrame_(frame)<br />	stopButton.setTarget_(controller)<br />	stopButton.setAction_(NSSelectorFromString("stopAudio:"))<br />	stopButton.setTitle_("Stop Audio")<br />	<br />	# add the buttons to the window<br />	window.contentView().addSubview_(playButton)<br />	window.contentView().addSubview_(stopButton)<br />	<br /><br />if __name__ == "__main__":<br />	# handling a tiny timing issue. this function calls initThisApp (asyncronously) 1 second<br />	# after the runEventLoop() method is called to give the system a chance to<br />	# get teh even loop running before making calls to NSApplication.sharedApplication()<br />	AppHelper.callLater(0.5, initThisApp)<br />	AppHelper.runEventLoop()<br /></pre>
<p>&nbsp;</p>
<p>Read through the script and make the appropriate changes (e.g. the path to an audio file, etc). This program does the same thing as the application built in chapter describing Marsyas Cocoa with Objective-C. Build and run the application by navigating to the project working directory and issuing:</p>
<blockquote>
<p>rm -rf build/ dist/; python setup.py py2app -A; ./dist/MarPlayer.app/Contents/MacOS/MarPlayer</p>
</blockquote>
<p>&nbsp;</p>]]></content:encoded></rss:item><rss:item rdf:about="http://www.noisyair.com/blog/2009/7/29/marsyas-and-cocoa-bridging-objective-c-and-c-code.html"><rss:title>Marsyas and Cocoa: Bridging Objective-C and C++ Code</rss:title><rss:link>http://www.noisyair.com/blog/2009/7/29/marsyas-and-cocoa-bridging-objective-c-and-c-code.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-07-29T16:34:31Z</dc:date><dc:subject>Audio Programming Mac OS Mac OS Marsyas Marsyas audio music information retrieval</dc:subject><content:encoded><![CDATA[<p>As was mentioned, modern Cocoa applications are built using Objective-C, while the Marsyas framework is implemented in C++. Accordingly, a bridge must be established to allow the two to work together. The current OSX (GCC) compiler allows for the mixing of Objective-C and C++ into a hybrid form called Objective-C++. The most comprehensive reference for this material is the Objective-C 2.0 Programming Guide. <br /><br />The compiler recognizes Objective-C++ classes by the file extension <strong>.mm</strong> (typically C++ files have the<strong> .cpp</strong> extension, while Objective-C files have a <strong>.m</strong> extension).</p>
<p>Because both Obj-C and C++ objects are simply pointers, Obj-C objects can be called from C++ code, and vise versa. However, C++ classes cannot inherit from Objective-C superclasses, nor can Objective-C classes inherit from C++ superclasses. Also, be mindful to avoid using keywords in either language for your identifiers. Objective-C reserves words including <strong>class</strong>, <strong>id</strong>, <strong>sel</strong> and <strong>BOOL</strong>.</p>
<p>The remainder of this chapter will illustrate the same application as the last chapter, but will focus on integrating the music playback functionality into a native Cocoa GUI.</p>
<h3>Create an XCode Project</h3>
<p>Create another XCode project. This time choose <strong>Cocoa Application</strong> for the project template:</p>
<p>This will create an empty project linked against the Cocoa framework (Foundation / AppKit / CoreData) and will contain the default application NIB file. Next, repeat the steps outlined in the previous chapter to include Marsyas into the project:</p>
<ul>
<li>Link against CoreAudio, CoreFoundation and CoreMIDI.</li>
<li>Link against libmarsyas.a and other optional libs (e.g. libmad.a).</li>
<li>Update the header search path to include the Marsyas header files.</li>
</ul>
<h3>Design the NIB File</h3>
<p>Open the NIB file and create a layout similar to the following figure:</p>
<p>The window is large enough to accommodate three items:</p>
<ul>
<li> An NSButton to begin audio playback.</li>
<li>An NSButton to stop audio playback.</li>
<li>An NSTextField to display the path of the audio file.</li>
</ul>
<h3>Implement the View Controller</h3>
<p>Technically, the class to be implemented isn't truly a ViewController, as the application is far too simple to require management of views. However the class is responsible for implementing the audio playback functionality (via Marsyas), responding to the user clicking buttons, and updating the filepath text field. <br /><br />In the XCode project, create a class called <strong>MarPlayerWrapper</strong> and have it extend <strong>NSObject</strong>. XCode should create two files: <strong>MarPlayerWrapper.h</strong> and <strong>MarPlayerWrapper.m</strong>. Change the name of the latter file to <strong>MarPlayerWrapper.mm</strong>. The additional "m" in the extension tells the compiler that this file will contain both Objective-C and C++ code. <br /><br />Replace the contents of <strong>MarPlayerWrapper.h</strong> with the following:</p>
<p><code> </code></p>
<pre>#import <br />#include "MarSystemManager.h"<br /><br />@interface MarPlayerWrapper : NSObject {<br />	IBOutlet NSTextField* filenameTextField;	<br />	NSString* filename;<br />	Marsyas::MarSystem* mMarSystem;<br />}<br /><br />@property(nonatomic, retain) IBOutlet NSTextField* filenameTextField;<br />@property(nonatomic, retain) NSString* filename;<br /><br />-(IBAction)startMusic:(id)sender;<br />-(IBAction)stopMusic:(id)sender;<br /><br />@end<br />\<br /></pre>
<p>&nbsp;</p>
<p>This interface is straightforward. There are two properties: The first is an IBOutlet that references the <strong>NSTextField</strong> which displays the path of the audio file, and the second is an <strong>NSString</strong> containing the path. There is also an extra instance variable of type <strong>MarSystem</strong>. It is not a managed property because it will simply be holding a reference to a MarSystem object while the audio is playing. Take note however, that it is acceptable to use C++ objects as Objective-C properties and vise-versa (both are just pointers). There are also two methods: one to begin audio playback and one to stop audio playback. These methods will be connected to the buttons in the NIB file. <br /><br />Next replace the contents of <strong>MarPlayerWrapper.mm</strong> with the following:</p>
<p><code> </code></p>
<pre>#import "MarPlayerWrapper.h"<br /><br />#include <br />#include <br /><br />using namespace Marsyas;<br /><br />@implementation MarPlayerWrapper<br /><br />@synthesize filenameTextField;<br />@synthesize filename;<br /><br />#pragma mark lifecycle methods:<br /><br />-(id)init{<br />	if(self = [super init]){<br />		// change this to a valid path to an audio file on your system:<br />		self.filename = @"/Users/darren/Desktop/song.mp3";	<br />	}<br />	return self;<br />}<br /><br />-(void)awakeFromNib{<br />	[filenameTextField setStringValue:filename];<br />}<br /><br />-(void)dealloc{<br />	self.filename = nil;<br />	self.filenameTextField = nil;<br />	[super dealloc];<br />}<br /><br />#pragma mark User Interface Actions<br /><br />/*<br /> * When the user clicks the play button, the audio will begin<br /> * playback.  Note that this method blocks (well stays in the loop <br /> * until the audio is finished) and thus freezes the UI.  A real<br /> * applicaiton would wrap this method in its own thread (NSOperation)<br /> */<br />-(void)startMusic:(id)sender{	<br />	float gain = 1.0;<br />	// Convert the objective-C string into a C++ string:<br />	std::string songName = [filename UTF8String];<br /><br />	// The rest of this method is all C++ code from the <br />	// previous tutorial.<br />	MarSystemManager mng;<br />	<br />	MarSystem* playbacknet = mng.create("Series", "playbacknet");<br />	// save a reference to the MarSystem as a member of the objective-c<br />	// object so it can be deleted if the user clicks the stop butotn<br />	mMarSystem = playbacknet;<br />	<br />	playbacknet-&gt;addMarSystem(mng.create("SoundFileSource", "src"));<br />	playbacknet-&gt;addMarSystem(mng.create("Gain", "gt"));<br />	playbacknet-&gt;addMarSystem(mng.create("AudioSink", "dest"));<br />	<br />	playbacknet-&gt;updctrl("SoundFileSource/src/mrs_string/filename", songName);<br />	playbacknet-&gt;updctrl("Gain/gt/mrs_real/gain", gain);<br />	playbacknet-&gt;updctrl("AudioSink/dest/mrs_bool/initAudio", true);<br />	<br />	while ( playbacknet-&gt;getctrl("SoundFileSource/src/mrs_bool/notEmpty")-&gt;to() )<br />	{<br />		playbacknet-&gt;tick();<br />	}<br />	delete playbacknet;<br />}<br /><br />/* <br /> * Crude: for demo purposes only. The audio should<br /> * be playing on a separate thread, apart from the<br /> * UI<br /> */<br />-(void)stopMusic:(id)sender{<br />	delete mMarSystem;<br />}<br /><br />@end<br /></pre>
<p>&nbsp;</p>
<p>Most of the excitement here happens in the <strong>startMusic</strong> method. Within this Objective-C method, the original C++ code from the last chapter is worked in. Notice how the (char*) value of an <strong>NSString</strong> is extracted with the <strong>UTF8String</strong> method. This allows it to be set as a C++ string. One other thing to point out is how the while loop repeats until the audio is finished playing. Because this is occurring on the main thread (the same thread as the user interface), the UI will be drastically affected. For this reason, a separate thread should be used to actually play the audio. This can be done very simply with the <strong>NSOperation</strong> and <strong>NSOperationQueue</strong> classes. <br /><br />Finally, notice how the <strong>MarSystem</strong> object is a pointer, but the <strong>MarSystemManager</strong> is allocated on the stack. Either is acceptable within the hybrid Objective-C++ system. You can even declare stack C++ objects as Objective-C properties: they are allocated and deallocated in the corresponding alloc and dealloc methods. Be warned though that the object models for C++ and Objective-C are quite different. Memory must be managed specific to each environment (new/free for C++, alloc/dealloc for Objective-C).</p>
<h3>Wire up the UI</h3>
<p>Return to the main NIB within Interface Builder. Add a new Object to the nib file and set its class to <strong>MarPlayerWrapper</strong>. The available outlets and actions should be immediately available for connections. Create an outlet connection from the new object to the <strong>NSTextView</strong>, and wire up the two actions for the NSButtons.</p>
<p>The result is a working Cocoa GUI application that plays audio via Marsyas. Click the <strong>Build and Go</strong> hammer to test out the application. Notice now laggy the UI becomes once the audio starts. This is because of the audio code hogging the main thread.</p>]]></content:encoded></rss:item><rss:item rdf:about="http://www.noisyair.com/blog/2009/7/29/creating-a-hello-world-application-with-marsyas-and-xcode.html"><rss:title>Creating a Hello World Application with Marsyas and XCode</rss:title><rss:link>http://www.noisyair.com/blog/2009/7/29/creating-a-hello-world-application-with-marsyas-and-xcode.html</rss:link><dc:creator>Darren Minifie</dc:creator><dc:date>2009-07-29T16:11:55Z</dc:date><dc:subject>Audio Programming Mac OS Mac OS Marsyas Marsyas audio iPhone music information retrieval</dc:subject><content:encoded><![CDATA[<p>This section describes the steps needed to build a simple application in XCode, that makes use of the functionality Marsyas has to offer. If building XCode projects is already familiar, the major differences here will be the inclusion of the libmarsyas.a static library, modifying the header search path to find Marsyas headers, and linking against the required OSX frameworks.</p>
<h3>Create an XCode Project</h3>
<p>Open XCode and select <strong>New Project</strong> from the File menu. For a template, choose the <strong>C++ Tool</strong> located in the <strong>Command line utility</strong> group:</p>
<p>Name the project and click finish.</p>
<h3>Alter main.cpp</h3>
<p>The demo project is a simple, one-file program that uses Marsyas to play back an audio file. This example can be found in the Marsyas User Manual. Replace the code in <strong>main.cpp</strong> with the following:</p>
<p><code> </code></p>
<pre>#include <br />#include "/Users/darren/development/mylibs/marsyas/src/marsyas/MarSystemManager.h"<br />using namespace std;<br />using namespace Marsyas;<br /><br />void sfplay(string sfName, float gain)<br />{<br /> MarSystemManager mng;<br /> <br /> MarSystem* playbacknet = mng.create("Series", "playbacknet");<br /> <br /> playbacknet-&gt;addMarSystem(mng.create("SoundFileSource", "src"));<br /> playbacknet-&gt;addMarSystem(mng.create("Gain", "gt"));<br /> playbacknet-&gt;addMarSystem(mng.create("AudioSink", "dest"));<br /> <br /> playbacknet-&gt;updctrl("SoundFileSource/src/mrs_string/filename", sfName);<br /> playbacknet-&gt;updctrl("Gain/gt/mrs_real/gain", gain);<br /> playbacknet-&gt;updctrl("AudioSink/dest/mrs_bool/initAudio", true);<br /> <br /> while ( playbacknet-&gt;getctrl("SoundFileSource/src/mrs_bool/notEmpty")-&gt;to() )<br /> {<br /> playbacknet-&gt;tick();<br /> }<br /> delete playbacknet;<br />}<br /><br />int main(int argc, const char **argv)<br />{<br /> string fileName;<br /> float gain;<br /> if (argc&lt;2)<br /> {<br /> cout&lt;&lt;"Please enter filename."&lt;&lt;3)<br /> {<br /> gain = 1;<br /> }<br /> else<br /> {<br /> gain = atof(argv[2]);<br /> }<br /> cout &lt;&lt; "Playing file " &lt;&lt; fileName &lt;&lt; " at volume " &lt;&lt;<br /> gain &lt;&lt; endl;<br /> <br /> sfplay(fileName,gain);<br /> exit(0);<br />}<br /></pre>
<p>Attempting to build at this point will result in errors because the compiler has no information about the Marsyas namespace and types. This is remedied by adding a directory to the header search path.</p>
<h3>Add Marsyas Headers to the Search Path</h3>
<p>To find the appropriate header files, add the <strong>src/marsyas/</strong> Marsyas directory to the project search path. Under <strong>Targets</strong> double click the project executable target:</p>
<p>From the newly presented window, select the <strong>build</strong> tab. Enter the phrase <strong>header search</strong> into the window's search box to filter the options. Of the three options that remain, select the <strong>Always Search User Paths</strong> checkbox. Add a new entry into the <strong>User Header Search Paths</strong> field. The entry should be the Marsyas <strong>src/marsyas/</strong> directory. The full path will depend on where Marsyas is installed. An example entry would be:</p>
<p>Two things to note here: First, be warned that errors may result if the path to a library or header is too long. Second, the path to the <strong>src/marsyas/</strong> should end with a / character.</p>
<p>With the new search directory in place, XCode should be able to find the Marsyas headers. At the top of the <strong>main.cpp</strong> file, start typing:</p>
<blockquote>
<p>#include "MarSystemManager.h"</p>
</blockquote>
<p>XCode should autofill the remainder of the typed phrase to suggest possible Marsyas headers.</p>
<h3>Link Against Marsyas and Core Frameworks</h3>
<p>The last step to a working application is to link the project against the static Marsyas library that was built previously. Also, because Marsyas relies on Core Audio, Core MIDI and Core Foundation, the project must be linked against them as well. <br /><br />Begin by double clicking the sub-item under the <strong>targets</strong> icon. The build window will appear. Select the <strong>general</strong> tab. Click on the <strong>+</strong> icon in the bottom left corner to add libraries and frameworks. From the popup list select <strong>CoreAudio</strong>, <strong>CoreMIDI</strong> and <strong>CoreFoundation</strong>, then click the <strong>Add</strong> button. The three frameworks should be added to the project. Again click the <strong>+</strong> to add another library. This time click the <strong>Add Other...</strong> button. Navigate to the Marsyas <strong>build/lib</strong> directory and add the <strong>libmarsyas.a</strong> static library. <br /><br />A new window will appear. Check the <strong>Copy items into destination group's folder</strong> checkox. Change the Reference Type to <strong>relative to project</strong>, then click <strong>Add</strong>. The target tab should look like this:</p>
<p>Finally, if <strong>libmad</strong> is included for mp3 support, it needs to be included as well. Click the<strong> +</strong> button in the <strong>Targets</strong> window, select <strong>Add Other...</strong>, navigate to the <strong>MacPorts</strong> directory where libmad was installed (for example it may be <strong>/opt/local/lib</strong> and add the <strong>libmad.a</strong> static library. <br /><br />The project should now compile without any errors.</p>
<h3>Test the Application</h3>
<p>This simple application uses Marsyas to play back an audio file. As such, it looks for a commandline argument, the filename of the audio, at startup. Adding commandline arguments in XCode is easy.</p>
<p>First, determine the full path of a sound file on the local machine. This can be done by viewing the <strong>get info </strong>menu on any track within iTunes. Copy the full path.</p>
<p>Back in XCode, double click the first item under the <strong>Executables</strong> tab. A new window will appear. Select the <strong>Arguments</strong> tab and add a new argument. Paste in the file name (it should be a valid path and file for example: <strong>/Users/name/iTunes/path/to/song.mp3</strong>. Finally, click on the<strong> Build and Go</strong> hammer. The project should compile properly and the given song will begin to play.</p>]]></content:encoded></rss:item></rdf:RDF>