<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-130402213334709639</id><updated>2012-01-29T10:37:55.899-09:00</updated><category term='peace'/><title type='text'>pkaudio</title><subtitle type='html'>The future will be pixelized.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default?start-index=101&amp;max-results=100'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>124</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-3023438706773894330</id><published>2011-12-03T18:17:00.001-09:00</published><updated>2011-12-03T18:25:30.004-09:00</updated><title type='text'>User Interaction - The Next Step</title><content type='html'>&lt;br /&gt;The best thing about the iPad. Man, we dev monkeys have known for a long time that something like the iPad was a good idea. Remember how touchscreens were like this mystical feature into a world of futuristic interfaces for so long? Like how engaging warp nine was totally the shit in conceptual whiteboard land but never actually a reality until a little PC vendor finally struck gold with a good design?&lt;br /&gt;&lt;br /&gt;So why was this such a cool idea for all those years? What message was in our deepest gut that said at we wanted iTouch everything? Now hat we finally have this platform well-deployed and it's the most popular consumer electronics item of our lifetime (of all time?), what do we do with it? What's next? What now?&lt;br /&gt;&lt;br /&gt;I think the answer is we push the envelope of user interface design with good graphics, wacky paradigms, and new ways of looking at problems. We are finally at a point where the door is open for the average developer to make the next big advancement, and it's all about the idea.&lt;br /&gt;&lt;br /&gt;For one small example, sketching with AutoDesk SketchPad pro is incredible. It won't replace pencil and paper for everything, but does a lot of things pencil and paper can't do. You can quickly and fearlessly fearlessly move through ideas with undo and by adding new layers. You can try combos of brushes and blending that would never be possible on the old medium. This means you've got a new tool with a new niche - not just a toy.&lt;br /&gt;&lt;br /&gt;We've had visualizations for music for some time. They've always &lt;i&gt;looked&lt;/i&gt; cool, but is it possible that they&lt;i&gt; help us think about the music better&lt;/i&gt;?&lt;br /&gt;&lt;br /&gt;What can the machine do that we could never do before? What other ways can we show the data? What new angle can we present the problem? Nothing other than unbridled creativity can answer those questions.&lt;br /&gt;&lt;br /&gt;My favorite pet puzzle is finding a way to push the envelope with live music production - and more specifically with music sequencing (writing out a part for an instrument). Just like finger painting, making music is something that is completely human and an art form where computers can make a big difference in helping humans become even more human.&lt;br /&gt;&lt;br /&gt;The obvious iPad answer is to resell software reproductions of classic hardware synthesizers with beautifully crafted interfaces like the Korg iMS-20, or iElectribe. Plugging a MIDI keyboard in using the camera connection kit means the iPad can be a real, usable musical instrument and can save us thousands of dollars on the hardware counterparts.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-zK-9yVOFezA/TtrnC6wnbCI/AAAAAAAAAn8/oXSZBOC__FY/s1600/KaossPad-003.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="233" src="http://4.bp.blogspot.com/-zK-9yVOFezA/TtrnC6wnbCI/AAAAAAAAAn8/oXSZBOC__FY/s320/KaossPad-003.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Kaoss Pad - So much fun with a low-pass filter.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Bt what next? What about new ways of designing the sounds or composing the music? In my humble opinion, the best interface for writing a drum part is &lt;a href="http://www.soundonsound.com/sos/dec04/articles/roland.htm"&gt;still 30 years old&lt;/a&gt;, and I feel like that is going to change very soon (remember all that techno from 10-15 years ago? Yeah, that's where it came from). It's time to try new ideas, like improving the workflow for live MIDI recording arrangement to build a better musical whiteboard. Or building on the clunky grid-based midi sequence editor that every music composition program seems to have settled on as "good enough".&lt;br /&gt;&lt;br /&gt;It's all about the features that &lt;i&gt;really matter&lt;/i&gt;. For example, if Garage Band for the iPad relied on the built-in keyboard or a shitty 16-step drum sequencer like all the other apps, it would be a very cool and utterly worthless gimmick. Adding a line-in to record real instruments makes it an incredible mixing and arranging tool.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-nosQNEhGzpI/Ttrn0OeBPfI/AAAAAAAAAoM/Z1HbaWhy7x8/s1600/Roland%252520TR-808.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="185" src="http://1.bp.blogspot.com/-nosQNEhGzpI/Ttrn0OeBPfI/AAAAAAAAAoM/Z1HbaWhy7x8/s320/Roland%252520TR-808.jpg" width="320" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Roland TR-808, and the classic 16-step drum sequencer. &lt;br /&gt;We haven't moved much past this for drums and synth lines.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;It's all about the &lt;i&gt;ideas&lt;/i&gt;. Rebuilding a cheaper and more portable version of something old is step one, but running with that old concept and making something new is the next step. This means breaking the mold, thinking outside the box, and not being afraid of failure. Presenting instrument tracks as 3D interactive planets, or adjusting the alpha channel of their colors to display their relevance in the mix, or drawing on modern empirical response studies and data visualization techniques to generate a good overview of the musical concept you are trying to put down are examples of things developers haven't tried.&lt;br /&gt;&lt;br /&gt;I put stuff like this on this blog because I feel they have relevance to the general world of software design. What an amazing time we are living in.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-3023438706773894330?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/3023438706773894330/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=3023438706773894330' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3023438706773894330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3023438706773894330'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/12/user-interaction-next-step.html' title='User Interaction - The Next Step'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-zK-9yVOFezA/TtrnC6wnbCI/AAAAAAAAAn8/oXSZBOC__FY/s72-c/KaossPad-003.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-239966862835401444</id><published>2011-12-01T10:29:00.001-09:00</published><updated>2011-12-01T15:16:09.765-09:00</updated><title type='text'>Prototyping</title><content type='html'>We've been having a hell of a (great!) time stitching together a new creative process with a new team here in the office. The company is already producing some really great 3d models, and I have been hired to head up the software effort to make those models interactive. Go touchscreen, go!&lt;br /&gt;&lt;br /&gt;Something that has struck me lately is generally how bad developers are at PROTOTYPING. Now don't get me wrong, I don't mean this in a negative way. Instead I think that our tools have held us back for a while, but our tools are getting really good really fast and I think we have a lot of work to do in order to find a place in the creative process.&lt;br /&gt;&lt;br /&gt;I've been talking to freelance developers and a few studios trying to find the right people to build a couple of key visual components for our first big job building touchscreen interactives. Meanwhile, we have been working hard to get our conceptual design done in parallel. So I'm having a look at how we are communicating our ideas and finding visual examples to illustrate what our ideas actually MEAN - and the whiteboard is just not cutting it.&lt;br /&gt;&lt;br /&gt;Sure we still need the whiteboard, but not for more than a conversational tool. What we really need is to spend a smaller amount of time describing what we need, and more time building real examples in a timely fashion. A picture is worth 1,000 words, and here an animation is worth closer to 10,000 words! The only goal here is to produce a rich touchscreen experience, so this stuff is super important.&lt;br /&gt;&lt;br /&gt;I'm getting the idea that most creative companies have their people make a bunch of prototypes, and then they go with the best option (Anyone seen Mad Men? Read a Steve Jobs book?). This means you have to burn time, and you also have to master your tools so that you can spend your time thinking about the big picture and less time thinking about the code. This brings me to my point.&lt;br /&gt;&lt;br /&gt;I am looking at where we are as developers and I think that we are juuuuuust almost there - at least in the visual and interactive design realm. We need to take the next step and get even better at our tools so we can do this. If a client comes up with a concept, we shouldn't need to have them spec out the whole animal for us before we build something. Instead we need to be so good at our tools that we can put all of our effort into interpreting the big picture and the code is nothing more than an after thought. I mean, we can spend all day talking about methodologies and "agile" and waterfall whatever blah blah blah, but at then end of the day we need to be able to quickly write something or a few somethings "for free" to get a tangible illustration of the idea in front of the right people at the right time.&lt;br /&gt;&lt;br /&gt;I think this means for a WebGL or CSS3 interactive we need to be able to turn a working example around in a couple of days. Then when someone says we need to rotate the camera around not one but all objects in the scene at once, we need to be able to turn that around in an hour. If we want to turn all the circles into squares and have them rotate around the axis instead of constantly looking at the camera, it should take 20 minutes.&lt;br /&gt;&lt;br /&gt;You can see how these ideas would be hard to illustrate since there's several ways that we can interpret these simple few statements. Seeing it work is everything. Also it's important for a developer to not take the instructions literally but to interpret them as solutions to the problem, and write prototypes that solve the problem. No one likes a monkey.&lt;br /&gt;&lt;br /&gt;On the same note, we eventually narrowed our focus to only hiring guys that have portfolios of prior work to show. We needed to SEE what they've put together to get a feel for what they can do. We also gave them a couple of days to put together a prototypical example of how they would approach our problem - off the clock. This seems to be the way of business in other creative industries, and I think it should be the way it works with software as well.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img src="webkit-fake-url://7549F838-A85B-4280-901F-59540D3B8846/image.tiff" /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-239966862835401444?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/239966862835401444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=239966862835401444' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/239966862835401444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/239966862835401444'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/12/prototyping.html' title='Prototyping'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-4501422963165864942</id><published>2011-11-11T18:15:00.001-09:00</published><updated>2011-11-11T18:16:08.879-09:00</updated><title type='text'>PKAudio Wordle</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-5zPjFvw-k90/Tr3k3gvCt2I/AAAAAAAAAnc/B-l8107BEpA/s1600/pkaudio_wordle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="436" src="http://1.bp.blogspot.com/-5zPjFvw-k90/Tr3k3gvCt2I/AAAAAAAAAnc/B-l8107BEpA/s640/pkaudio_wordle.png" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-4501422963165864942?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/4501422963165864942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=4501422963165864942' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4501422963165864942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4501422963165864942'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/11/pkaudio-wordle.html' title='PKAudio Wordle'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-5zPjFvw-k90/Tr3k3gvCt2I/AAAAAAAAAnc/B-l8107BEpA/s72-c/pkaudio_wordle.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6354527441252644191</id><published>2011-10-27T16:25:00.003-08:00</published><updated>2011-10-27T16:27:03.976-08:00</updated><title type='text'>Open Terminal from Finder Window</title><content type='html'>- Create an automator application with the following AppleScript and save it somewhere.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 28.8px; text-indent: -28.9px;"&gt;on run&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 43.2px; text-indent: -43.2px;"&gt;&amp;nbsp; tell application "Finder"&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 57.6px; text-indent: -57.6px;"&gt;&amp;nbsp; &amp;nbsp; try&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 72.0px; text-indent: -72.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; activate&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 72.0px; text-indent: -72.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; set frontWin to folder of front window as string&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 72.0px; text-indent: -72.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; set frontWinPath to (get POSIX path of frontWin)&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 72.0px; text-indent: -72.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; tell application "Terminal"&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 86.4px; text-indent: -86.5px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; activate&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 86.4px; text-indent: -86.5px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; do script with command "cd \"" &amp;amp; frontWinPath &amp;amp; "\""&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 72.0px; text-indent: -72.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; end tell&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 57.6px; text-indent: -57.6px;"&gt;&amp;nbsp; &amp;nbsp; on error error_message&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 72.0px; text-indent: -72.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; beep&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 72.0px; text-indent: -72.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; display dialog error_message buttons¬&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 72.0px; text-indent: -72.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {"OK"} default button 1&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 57.6px; text-indent: -57.6px;"&gt;&amp;nbsp; &amp;nbsp; end try&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 43.2px; text-indent: -43.2px;"&gt;&amp;nbsp; end tell&lt;/div&gt;&lt;div style="color: #911993; font: 12.0px Courier; margin: 0.0px 0.0px 0.0px 28.8px; text-indent: -28.9px;"&gt;end run&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;- Right-click the finder toolbar and customize it by dragging the automator application onto the toolbar.&lt;/div&gt;&lt;div&gt;- Change the automator application icon by running "Get Info" on Terminal.app &lt;i&gt;as well as&lt;/i&gt;&amp;nbsp;the automator application, and dragging the large Terminal icon onto the icon for the automator application. It should change in the Finder.&lt;/div&gt;&lt;div&gt;- Open a Finder window, navigate to a folder, click the button.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-EB6NVvj1M_4/Tqn1Cvj0NiI/AAAAAAAAAnA/P_dQprlPTiM/s1600/Untitled+2.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="476" src="http://3.bp.blogspot.com/-EB6NVvj1M_4/Tqn1Cvj0NiI/AAAAAAAAAnA/P_dQprlPTiM/s640/Untitled+2.jpg" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Make this&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-wZ5nSKsfVnk/Tqn1EPJDkOI/AAAAAAAAAnI/F_nCNvhpWds/s1600/Untitled.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="211" src="http://2.bp.blogspot.com/-wZ5nSKsfVnk/Tqn1EPJDkOI/AAAAAAAAAnI/F_nCNvhpWds/s640/Untitled.jpg" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;And you'll get this&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-bvffRJ8FrSc/Tqn2fZWNAuI/AAAAAAAAAnQ/aorgwSFb1Po/s1600/Screen+Shot+2011-10-27+at+4.25.11+PM.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-bvffRJ8FrSc/Tqn2fZWNAuI/AAAAAAAAAnQ/aorgwSFb1Po/s1600/Screen+Shot+2011-10-27+at+4.25.11+PM.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Then you'll get this&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6354527441252644191?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6354527441252644191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6354527441252644191' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6354527441252644191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6354527441252644191'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/10/open-terminal-from-finder-window.html' title='Open Terminal from Finder Window'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-EB6NVvj1M_4/Tqn1Cvj0NiI/AAAAAAAAAnA/P_dQprlPTiM/s72-c/Untitled+2.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-4309046173278787474</id><published>2011-10-22T11:56:00.002-08:00</published><updated>2011-10-22T11:56:42.720-08:00</updated><title type='text'>New Twitter Account</title><content type='html'>I've separated my athletic / personal twitter account with my software / music / art twitter account. The old "pkaudio" is now called "plasteredskier" and I've created a new empty "pkaudio" account. Hope to see you followers back there again.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-4309046173278787474?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/4309046173278787474/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=4309046173278787474' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4309046173278787474'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4309046173278787474'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/10/new-twitter-account.html' title='New Twitter Account'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2805811464506717301</id><published>2011-09-14T16:06:00.000-08:00</published><updated>2011-09-14T16:06:07.882-08:00</updated><title type='text'>Separation of Ego and Will</title><content type='html'>&lt;br /&gt;I believe the path to enjoyment through excellence lies through the heart more than the average athlete. The Ego drives so much of our lives, and thus can quickly get out of control and throw our lives of course. Because of this, it's easy to think that removing the Ego from the equation would coax forth an untamable beast of pure power and athletic perfection.&lt;br /&gt;&lt;br /&gt;About four years ago I remember a day where I found a really nice rhythm on the track, sort of like a place to put my mind while pushing my body over the limit. I remember imagining a max pace that would work for that distance and then just sort of hang my body on it, like a person hangs a coat on a hook. It felt right because it was juuuust the right balance between fast and slow for that distance. I was amazed at what this small change in attitude did for my performance.&lt;br /&gt;&lt;br /&gt;I didn't know it then, but I was getting my first glimpse of a balance between Ego and Will.&lt;br /&gt;&lt;br /&gt;The "Ego" is your rational mind that drives you to compete and judge yourself alongside your external world. It is the ego that keeps you alive, and conversely it is the ego that causes performance anxiety.&lt;br /&gt;&lt;br /&gt;The "Will" is your innate, inner tendency towards peace. It is the subconscious personality that thrives on warm fuzzy feelings, or gives you that incredibly serene sensation of unity that comes on a solo day in the mountains when you could care less about races and glory. The Will is a factor of the "you", if the rest of the world didn't exist.&lt;br /&gt;&lt;br /&gt;All of us in the western world are very well acquainted with The Ego, myself included. For the past few years I have been trying to learn how to run purely by Will, keeping the ego and its mischief out of my experiences. I have believed that there is an animal inside that wants to run and become strong and conquer all, and the true meaning of success meant letting this animal drive 100% of my athletic life. Today I don't think that this is the case.&lt;br /&gt;&lt;br /&gt;Just like that day on the track, I think that pure life (and fast race times) comes from a balance of The Ego and The Will. Not only is this balance extremely difficult to find, but it requires that you have a comfortable relationship with your Ego, and a comfortable relationship with your Will, both as separate entities.&lt;br /&gt;&lt;br /&gt;For the average American, learning to listen to your innate Will *alone* is the challenge of a lifetime. Learning to play with both, and then demonstrate the fine balance required to crush a race without anxiety and with predictable gratification is a challenge for only the most elite of athletes. I feel like less than 1% of any community truly has this balance.&lt;br /&gt;&lt;br /&gt;I've had a couple of good runs with this on my mind lately. The next time I head out and start to push it, I'm not going to crush my Will into submission like the usual hammerhead. But I'm also not going to shut out my Ego in favor of endless calm and peace. Instead, I'm going to ask both what each is feeling at the same time, strike a balance, and crush forth with endless calm.&lt;br /&gt;&lt;br /&gt;Trippy&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2805811464506717301?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2805811464506717301/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2805811464506717301' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2805811464506717301'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2805811464506717301'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/09/separation-of-ego-and-will.html' title='Separation of Ego and Will'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-129867683751269379</id><published>2011-08-30T12:08:00.001-08:00</published><updated>2011-08-30T12:09:48.532-08:00</updated><title type='text'>Two Parallels</title><content type='html'>In music, we figured out how to get machines to make music for us, and how to use a killer sample or two to make it sound good. But, our listeners are getting tired of hearing a killer sample over and over again. Now, our challenge is to get our music back to a level where the &lt;i&gt;entire&lt;/i&gt; song uses unique, expressive, humanistic elements.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Time to raise the bar.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In computing, we figured out how to get machines to remember everything for us, and to recall and reshape it for us faster than we ever could. But, our users are growing tired of us saying "I'll just add a checkbox for that." Now, our challenge is to make the checkbox go away.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Time to raise the bar.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-r5kGHZHi6YQ/Tl1DPx0TiaI/AAAAAAAAAm8/PA6hwWviu50/s1600/michael-johnson-track-photo.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-r5kGHZHi6YQ/Tl1DPx0TiaI/AAAAAAAAAm8/PA6hwWviu50/s1600/michael-johnson-track-photo.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-129867683751269379?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/129867683751269379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=129867683751269379' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/129867683751269379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/129867683751269379'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/08/two-parallels.html' title='Two Parallels'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-r5kGHZHi6YQ/Tl1DPx0TiaI/AAAAAAAAAm8/PA6hwWviu50/s72-c/michael-johnson-track-photo.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-3606690222940623349</id><published>2011-08-27T19:50:00.001-08:00</published><updated>2011-08-27T20:23:46.192-08:00</updated><title type='text'>Impermanence</title><content type='html'>It occurred to me the other day that a major flaw in the new technologies that we are enjoying so much today is that very few of the incredible works they are allowing us to produce will be around for very long. This makes me very sad.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For example, if a graphic designer sits down and produces an incredible web page and loves it like a piece of art, he may not be able to enjoy it again several years down the line because the programs that allowed the piece of art to took, behave, and feel so inspiring will not exist in the state that they do today. The font rendering may change, or the browsers will not support the programming language, or we simply won't have web pages.&lt;br /&gt;&lt;br /&gt;Sadly, the same goes for some forms of music.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In my last job I developed software-based musical instruments that relied on a custom engine to play the thousands and thousands of meticulously recorded audio samples used in to reproduce a single instrument. These instruments were beautifully crafted by sound designers and recording engineers through months and years of work. The engine runs as a plugin inside mixing applications that rely heavily on the bleeding-edge technologies of today. Thus, it is likely that all of our years of meticulous toil won't even make it past the next operating system version because the plugin standard may change, the host software may not be supported, etc. A small piece of this work may live on in the musical recordings they were played in, but the instrument itself will &lt;i&gt;DIE&lt;/i&gt;. And it will likely die very, very soon.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So I want to ask: Are we considering this extremely unfortunate loss as we cruise blindly into this high wave of technological expansion? How much art will we lose to this sad fact, and how much have we already lost? With the exception of old-style, static media like photos, videos, and audio, do we even consider the interactive and functional art that we are making today &lt;i&gt;worthy&lt;/i&gt; of being saved?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If not, then that would make me saddest of all.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://www.longnow.org/" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-71LwvgrTCd4/TlmzmVS93TI/AAAAAAAAAmw/E_QAB0l3SLc/s1600/longnow.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;&lt;a href="http://longnow.org/"&gt;The Long Now Foundation is devoted to exactly this startling fact of modern impermanence.&amp;nbsp;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-3606690222940623349?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/3606690222940623349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=3606690222940623349' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3606690222940623349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3606690222940623349'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/08/impermanence.html' title='Impermanence'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-71LwvgrTCd4/TlmzmVS93TI/AAAAAAAAAmw/E_QAB0l3SLc/s72-c/longnow.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5273567180174745633</id><published>2011-08-27T19:32:00.002-08:00</published><updated>2011-08-27T20:32:20.805-08:00</updated><title type='text'>Elated</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Q1BQO-ztVh0/TlmfJ6dtWiI/AAAAAAAAAms/KpvDwcn9WYc/s1600/elated.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-Q1BQO-ztVh0/TlmfJ6dtWiI/AAAAAAAAAms/KpvDwcn9WYc/s1600/elated.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;I wanted to call this post "giddy", but it turns out that word means "having a&amp;nbsp;&lt;span apple_mouseover_highlight="1"&gt;sensation&lt;/span&gt;&amp;nbsp;&lt;span apple_mouseover_highlight="1"&gt;of&lt;/span&gt;&amp;nbsp;&lt;span apple_mouseover_highlight="1"&gt;whirling&lt;/span&gt;&amp;nbsp;&lt;span apple_mouseover_highlight="1"&gt;and&lt;/span&gt;&amp;nbsp;a&amp;nbsp;&lt;span apple_mouseover_highlight="1"&gt;tendency&lt;/span&gt;&amp;nbsp;&lt;span apple_mouseover_highlight="1"&gt;to&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;&amp;nbsp;fall or stagger; dizzy". Not really the feeling I was going for.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;But, I digress.&lt;br /&gt;&lt;br /&gt;I am elated at the direction the web is going in. I am most excited with how far from "web" the web is actually becoming. Watching the web browser become the future of visual expression is exciting, and while in some ways the HTML/CSS/JS triumvirate is tearfully clutching pieces of the technology that really truly just...need...to...die, it's story is a wonderful example of an organic and purpose-full evolution.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;div&gt;It started out as a simple way to link together and transmit simple text documents, and after a long, strangely stitched labor, it is giving birth to inspiring new ways of visually expressing ideas and information. I mean, JavaScript used to suck, and it can now be used to generate incredibly smooth and colorful 3D content (canvas, WebGL, etc...). I'd say I was excited when I saw python for the first time in 1999, but I have never been this excited about anything related to computers before.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is because I feel like computing is finally growing up. It is no longer strange but is now mainstream, and has rich purposes that people can relate to without having to think that a computer is even there. Today we aren't so much trying to get computers to help us do things we have &lt;i&gt;already been doing for centuries&lt;/i&gt;, like allow us to read books, look at paintings, or just play chess. Instead, they are finally allowing us to do things that we have &lt;i&gt;never been able to do before&lt;/i&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We can create &lt;i&gt;new&lt;/i&gt; kinds of music that would have never&amp;nbsp;before&amp;nbsp;been possible. We can express &lt;i&gt;new&lt;/i&gt; ideas in &lt;i&gt;new&lt;/i&gt; ways using animations, interactivity, and multiple media at the &lt;i&gt;same time&lt;/i&gt;. We can create fine art that becomes new art all on its own because it interacts with other art. Above all, we can actually be &lt;i&gt;more creative&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;Because of this, I am in awe and inspired by the "web". If the true test of a language is implementing itself in itself, then the technology of computing is redefining this test because we have used programming languages to invent new ways to write programming languages - the web browser is becoming the next generation of the computer operating system. Standing on the shoulders of giants we are, no doubt.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-KOjDvIke1PU/TlnEaImm2SI/AAAAAAAAAm4/EEPhZxi2DUw/s1600/three.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-KOjDvIke1PU/TlnEaImm2SI/AAAAAAAAAm4/EEPhZxi2DUw/s1600/three.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Three.js: The page that inspired this blog post.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;div&gt;&lt;hr /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was talking with someone earlier today about some work involving interactive presentations, and realized that I was starting to think so far outside the box that the computer part of the equation wasn't really part of the equation any more. Sure, we know that we were going to use computers for the job, but I wasn't really thinking in terms of what the technology would &lt;i&gt;allow&lt;/i&gt; us to&amp;nbsp;do; instead I was thinking in terms of what we &lt;i&gt;wanted&lt;/i&gt;&amp;nbsp;to do for the job.&lt;br /&gt;&lt;br /&gt;This is an incredible success for the story of computers.&lt;br /&gt;&lt;br /&gt;In this case the success is largely credited to the fact that web browsers kick so much freaking ass right now. And they are kicking a few more asses every day. We are getting flexible tools, rapid prototyping, and performance that was hard to imagine just five (five!) years ago. All of this means that a decent developer with mediocre web experience can sit down and produce something that can &lt;i&gt;blow his clients away&lt;/i&gt; in a relatively short time frame if he has a good idea.&amp;nbsp;In my humble opinion, this is the very definition of success in design.&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;Thank you to all the giants for all the amazing tools that we are enjoying today.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5273567180174745633?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5273567180174745633/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5273567180174745633' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5273567180174745633'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5273567180174745633'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/08/elated.html' title='Elated'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-Q1BQO-ztVh0/TlmfJ6dtWiI/AAAAAAAAAms/KpvDwcn9WYc/s72-c/elated.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5458450886092710853</id><published>2011-08-14T13:06:00.000-08:00</published><updated>2011-08-14T13:06:59.162-08:00</updated><title type='text'>Tools</title><content type='html'>A quote from a really good book:&lt;br /&gt;&lt;br /&gt;&lt;i&gt;"Design is a process of making, it is the transfer of ideas to a surface by means of tools. Eric Gill used the image of a hand and eye as an emblem in his design. Graphic design exploits the visual and sensual in equal measure.&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;"If the computer deprives us of anything in exchange for its bounteous gifts, it is the physical pleasures of making. When using the (near redundant) letterpress process, every action has an effect: if the ink is carefully thinned, it prints thinly; if the colors are bled, they print that way, but differently each time; you can see the dust from the paper swirling in the sunlight; you can hear the treacle crackle as you ink the roller; you reel at the bitter smell of the turpentine. Each little piece of type bytes itself into the paper. The surface of work printed by letterpress undulates minutely - the type sinks back, the ink has a sheen. Each print differs, even if only by a fraction, from its fellows.&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;"This loss of sensuality is felt by even the fiercest devotees of digital design: 'What I really want on the Macintosh is a virtual reality interface - armholes in either side of the box so you can reach in and move logos around; a real paintbrush so you can feel the texture of the surface underneath', says Neville Brody.&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;"Perhaps the most important tool of any designer is the voice: calming, cajoling, questioning, and asserting. Design is above all else a social activity: event the simplest letterhead might involve lengthy meetings and discussion with a long cast-list: client, assistant, photographer, plat-maker, printer and paper supplier. The needs of every cast member may vary."&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5458450886092710853?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5458450886092710853/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5458450886092710853' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5458450886092710853'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5458450886092710853'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/08/tools.html' title='Tools'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-638871850369069303</id><published>2011-08-08T19:52:00.001-08:00</published><updated>2011-08-08T19:56:15.582-08:00</updated><title type='text'>More Bliss: All-Keyboard control in OS X?</title><content type='html'>Speaking of bliss... I was just recalling the blissful days of WindowMaker and writing code using nothing but emacs and an xterm. Sub-80 chars and python-mode syntax highlighting...man those were the days. The only thing I used the mouse for was to position and resize my windows once at startup, and I rarely did that because my default wmaker session did that for me! Not using the mouse was so FAST.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-RAyeL9TSedQ/TkCvlIiX1tI/AAAAAAAAAmg/Ga4xMkWVAEQ/s1600/emacs_scripting.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-RAyeL9TSedQ/TkCvlIiX1tI/AAAAAAAAAmg/Ga4xMkWVAEQ/s1600/emacs_scripting.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;....&lt;br /&gt;&lt;br /&gt;Whew! I had to take a breath for a second. &lt;a href="http://pkaudio.blogspot.com/2008/11/style-wars.html"&gt;Here's a previous post about the same thing&lt;/a&gt;, and here's &lt;a href="http://lorenzod8n.wordpress.com/2008/01/27/an-evening-with-window-maker/"&gt;one from another guy on the same page as me&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;These days I use OS X, and I realized how distracted I've become from that special place in my programmer heart! Have any other developers managed to remove the mouse from the equation in OS X? What tricks do you use to keep yourself on the keyboard as much as possible? Shortcuts keys? Apple scripts? tab-tab-tab-tab-tab...tab?&lt;br /&gt;&lt;br /&gt;Peace out.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-638871850369069303?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/638871850369069303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=638871850369069303' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/638871850369069303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/638871850369069303'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/08/more-bliss-all-keyboard-control-in-os-x.html' title='More Bliss: All-Keyboard control in OS X?'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-RAyeL9TSedQ/TkCvlIiX1tI/AAAAAAAAAmg/Ga4xMkWVAEQ/s72-c/emacs_scripting.png' height='72' width='72'/><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6957715770890240899</id><published>2011-08-07T16:04:00.000-08:00</published><updated>2011-08-07T16:04:05.080-08:00</updated><title type='text'>Money in the bank: CSS Text Wrapper</title><content type='html'>&lt;div&gt;Web designers: Say you have a shape on your web page and you want to shrink-wrap text inside or around it. Go check this out.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.csstextwrap.com/#export"&gt;http://www.csstextwrap.com/&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Tbz0dh3K_-o/Tj8n4FZTCKI/AAAAAAAAAmY/bHt7B79uuVo/s1600/Untitled.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://1.bp.blogspot.com/-Tbz0dh3K_-o/Tj8n4FZTCKI/AAAAAAAAAmY/bHt7B79uuVo/s640/Untitled.jpg" width="587" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So cool.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6957715770890240899?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6957715770890240899/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6957715770890240899' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6957715770890240899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6957715770890240899'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/08/money-in-bank-css-text-wrapper.html' title='Money in the bank: CSS Text Wrapper'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-Tbz0dh3K_-o/Tj8n4FZTCKI/AAAAAAAAAmY/bHt7B79uuVo/s72-c/Untitled.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-197186442797852279</id><published>2011-08-05T17:10:00.000-08:00</published><updated>2011-08-05T17:10:05.895-08:00</updated><title type='text'>Reaching the top: Pure Bliss</title><content type='html'>Have you ever reached a state of pure bliss with your code, or technology? Like when you feel like your skills AND ability to see the big picture both reach a high point so that you are able to actually *express* yourself like an artist. It seems like this is only possible when you specialize with a given toolkit and really get your fingers into it, allowing you to actually turn out products at the rate that clients initially EXPECT you too. Pure bliss.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There was a time about 6 years ago when I had barely reached this point doing GUI programming with PyQt. I was able to come up with an idea AND prototype it fast enough so that I could build on the idea without losing the creative spark. A bunch of nice python libraries (including pyrtmidi) came out of this time.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since then I've been forced to change technologies often enough that I haven't been able to really make things sing. This is an interesting phenomenon.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First it was moving from Python to C++, but the slow link/build times were a total show stopper.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Second was writing a Python-based realtime musical effects engine, with features for authoring SWEET custom GUIs. This one had potential for expression both through the GUI programming and the musical effects, but the project changed directions and I found a new job.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Third is HTML/CSS/JavaScript. Here I am today learning something all over again. Sure, it's great having a wide range of skills, but man it would be really sweet to actually hit the elite level for SOMETHING and actually have a shot at experiencing pure bliss.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You know what I mean, right? Like when you run across a project and get that "woah" factor...Man I miss that.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-197186442797852279?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/197186442797852279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=197186442797852279' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/197186442797852279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/197186442797852279'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/08/reaching-top-pure-bliss.html' title='Reaching the top: Pure Bliss'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-7867608319353293964</id><published>2011-07-16T10:26:00.001-08:00</published><updated>2011-07-16T10:40:01.081-08:00</updated><title type='text'>Managing Software Projects: When has it gone RIGHT?</title><content type='html'>It occurred to me yesterday that I have never seen a software project managed well. (Almost) Every project I've worked on has had the fortune of excellent talent that has delivered and made someone money, but the developers always get burned out doing it.&lt;br /&gt;&lt;br /&gt;Is this just the nature of the industry? Is it not actually as profitable as we once thought? Sure, it seems that there is never enough time or money in any business, but I just have this feeling that it doesn't have to feel as catastrophic as I've seen it.&lt;br /&gt;&lt;br /&gt;My very humble hunch is that we as developers (and people) have not properly asked ourselves this one question:&lt;br /&gt;&lt;br /&gt;"What do I have that will allow me to do this better than it has been done in the past."&lt;br /&gt;&lt;br /&gt;I think that too often our answer is: "We have good skills, and we are ambitious," and I think that that answer is not good enough. I think that software is still new and not enough of us have an experiential understanding of how software (and developer resources!) mature through development, testing, and maintenance phases. If we do have that understanding, I think we are not good enough communicators to apply it to our boss' and clients' expectations.&lt;br /&gt;&lt;br /&gt;A lot of us has read the &lt;a href="http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959/ref=sr_1_1?ie=UTF8&amp;amp;qid=1310840234&amp;amp;sr=8-1"&gt;Mythical Man Month&lt;/a&gt;, but has anyone actually been on a successful project? Has anyone been happy enough with the life cycle of a product to be willing to go through it again in the same way? If so, I'd really love to hear about it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-7867608319353293964?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/7867608319353293964/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=7867608319353293964' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7867608319353293964'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7867608319353293964'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/07/managing-software-projects-when-has-it.html' title='Managing Software Projects: When has it gone RIGHT?'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-3781068573079733565</id><published>2011-07-02T12:14:00.000-08:00</published><updated>2011-07-02T12:14:22.367-08:00</updated><title type='text'>Scaling with Virtual Machines</title><content type='html'>One new thing since my real-world hiatus in the music industry is the prevalence of low-cost (like free) virtual machine software. They're cheap, they're stable, now we have linux and windows wherever we want, we can all own macbooks.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This idea is extremely intriguing when you start applying it to deploying server software. It seems to me like we would ideally be deploying a new virtual machine for every app in order to sandbox the application and it's environment. Yeah, a lot of us are stuck in the old timeshare paradigm, but let's look at it in terms of the next level.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;The Desktop&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Start with a developer's desktop machine.&amp;nbsp;I have a maxed-out i7 macbook pro, and run Windows under VirtualBox for IIS/Visual Studio/Office/etc. Then, whenever I start a new linux app, I just tack on a new virtual machine with a hostname matching the project.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;With all machines using a single Mac shared folder, I get to use my favorite app to write code (Coda, in my case) and work within my mac environment. I generally never even look at the virtual hosts' window, just use them as if they were a server somewhere in the closet.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Slick.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;The Servers&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Now this gets really interesting when you start thinking about deploying servers. Ideally we would have one box with an infinite number of virtual machines. Ideally, the OS overhead would be negligible. When you release a new project, you fire up a new virtual machine, install yer stuff, and add a DNS entry. No more site-wide broken apache configs, no more runaway processes, everyone has sudo where they need it with none of the risk. Once you own the hardware, you can do this as much as you want.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In that world hosting is not a problem anymore. You buy hardware resources in bulk and parcel out the pieces.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is where we are going. I wonder how long it's going to take us to get there?&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-3781068573079733565?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/3781068573079733565/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=3781068573079733565' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3781068573079733565'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3781068573079733565'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/07/scaling-with-virtual-machines.html' title='Scaling with Virtual Machines'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1722621517170407</id><published>2011-07-02T01:11:00.000-08:00</published><updated>2011-07-02T01:11:50.425-08:00</updated><title type='text'>My release schedule</title><content type='html'>0) Throw that dumb DDD/FRD schema you learned in college out the window.&lt;br /&gt;&lt;br /&gt;1) Gather requirements. Talk, meet, and outline as much of the system as you can with your poor human brain. Make sure you know your tools well enough to ask the right questions. Compile a list of atomic features that can be checked off by a tester for completion. Call it the FRD. Make estimates.&lt;br /&gt;&lt;br /&gt;2) Implement a working version of the features. Anything obvious that they do, they should do well, but they don't have to do EVERYTHING. Show prototypes to the client for feedback on potentially confusing features whenever possible. Update estimates.&lt;br /&gt;&lt;br /&gt;3) Review the running code with the client to ensure that you haven't forgotten any functional requirements. This does not include bugs. You must learn this difference. Get a final sign off from the client agreeing that the FRD is complete and no additional features are required. This is absolutely critical for your sanity later.&lt;br /&gt;&lt;br /&gt;3) The code is now in "beta". This isn't the stupid flash word that is overused everywhere to mean "new and cool". It means that the client is seeing the code run and providing feedback, and no new features can be added. Only bugs can be fixed, and only without causing new ones. If the client cannot be held responsible for putting the time in to test the code, then you need to find someone that can.&lt;br /&gt;&lt;br /&gt;4) When you feel like you are getting down to the last few show stoppers and you as a developer or project manager feels that the system is stable enough to release, start talking to the client about a deadline for bug submittal. There will always be more bugs. It will never be perfect, but it WILL be USABLE. If they thought that they were paying for perfection, direct them to the nearest meditation hall and instruct them that perfection is only found within.&lt;br /&gt;&lt;br /&gt;5) You are gold. Or, at least your code is. Compensate your employees as well as you can while retaining enough capitol for the next project.&lt;br /&gt;&lt;br /&gt;Repeat.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1722621517170407?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1722621517170407/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1722621517170407' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1722621517170407'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1722621517170407'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/07/my-release-schedule.html' title='My release schedule'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1010496208388674845</id><published>2011-07-02T00:50:00.000-08:00</published><updated>2011-07-02T00:50:21.385-08:00</updated><title type='text'>Beware the "cool" company</title><content type='html'>"Office Space" changed everything. The cubby has been a known death-wish for several years. Grey walls, beige boxes, dorky ties and coffee mugs. Screw that, right?&lt;br /&gt;&lt;br /&gt;These days you see a lot of companies steering clear of that dead and dying image by sprucing up their offices, having more fun group events, shooting toy guns at the bosses, stuff like that. We all think of Google.&lt;br /&gt;&lt;br /&gt;However, beware the "cool" company that wants to be all of those things, but doesn't have the integrity to back it up. Anyone can paint their walls brown and orange, and buy goofy chairs, and talk about how fun it is to work there, but this is not to be confused with signs that the company is actually SUCCESSFUL.&lt;br /&gt;&lt;br /&gt;A group is only really killing it if they are getting shit done first, and being nerds second. When you have pleased the clients, mastered the process, and provided increased security for your work environment, then we can talk about taking off early every day because we are "so laid back."&lt;br /&gt;&lt;br /&gt;"Laid back" companies have either mastered the craft (very rare, you usually know about them for THAT instead), or because the market proved them lucky, which means they will as easily be proved unlucky.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1010496208388674845?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1010496208388674845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1010496208388674845' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1010496208388674845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1010496208388674845'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/07/beware-cool-company.html' title='Beware the &quot;cool&quot; company'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-9155424644072331517</id><published>2011-06-07T15:25:00.000-08:00</published><updated>2011-06-07T15:25:20.597-08:00</updated><title type='text'>Steve Job's 1997 re-hire keynote</title><content type='html'>Steve Jobs’ ‘97 WWDC keynote after being rehired to rebuild apple. Back then they still said “Rhapsody” and “Networking”. The most compelling part is that his message has always been the same even through the iPhone “antennagate” flak: "Stop bitching and build a better product than us."&lt;br /&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="390" src="http://www.youtube.com/embed/3LEXae1j6EY" width="480"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;“The reason Apple was successful is because we weren’t trying to build a company, we were trying to build a computer.”&lt;br /&gt;&lt;br /&gt;Solid gold.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-9155424644072331517?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/9155424644072331517/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=9155424644072331517' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9155424644072331517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9155424644072331517'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/06/steve-jobs-1997-re-hire-keynote.html' title='Steve Job&apos;s 1997 re-hire keynote'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/3LEXae1j6EY/default.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-3127770649498981693</id><published>2011-06-04T11:14:00.020-08:00</published><updated>2011-08-15T20:04:49.881-08:00</updated><title type='text'>And I quote...</title><content type='html'>&lt;br /&gt;&lt;i&gt;"But none of this answers the original question: why do we have an &lt;img /&gt; element? Why not an &lt;icon&gt; element? Or an &lt;include&gt; element? Why not a hyperlink with an include attribute, or some combination of rel values? Why an &lt;img /&gt; element? Quite simply, because Marc Andreessen shipped one, and shipping code wins."&lt;/include&gt;&lt;/icon&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://diveintohtml5.org/past.html"&gt;http://diveintohtml5.org/past.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;"Scripting is here to stay, but should be avoided where more convenient declarative markup can be used. Scripting should be device and presentation neutral unless scoped in a device-specific way (e.g. unless included in XBL)."&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;I'm not sure that scripting should be avoided where possible in favor for declarative markup. My reasoning is that in order to get a page to DO ANYTHING you have to whack the declarative markup on the head to get it to change. How do you do this? JavaScript.&lt;br /&gt;&lt;br /&gt;I do, however, strongly agree with keeping the languages as neutral as possible. Ubiquitous support and good, fast debuggability is key for developing any app.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-3127770649498981693?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/3127770649498981693/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=3127770649498981693' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3127770649498981693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3127770649498981693'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/06/and-i-quote.html' title='And I quote...'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1976314307476539118</id><published>2011-04-21T18:15:00.000-08:00</published><updated>2011-04-21T18:15:29.071-08:00</updated><title type='text'>The Beer Code</title><content type='html'>I've noticed lately that you can work so hard on a problem that sometimes it actually helps to stop, drink a beer, and go at it again with whatever the beer gives you on the way. It's like there's two modes of thought, one that works with a clear head and maybe some coffee, and another that taps into that lazy, Chappelle's Show and a High Life kind of attitude that can actually be quite productive if taken in stride. Interesting.&lt;br /&gt;&lt;br /&gt;By the way, I did not type this while drinking beer. But, I am about to crack a High Life and get into some Backbone.js :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1976314307476539118?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1976314307476539118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1976314307476539118' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1976314307476539118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1976314307476539118'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/04/beer-code.html' title='The Beer Code'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8687458683275840981</id><published>2011-04-18T22:14:00.001-08:00</published><updated>2011-04-18T22:17:30.015-08:00</updated><title type='text'>The New Thing</title><content type='html'>Javascript is the new thing. About five years ago I got a little tired of the explosion of web frameworks and moved into compiled programs and music software. Now, after a long hiatus, the web is completely different. Now we have that javascript debugger I was missing all those alert()s ago, and the same code (pretty much) runs everywhere.&lt;br /&gt;&lt;br /&gt;Now here's what I see coming in cold.&lt;br /&gt;&lt;br /&gt;We literally have ubiquitous support of a high-level language (javascript) in the whole world's hands (mobile devices), and it has access to cutting edge graphics technology (html 4/5, etc). While before OS's were struggling for streamlined and unilateral application support, the browsers have climbed and dismounted that ladder on the roof of the platform game. The web browser is a virtual machine that is poised to become the next host for desktop applications. Now it's just up to us to get better at doing that.&lt;br /&gt;&lt;br /&gt;Yes, I mean *desktop* applications. The term "client-side" should go away. We should write more javascript and ditch the stateless paradigm. We've already a great RESTful concepts (http/JSON) to harness our massive distributed resources, so let's get going. We need to start writing javascript like we write C++ for native apps, and improving on the markup (because right now it totally sucks).&lt;br /&gt;&lt;br /&gt;And why not? Google has apparently invested millions getting their javascript engine to run faster than CPython. Safari and IE are right behind. Everyone supports it absolutely everywhere. The debuggers are getting better.&amp;nbsp;jQueryUI style coding is where it's at.&amp;nbsp;Now we just need to write more code.&lt;br /&gt;&lt;br /&gt;Go! Go! Go!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8687458683275840981?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8687458683275840981/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8687458683275840981' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8687458683275840981'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8687458683275840981'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/04/new-thing.html' title='The New Thing'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2892766815576701749</id><published>2011-03-11T07:24:00.001-09:00</published><updated>2011-03-11T07:31:21.512-09:00</updated><title type='text'>VirtualBoxVM == Excellent</title><content type='html'>Boy I'll tell you what, a bad job is like a bad relationship (I'll leave drawing the parallels to the following description as an&amp;nbsp;exercise&amp;nbsp;for the reader). At first you are excited for the prospect of something new and everything's great. Then if the stars aren't&amp;nbsp;aligned&amp;nbsp;for you, you start to get cranky and any possible gaps in communication now pose a real threat to your happiness. If you were a contractor, quitting is less clear because they can always send an email asking for help on something small. Next thing you know it's one year later and you have no idea what your status is, but it occupies enough space in your mind to become a problem. Eventually you have to cut all ties and go cold turkey, or face an&amp;nbsp;eternity&amp;nbsp;in limbo.&lt;br /&gt;&lt;br /&gt;Once you are "free" of any previous obligations, you are able to start looking for some new ones ;). If you previously rose to any challenges provided to you, you may choose to aim a little lower next time to give your mind and body a break.&lt;br /&gt;&lt;br /&gt;Anyway, I'm looking at starting a new job this week at a consulting firm here in Anchorage. This time it's salary, writing C# swag for the state and local telephone companies. It's not exactly (nearly) as exciting as building virtual instruments for Hollywood score composers, but I am glad to take on a workload that is "light as a feather." But, being a mac guy I'm not too excited about the prospect of using Windows full time.&lt;br /&gt;&lt;br /&gt;But lo and behold, Oracle's VirtualBox VM is amazing! I hardly notice the speed bump on my i7 macbook pro, and I can just cmd-F to full screen Vista while running Mac OS X. The Dock still works well, and all the iTunes hot keys on the keyboard work. The integration is so smooth, I'm actually looking forward to this.&lt;br /&gt;&lt;br /&gt;If you have a decent mac machine and need to use Windows, try Virtual Box VM. It's free and works extremely well.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2892766815576701749?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2892766815576701749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2892766815576701749' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2892766815576701749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2892766815576701749'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/03/virtualboxvm-excellent.html' title='VirtualBoxVM == Excellent'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8101618900294608812</id><published>2011-02-01T11:32:00.000-09:00</published><updated>2011-02-01T11:32:25.344-09:00</updated><title type='text'>Enough with the "BETA"</title><content type='html'>Hey commercial guys: Enough with the "beta" tag! We all know you are just trying to find a cool way to say "kinda new", but it doesn't really buy you any credibility despite the "bugs" it may have. A feature that is fully deployed as the second tab on cnn.com's from page is by definition not "beta".&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We know software isn't perfect. We're over it. You should be too.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8101618900294608812?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8101618900294608812/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8101618900294608812' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8101618900294608812'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8101618900294608812'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/02/enough-with-beta.html' title='Enough with the &quot;BETA&quot;'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-7243785880533828255</id><published>2011-01-26T19:03:00.000-09:00</published><updated>2011-01-26T19:03:50.070-09:00</updated><title type='text'>Signposts in Shark</title><content type='html'>Shark is a pretty badass profiler. I don't know much about the mach internals that let it do it's thing, but it's pretty sweet.&lt;br /&gt;&lt;br /&gt;I've been trying to get a handle on the performance of my python-based scripting engine in the audio thread, and have found setting sign posts extremely useful for a system trace. A system trace provides a timeline view of all the threads in your app or system, and you can use sign posts to display when a particular event is happening. If I set start and end signposts around the script execution phase, I can see just how much of the audio period the script engine is taking up. This is huge.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_-kPtlLn0YiA/TUDtFZ0hzaI/AAAAAAAAAk4/ETMxu9JzLCY/s1600/System_trace.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" height="166" src="http://2.bp.blogspot.com/_-kPtlLn0YiA/TUDtFZ0hzaI/AAAAAAAAAk4/ETMxu9JzLCY/s640/System_trace.png" width="640" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Shark System Trace. The Audio thread is second from the top.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;The above is a screenshot of a system trace of about 5ms, indicating a timeline of each thread in my audio application. The gui thread is at the top, the audio thread is second from the top, and the rest are disk streaming threads, watchdogs, etc.&lt;br /&gt;&lt;br /&gt;The 5ms of execution shown above is a particularly busy audio buffer period, where the scripting engine is really close to causing an overrun and high cpu usage (and scratchy audio). The first set yellow line and green telephones indicate the previous audio period. Then the next audio period starts with a yellow warning sign post marking the beginning of script execution, and each blue telephone is a system call to release or acquire a semaphore (semaphore_wait and semaphore_signal). Then you can see it barely finishing before the next audio buffer, marked by yet another yellow line.&lt;br /&gt;&lt;br /&gt;Whew! That was a lot of effort. Anyway, sign posts rule.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-7243785880533828255?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/7243785880533828255/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=7243785880533828255' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7243785880533828255'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7243785880533828255'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/01/signposts-in-shark.html' title='Signposts in Shark'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_-kPtlLn0YiA/TUDtFZ0hzaI/AAAAAAAAAk4/ETMxu9JzLCY/s72-c/System_trace.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-156228297480770106</id><published>2011-01-26T17:54:00.002-09:00</published><updated>2011-01-26T18:01:26.489-09:00</updated><title type='text'>Humans VS Computers: Humans +1</title><content type='html'>It recently struck me how definite the line between musical phrases and structures that are machine-like and which ones are human-like, and how important it is that music includes the human structures. For example, imagine a robot voice telling poetry. That's sort of what electro-techno can be like.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I write this because I am a computer programmer, and am heavily into electronic music. Like &lt;i&gt;heavy&lt;/i&gt;&amp;nbsp;heavily. Lately I've been spent quite a few of evenings on the internet listening to new music that has a strong mix of modern electronic elements and more organic parts like guitars and voice.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Bands like &lt;a href="http://www.amazon.com/Lusine/e/B001LHBJR4/ref=sr_ntt_srch_lnk_3?qid=1296087341&amp;amp;sr=8-3"&gt;Lusine&lt;/a&gt;, &lt;a href="http://www.amazon.com/Gold-Panda/e/B002M7FBKI/ref=sr_ntt_srch_lnk_1?_encoding=UTF8&amp;amp;qid=1296087419&amp;amp;sr=1-1"&gt;Lucky Shiner&lt;/a&gt;, &lt;a href="http://itunes.apple.com/us/artist/sister-crayon/id345762239"&gt;Sister Crayon&lt;/a&gt;, &lt;a href="http://itunes.apple.com/us/artist/the-notwist/id14957113"&gt;The Notwist&lt;/a&gt;, &lt;a href="http://madeinheights.bandcamp.com/"&gt;Made in Heights&lt;/a&gt;, and of course, the extremely famous Radiohead, are all discovering new ways to impress their humanistic creativity upon the functions of their technology. Vocals over cheap gameboy drums. Chopped guitar loops triggered with eyes closed and emotions running high. Wurlitzer keys gapped and glitched perfectly to print the message of emotional-technological conflict in the author directly into the passage. This is an important step for us because I believe that most people still see a very black and white relationship between technology and music - it's either techno or it's well, &lt;i&gt;music&lt;/i&gt;. But even through all the techno-lacing over the last 30 years, a listener can still tell when there's a person hidden behind the curtain or not. The existence of this human element is what makes good music &lt;i&gt;good music&lt;/i&gt;.&amp;nbsp;Replace the poetry robot with William Shatner and it's well, at least a step in the right direction.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Check out the end of&amp;nbsp;&lt;a href="http://www.youtube.com/watch?v=4iIvRXCV9lk"&gt;Two Dots, by Lusine&lt;/a&gt;&amp;nbsp;in the following video:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;iframe allowfullscreen="" class="youtube-player" frameborder="0" height="390" src="http://www.youtube.com/embed/4iIvRXCV9lk" title="YouTube video player" type="text/html" width="640"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;br /&gt;In the last minute or so, Lusine's use of the female's voice is absolutely brilliant. The timing and selection of each voice sample is chosen with wonderful precision, which overwhelms the pragmatic critic's mind in the way only true human expression can.&lt;br /&gt;&lt;br /&gt;I am so glad to see the beginning of the techno thing starting to really hit home on the human thing. Dance hall anthems rely heavily on the machine pounding of a new fat-bass sound or a rhythm hammered mechanically into the listener's body, but will also fade from the listener's memory in time. Real, timeless music has more of that human message through expressive use of technology, whether it's a violin, or an MPC-5000. No matter how much modern producers "ruin" music in the same way that &lt;a href="http://www.amazon.com/Born-Run-Hidden-Superathletes-Greatest/dp/0307266303"&gt;modern shoes have "ruined" running&lt;/a&gt;, the basic rule that it takes a human to touch a human will aways hold true.&lt;br /&gt;&lt;br /&gt;That's why I have infinite faith in music.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-156228297480770106?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/156228297480770106/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=156228297480770106' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/156228297480770106'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/156228297480770106'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/01/humans-vs-computers.html' title='Humans VS Computers: Humans +1'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://img.youtube.com/vi/4iIvRXCV9lk/default.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-4941972206560384120</id><published>2011-01-06T01:25:00.002-09:00</published><updated>2011-01-06T01:32:58.313-09:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='peace'/><title type='text'>More Zen, Man!</title><content type='html'>Not the first time for this topic. Not at all..&lt;br /&gt;&lt;br /&gt;You ever look around on the internets and see some projects that speak to you a little? Like you see "Download in FLAC, MP3, OGG." And then you think, "FLAC? really? for an album? dang. ...I like writing headers for audio formats."&lt;br /&gt;&lt;br /&gt;That was random, huh? But it's the little things like that that are important to remember when you dive back into optimizing 10,000 of rpc code, or figuring out why your stupid Qt combobox pop-up looks a little different on mac. Shit.&lt;br /&gt;&lt;br /&gt;I'm tellin' ya man, those simple things are the things that really get our gears turning. When you finish a major work of complexity, what is it that you appreciate after it's done and works well and everything? It's the feeling of sitting back and feeling the simplicity of the function painted plainly in contrast to the complexity concealed within. It's like an instant of grace that happens like 1/100 minutes that I work on any given project.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;Recently I've been tasked with moving from writing more and more docs on the scripting engine, to trying to cut down on the system calls made to the mach kernel to operate the pipe between audio-&amp;gt;scripting processes. This shit is super complicated. There's #ifdefs, and // german comments, and mach calls VS win32 calls, etc.&lt;br /&gt;&lt;br /&gt;Then I take a step back and get tapped on the forehead with the thought of a FLAC header. so simple. I cant wait to be a project lead in a time when I have the resources to make my own decisions. What an idea. Man-power available for good testing. Some sort of loose but consistent process for tracking workload. Individual responsibility depicted in a simple progress-bar (thank you trac).&lt;br /&gt;&lt;br /&gt;But most of all, the greatest simplicity to toss into that "back in the day we yusta'" talk, is the simplicity if the finished product. You load and play an instrument, add another and a side-chained compressor, and get off to dance-land. There's no more audio locks, xml attributes, platform-sepcific code, no more multi-national arguments about the overhead of a semaphore lock when the semaphore is guaranteed free. Jesus.&lt;br /&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;In code, the next best level of simplicity is to have the time available to you to sit down and just dig your little fingers into the steaming guts of that knob's painting routine. It's an ellipse. With a two-toned bevel. On one side only. Fuck the bevel, just antialias. Small value text, extremely accurate integer and float value representations for any unit. dB Hz % ms. All as good as the other.&lt;br /&gt;&lt;br /&gt;Bring it back, baby, just bring it back. Get right into that knob, and just make it as nice as you possibly can. Then move on to the next thing. Ahhhhhhhhhh. peace.&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_-kPtlLn0YiA/TSWZPlsULPI/AAAAAAAAAks/YDnPYaFJTtI/s1600/Dry+Wet.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_-kPtlLn0YiA/TSWZPlsULPI/AAAAAAAAAks/YDnPYaFJTtI/s1600/Dry+Wet.png" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Looks like someone had a good day designing.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-4941972206560384120?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/4941972206560384120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=4941972206560384120' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4941972206560384120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4941972206560384120'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2011/01/more-zen-man.html' title='More Zen, Man!'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-kPtlLn0YiA/TSWZPlsULPI/AAAAAAAAAks/YDnPYaFJTtI/s72-c/Dry+Wet.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-3116395642829474239</id><published>2010-12-16T16:53:00.001-09:00</published><updated>2010-12-17T10:43:12.433-09:00</updated><title type='text'>No Work in Alaska</title><content type='html'>Finding developer work in Alaska sucks. As far as I can see from growing up here, it's very difficult to find anything other than a C# web form developer for something that eventually just supports the oil industry. &amp;nbsp;What a contrast after spending time close to the SF bay area.&lt;br /&gt;&lt;br /&gt;After years of telecommuting, living in your home office can get very, very old. You wake up at work, you work, and when you are done, you are still home. Most of all, you never get a chance to see real people, and your social life takes a hard dive.&lt;br /&gt;&lt;br /&gt;The same old question pops up for me again...mountains and people that run and ski and hike, or a killer job. Damn it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-3116395642829474239?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/3116395642829474239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=3116395642829474239' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3116395642829474239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3116395642829474239'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/12/no-work-in-alaska.html' title='No Work in Alaska'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1545169001384660591</id><published>2010-12-16T16:47:00.002-09:00</published><updated>2011-01-08T11:45:08.263-09:00</updated><title type='text'>Please Stop Misguiding Our Youth</title><content type='html'>&amp;nbsp;Abhi: I'm going to disagree with your last paragraph, but only on a very nit-picky kind of way :)&lt;br /&gt;&lt;br /&gt;I believe that it is easy to confuse hiding data with providing a clean interface. The idea of a functional contract between components does not *require* any kind of restriction, it simply requires that the interface through which the function is provided does not change.&lt;br /&gt;&lt;br /&gt;This contract may be provided in the form of documentation, naming conventions, even a simple phone call to describe that single method used as an entry point to a library. It can even go so far to say that a contract is made by simply keeping the client code ignorant of internal attribute names, so that they won't use them. If you hack the library to find and use the internal symbols, you should not be surprised when the library starts acting weird, right?&lt;br /&gt;&lt;br /&gt;The public and private keywords are specific to languages like C++ and java, and the only reason that I could see a use for them is if the person writing client code was actually reading the headers that defined the class. Including type headers (which is only a convention!) is a language-specific thing, and do not *facilitate* this contract, they only provide a semantic (compile-time!&lt;br /&gt;) helping hand for a language's *implementation* to remind a programmer that they are breaking the contract.&lt;br /&gt;&lt;br /&gt;If I were teaching an OO basics class, I would not teach that "encapsulation" is necessary for object-orientedness. Instead I would focus on the idae of clean *abstraction*, which is the separation of components to ensure that one can be changed without affecting the other. This can be just easily be achieved by providing a wrapper class, or naming methods using an underscore convention like "_handsOffThisWillBreakTheContract", or simply keeping the names of the "private" methods and attributes out of the docs, whether those docs are defined as the html user docs or the class header file itself.&lt;br /&gt;&lt;br /&gt;I will say that I am tired of hearing that encapsulation has anything to do with object oriented programming. Shoot, even abstraction is only necessary &amp;nbsp;in *some* cases, and it can just as easily be achieved in a structured language like C, and so also has nothing to do with object oriented programming.&lt;br /&gt;&lt;br /&gt;The "object oriented" concept provides nothing more than a thin semantic helping hand, in the form of a real-world representation instances of stageful types that provide a function. Everything else is nothing more than language implementation.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1545169001384660591?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1545169001384660591/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1545169001384660591' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1545169001384660591'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1545169001384660591'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/12/please-stop-misguiding-our-youth.html' title='Please Stop Misguiding Our Youth'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2514183727393150790</id><published>2010-11-18T07:41:00.001-09:00</published><updated>2010-11-18T07:41:45.662-09:00</updated><title type='text'>Python/Music Talk Tonight at BayGiggies in South Bay</title><content type='html'>I should have thought to post this up here earlier, but I will be giving a talk at the BayBiggies meeting at Symantec tonight at 7:30 California time. The talk is entitled "Embedding Python as a Realtime Audio Scripting Engine", and this is the summary:&lt;br /&gt;&lt;br /&gt;Topics will include separation and communication between the&lt;br /&gt;application and scripting engine, why Python is "safe" for audio work&lt;br /&gt;including empirical performance metrics, and caveats related to&lt;br /&gt;multithreaded processing as performance requirements increase. I will&lt;br /&gt;share my experiences using the standard CPython implementation to&lt;br /&gt;research and develop a state-of-the-art audio scripting engine.&lt;br /&gt;&lt;br /&gt;At least there's something happening even if the economy did take my job!&lt;br /&gt;&lt;br /&gt;Here is the BayPiggies link for more info:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.baypiggies.net/index_html/eventfolder/copy9_of_baypiggies-meeting-January-28th-2010"&gt;http://www.baypiggies.net/index_html/eventfolder/copy9_of_baypiggies-meeting-January-28th-2010&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2514183727393150790?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2514183727393150790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2514183727393150790' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2514183727393150790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2514183727393150790'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/11/pythonmusic-talk-at-baygiggies-in-south.html' title='Python/Music Talk Tonight at BayGiggies in South Bay'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-9049345046636516644</id><published>2010-09-26T17:33:00.000-08:00</published><updated>2010-09-26T17:33:10.070-08:00</updated><title type='text'>Blocking functionality to pyrtmidi</title><content type='html'>The pyrtmidi module is now complete, offering both a blocking or non-blocking getMessage(timeout_ms=None) and setCallback(func) option. As far as I know, this is now the only complete python midi I/O extension.&lt;br /&gt;&lt;br /&gt;I have not compiled it on windows (in fact it probably won't compile), have not compiled on linux (but it probably works), and the code passes initial tests on mac but other reports are more than welcome.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://trac2.assembla.com/pkaudio/wiki/pyrtmidi"&gt;http://trac2.assembla.com/pkaudio/wiki/pyrtmidi&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Thank you all for your patches, and have fun using midi hardware in your apps!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-9049345046636516644?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/9049345046636516644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=9049345046636516644' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9049345046636516644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9049345046636516644'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/09/blocking-functionality-to-pyrtmidi.html' title='Blocking functionality to pyrtmidi'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6999584690337096914</id><published>2010-09-21T08:57:00.000-08:00</published><updated>2010-09-21T08:57:16.918-08:00</updated><title type='text'>pyrtmidi updates</title><content type='html'>&lt;a href="http://trac2.assembla.com/pkaudio/wiki/pyrtmidi"&gt;pyrtmidi&lt;/a&gt; is a simple python extension to &lt;a href="http://www.music.mcgill.ca/~gary/rtmidi/"&gt;RtMidi&lt;/a&gt;, an awesome three-file C++ library that allows you to read and write midi messages from hardware on all platforms. It's awesome.&lt;br /&gt;&lt;br /&gt;I've been updating the module lately with major api changes. It replaces those inane tuple midi objects with a comprehensive MidiMessage class ripped from the &lt;a href="http://rawmaterialsoftware.com/juce.php"&gt;juce&lt;/a&gt; library that includes great functions like isNoteOn(), isNoteOff(), isController(), getNoteNumber(), getMidiNoteName(), setTimeStamp(), etc. That means that pyrtmidi is now a real midi io library. Both input and output works, but virtual ports are untested, and I also updated RtMidi to the latest version.&lt;br /&gt;&lt;br /&gt;However, as of last night I removed the platform-specific code to support a blocking version of RtMidiIn.getMessage(), and RtMidiIn.setCallback() works exactly as documented in the C++ RtMidi docs which means that the callable object is called from the midi thread. I'll re-add the blocking getMessage() between builds at work asap since I think that's the nicest feature in the module. You should be able to use a Queue.Queue (blocking queue in the stdlib) to get around this for now.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://trac2.assembla.com/pkaudio/wiki/pyrtmidi"&gt;http://trac2.assembla.com/pkaudio/wiki/pyrtmidi&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Have Fun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6999584690337096914?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6999584690337096914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6999584690337096914' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6999584690337096914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6999584690337096914'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/09/pyrtmidi-updates.html' title='pyrtmidi updates'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5690432236669419938</id><published>2010-09-08T13:04:00.001-08:00</published><updated>2010-09-08T13:04:41.810-08:00</updated><title type='text'>One idea for GIL contention</title><content type='html'>One thing that would eliminate the problem of the single GIL from our app would be to load and reload the libpython dll into a new address space within the same process. Our app is a plugin and the instances never have to talk to each other, so if we could simply load libpython into a new, duplicated address space each time we created an instance of our plugin, we would not have to worry about the GIL.&lt;br /&gt;&lt;br /&gt;Has anyone ever heard of this sort of thing? The same thing could effectively be achieved by creating libpython31_1.dylib, libpython31_2.dylib, libpython31_3.dylib, libpython31_4.dylib, etc, and then loading them in order, but this seems kind of excessive.&lt;br /&gt;&lt;br /&gt;What do you think? Stupid? Genius?&lt;br /&gt;&lt;br /&gt;Please don't post comments like "Use multiprocessing module", or "Use process migration". Believe me, I've looked at it and they won't work for our app. If you want to know why, read this post: &lt;br /&gt;&lt;br /&gt;&lt;a href="http://pkaudio.blogspot.com/2010/04/whey-multiprocessing-doesnt-always-work.html"&gt;http://pkaudio.blogspot.com/2010/04/whey-multiprocessing-doesnt-always-work.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5690432236669419938?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5690432236669419938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5690432236669419938' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5690432236669419938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5690432236669419938'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/09/one-idea-for-gil-contention.html' title='One idea for GIL contention'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-378861510998081138</id><published>2010-09-08T12:45:00.000-08:00</published><updated>2010-09-08T12:45:16.488-08:00</updated><title type='text'>Next Year At Burning Man: De-Bunking The DJ</title><content type='html'>Next year at Burning Man I want to create a clinic outlining the basics of making dance music. I want to show how easy and simple electronic music in an attempt to debunk the whole "DJ is cool" myth.&lt;br /&gt;&lt;br /&gt;I'll give a plain-english overview of the tools available to DJ's and producers, and then put together a simple jam session with a bunch of midi controllers so everyone can join in a jam and see how easy it is. 30-second discussion bullets:&lt;br /&gt;&lt;br /&gt;1) Sequencer - Puts tracks in a mixer and plays them in time.&lt;br /&gt;2) Sythesizer - Like a guitar in a mixer.&lt;br /&gt;3) Simple "Rythm Is A Dancer" chord.&lt;br /&gt;4) Arpeggiator - Automatically plays notes from Simple "R.I.A.D." chord to sound like trance.&lt;br /&gt;5) LP Filter - That familiar effect.&lt;br /&gt;6) HP filter - That other familiar effect.&lt;br /&gt;7) Delay - That other other familiar effect.&lt;br /&gt;&lt;br /&gt;8) Jam session - Everyone gets an effect knob on one of the above effect demo tracks, I control mixer on overhead projector, people "totally get it now".&lt;br /&gt;&lt;br /&gt;Hopefully next time they listen to that "sick drum beat" they'll realize that playing it is as simple as the last time they tapped their index finger to Sweet Home Alabama.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-378861510998081138?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/378861510998081138/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=378861510998081138' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/378861510998081138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/378861510998081138'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/09/next-year-at-burning-man-de-bunking-dj.html' title='Next Year At Burning Man: De-Bunking The DJ'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-4181296141239722248</id><published>2010-09-08T12:34:00.002-08:00</published><updated>2010-09-08T12:34:12.519-08:00</updated><title type='text'>Get It!</title><content type='html'>Yes!&lt;br /&gt;&lt;br /&gt;&lt;a href="http://lateral.netmanagers.com.ar/weblog/posts/BB914.html"&gt;http://lateral.netmanagers.com.ar/weblog/posts/BB914.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-4181296141239722248?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/4181296141239722248/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=4181296141239722248' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4181296141239722248'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4181296141239722248'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/09/get-it.html' title='Get It!'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8597172261747836438</id><published>2010-08-06T11:09:00.000-08:00</published><updated>2010-08-06T11:09:36.121-08:00</updated><title type='text'>Porting to Python3: 'bytes' in sys.path gotchya!</title><content type='html'>I'm busy hacking away trying to get my embedded scripting engine ported to python3.&lt;br /&gt;&lt;br /&gt;The biggest pain in the ass is the new bytes VS str type. Today I ran into this error, raised once my import hook called the original builtins.__import__.&lt;br /&gt;&lt;br /&gt;TypeError: must be string, not bytes&lt;br /&gt;&lt;br /&gt;Oh geeze, thanks! What the hell does that mean? Want to see how rediculously long the path to debugging this problem was? Read on...&lt;br /&gt;&lt;br /&gt;First thing was try to find the old builtin_import from import.c. No dice, it's gone.&lt;br /&gt;&lt;br /&gt;Next thing was find_frozen_module, since I had frozen the stdlib and thought there was a problem demarhsalling the code. No dice.&lt;br /&gt;&lt;br /&gt;Then it dawned on me to put a breakpoint in PyErr_Format. No dice. That function is called more times just for Py_Initialize() than I have to restart my machine with m-audio hardware.&lt;br /&gt;&lt;br /&gt;Then I set a breakpoint in PyErr_SetObject for exception == PyExc_TypeError. Bingo - the error is raised from PyArg_ParseTuple, as called by zipimporter_init(). Oh Boy.&lt;br /&gt;&lt;br /&gt;Then I debugged vagetargsl() for a while, and finally found convertsimple(). Ahh, it's getting a bytes object and not a string, as the "s:zipimporter" format string indicated. Finally, square one.&lt;br /&gt;&lt;br /&gt;A look into the module docs say the first value should be a path. Debugging further up the call stack into import.c showed that the 'args' object passed to zipimporter_init() was created waaaay up in find_module(), and was generated from the sys.path object. I have a &lt;bytes&gt; object in my sys.path instead of all &lt;str&gt; objects. But why?&lt;br /&gt;&lt;br /&gt;Because my application is embedded and the std lib is statically linked as frozen C source, I reset sys.path using "sys.path = [myinternalstuff.SCRIPTS_PATH]" in my app startup code. SCRIPTS_PATH is set in my internal module's init function like this:&lt;br /&gt;&lt;br /&gt;PyObject *scriptsdir = PyBytes_FromString(getScriptsDirPath());&lt;br /&gt;PyModule_AddObject(m, "SCRIPTS_PATH", scriptsdir);&lt;br /&gt;&lt;br /&gt;THE GLORIOUS SOLUTION!!!&lt;br /&gt;&lt;br /&gt;Reading the porting docs, I understood that PyString_FromString() has been replaced with PyBytes_FromString() instead of some PyUnicode_*() equivalent. For crying out loud!! I did a direct API swap-out, which led to this mega debugging fiasco due to poor error reporting, and an entire morning wasted.&lt;br /&gt;&lt;br /&gt;Lesson learned, I guess? Not quite sure...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8597172261747836438?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8597172261747836438/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8597172261747836438' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8597172261747836438'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8597172261747836438'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/08/porting-to-python3-bytes-in-syspath.html' title='Porting to Python3: &apos;bytes&apos; in sys.path gotchya!'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-336796174496463807</id><published>2010-05-31T16:25:00.029-08:00</published><updated>2010-05-31T17:57:47.516-08:00</updated><title type='text'>Mac OS X: No timed semaphore waits between processes</title><content type='html'>There are a few very clunky things that the average developer might run into when trying to use IPC primitives on OS X.&lt;br /&gt;&lt;br /&gt;For one, There are gaping holes in the documentation - like some of the functions don't even exist. Even a google search won't turn anything up.&lt;br /&gt;&lt;br /&gt;Second, it's extremely hard to figure out how to do a timed wait on a semaphore shared between processes. There is no timed wait implementation for named semaphores created using semget, and while the native mach semaphores do include a timed wait implementation, it's too hard to figure out how to share one between processes.&lt;br /&gt;&lt;br /&gt;What's the deal Apple? Why am I forced to read off-topic documentation in detail just to get a timed wait between processes? When I realized I was reading and re-reading about bootstrap contexts and ports in the Kernel Programming Guide, I knew I'd gone too far.&lt;br /&gt;&lt;br /&gt;Backing up, all I'm trying to do is signal my daemon when a message is ready, and have the daemon signal my parent process when the request is complete. Considering the response time will always be very small, I'd like to have a timeout on both sides to detect when either process has crashed. &lt;br /&gt;&lt;br /&gt;I've tried installing a SIGALRM handler which works, but that's process-wide and extremely clunky when all I want is a timed wait.&lt;br /&gt;&lt;br /&gt;Simple enough? Apparently not...&lt;br /&gt;&lt;br /&gt;What's the deal Apple?&lt;br /&gt;&lt;br /&gt;=================&lt;br /&gt;&lt;br /&gt;30 minutes pass...&lt;br /&gt;&lt;br /&gt;=====================&lt;br /&gt;&lt;br /&gt;Sometimes all it takes is writing about a problem to help you solve it. Here's what I found, after reading all the mach documentation and the Jack source code (Thank you, once again, Paul):&lt;br /&gt;&lt;br /&gt;It is possible to register a native unnamed mach semaphore (created with semaphore_create()) with a name that another process can use to attach to the same semaphore and do a timed wait (using sempahore_timedwait()). What you have to do is acquire the bootstrap context of the current process and register the semaphore with a name there so that another process that you start can see it. A bootstrap context is like a scope or namespace, and the context in question is the login context, which means that all processes that your user starts uses that namespace.&lt;br /&gt;&lt;br /&gt;I created some example code that shows how to create a semaphore and do a timed wait.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;/** parent.cpp: Create and register a named semaphore, and wait for &lt;br /&gt;    child.cpp to attach to and signal it, allowing this process to terminate.&lt;br /&gt;*/&lt;br /&gt;#include &lt;mach/mach.h&gt;&lt;br /&gt;#include &lt;mach/semaphore.h&gt;&lt;br /&gt;#include &lt;servers/bootstrap.h&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;#include &lt;signal.h&gt;&lt;br /&gt;&lt;br /&gt;void sig(int){}&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;  semaphore_t sem;&lt;br /&gt;  mach_port_t task = mach_task_self();&lt;br /&gt;  mach_port_t boot_port;&lt;br /&gt;  kern_return_t err;&lt;br /&gt;&lt;br /&gt;  err = task_get_bootstrap_port(task, &amp;amp;boot_port);&lt;br /&gt;  if(err != KERN_SUCCESS)&lt;br /&gt;    {&lt;br /&gt;      printf("BOOTSTRAP: %s\n", mach_error_string(err));&lt;br /&gt;      exit(1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  err = semaphore_create(task, &amp;amp;sem, SYNC_POLICY_FIFO, 0);&lt;br /&gt;  if(err != KERN_SUCCESS)&lt;br /&gt;    {&lt;br /&gt;      printf("semaphore_create: %s\n", mach_error_string(err));&lt;br /&gt;      exit(1);&lt;br /&gt;    }&lt;br /&gt;  printf("Created semaphore\n");&lt;br /&gt;  &lt;br /&gt;  err = bootstrap_register(boot_port, "pksem", sem);&lt;br /&gt;  if(err != KERN_SUCCESS)&lt;br /&gt;    {&lt;br /&gt;      //      printf("bootstrap_register: %s\n", mach_error_string(err));&lt;br /&gt;      switch(err)&lt;br /&gt; {&lt;br /&gt; case BOOTSTRAP_SUCCESS :&lt;br /&gt;   /* service not currently registered, "a good thing" (tm) */&lt;br /&gt;   break;&lt;br /&gt; case BOOTSTRAP_NOT_PRIVILEGED :&lt;br /&gt;   /* already exists */&lt;br /&gt;   printf("bootstrap_register(): bootstrap not privileged\n");&lt;br /&gt;   break;&lt;br /&gt; case BOOTSTRAP_SERVICE_ACTIVE :&lt;br /&gt;   printf("bootstrap_register(): bootstrap service active\n");&lt;br /&gt;   break;&lt;br /&gt; default :&lt;br /&gt;   printf("bootstrap_register() err = %s\n", mach_error_string(err));&lt;br /&gt;   break;&lt;br /&gt; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  printf("semaphore_wait()\n");&lt;br /&gt;  //  semaphore_wait(sem);&lt;br /&gt;&lt;br /&gt;  printf("semaphore_timedwait()\n");&lt;br /&gt;  const int ms = 1750000;&lt;br /&gt;  mach_timespec_t ts;&lt;br /&gt;  ts.tv_sec = ms / 1000;&lt;br /&gt;  ts.tv_nsec = (ms % 1000) * 1000000;&lt;br /&gt;  bool wait = true;&lt;br /&gt;  while(wait)&lt;br /&gt;    {&lt;br /&gt;      err = semaphore_timedwait(sem, ts);&lt;br /&gt;      switch(err)&lt;br /&gt; {&lt;br /&gt; case KERN_SUCCESS:&lt;br /&gt;   printf("signaled\n");&lt;br /&gt;   wait = false;&lt;br /&gt;   break;&lt;br /&gt; case KERN_OPERATION_TIMED_OUT:&lt;br /&gt;   printf("timed out\n");&lt;br /&gt;   wait = false;&lt;br /&gt;   break;&lt;br /&gt; case KERN_ABORTED:&lt;br /&gt;   printf("caught signal, trying again\n");&lt;br /&gt;   break;&lt;br /&gt; default:&lt;br /&gt;   printf("default: %s\n", mach_error_string(err));&lt;br /&gt;   break;&lt;br /&gt; };&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/signal.h&gt;&lt;/stdlib.h&gt;&lt;/stdio.h&gt;&lt;/servers/bootstrap.h&gt;&lt;/mach/semaphore.h&gt;&lt;/mach/mach.h&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;/** child.cpp: Attach to the semaphore by name and release it.&lt;br /&gt; */&lt;br /&gt;&lt;br /&gt;#include &lt;mach/mach.h&gt;&lt;br /&gt;#include &lt;mach/semaphore.h&gt;&lt;br /&gt;#include &lt;servers/bootstrap.h&gt;&lt;br /&gt;#include &lt;stdio.h&gt;&lt;br /&gt;#include &lt;stdlib.h&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;int main()&lt;br /&gt;{&lt;br /&gt;  semaphore_t sem;&lt;br /&gt;  kern_return_t err;&lt;br /&gt;  mach_port_t boot_port;&lt;br /&gt;&lt;br /&gt;  err = task_get_bootstrap_port(mach_task_self(), &amp;amp;boot_port);&lt;br /&gt;  if(err != KERN_SUCCESS)&lt;br /&gt;    {&lt;br /&gt;      printf("task_get_bootstrap_port(): %s\n", mach_error_string(err));&lt;br /&gt;      exit(1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  err = bootstrap_look_up(boot_port, "pksem", &amp;amp;sem);&lt;br /&gt;  if(err != KERN_SUCCESS)&lt;br /&gt;    {&lt;br /&gt;      printf("bootstrap_look_up(): %s\n", mach_error_string(err));&lt;br /&gt;      exit(1);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;  semaphore_signal(sem);&lt;br /&gt;  printf("success\n");&lt;br /&gt;}&lt;br /&gt;&lt;/stdlib.h&gt;&lt;/stdio.h&gt;&lt;/servers/bootstrap.h&gt;&lt;/mach/semaphore.h&gt;&lt;/mach/mach.h&gt;&lt;/pre&gt;&lt;br /&gt;Unfortunately I can't find any documentation for the semaphore functions along with mach_task_self(), task_get_bootstrap_port(), bootstrap_register (), bootstrap_look_up(). In fact, boostrap_register() is deprecated! Unbelievable.&lt;br /&gt;&lt;br /&gt;But, as far as I know, using these native unnamed mach semaphores is faster than the POSIX named semaphores created with semget() and managed via semctl(). The native mach semaphores also go away when you kill the process that created them. That means I can get rid of all of my code to manage and cleanup orphaned semaphores based on key files on the disk. What a waste of time that was...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-336796174496463807?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/336796174496463807/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=336796174496463807' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/336796174496463807'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/336796174496463807'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/05/mac-os-x-no-timed-semaphore-waits.html' title='Mac OS X: No timed semaphore waits between processes'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-9139702845546762581</id><published>2010-05-31T15:03:00.000-08:00</published><updated>2010-05-31T15:03:24.467-08:00</updated><title type='text'>What's the mutex for in pthread_cond_wait()?</title><content type='html'>You might notice that you have to pass a mutex to pthread_cond_wait, when you are thinking to yourself "Why do I need a mutex when all I want to do is signal a waiting thread?"&lt;br /&gt;&lt;br /&gt;This is one of those questions that doesn't have an immediately obvious answer. Well, you are right that you can just use a dummy mutex and your thread will properly wake up, but if you actually want to signal the thread based on a *boolean condition* (as determined by real C executing code) then you need to pass a meaningful mutex.&lt;br /&gt;&lt;br /&gt;Here is a really good explanation of when you would want to do that:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cs.wustl.edu/~schmidt/win32-cv-1.html"&gt;http://www.cs.wustl.edu/~schmidt/win32-cv-1.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Happy reading.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-9139702845546762581?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/9139702845546762581/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=9139702845546762581' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9139702845546762581'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9139702845546762581'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/05/whats-mutex-for-in-pthreadcondwait.html' title='What&apos;s the mutex for in pthread_cond_wait()?'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5195106505849642714</id><published>2010-05-14T17:33:00.000-08:00</published><updated>2010-05-14T17:33:15.977-08:00</updated><title type='text'>One Major Feature For GUI Frameworks</title><content type='html'>Our project has been using Qt for four years, and the majority of our company's income is currently based on releases from that time period. But, Qt is really buggy when using your code in VST/AU/RTAS plugins, and juce is a tried and true audio/gui/plugin library. We are considering porting our entire gui code base from qt to juce before what will be our flagship product, and incrementally porting the code while also being able to enable and disable support for each ported feature, code compatibility is going to be key.&lt;br /&gt;&lt;br /&gt;It occurred to me that one feature that all platform-independent gui wrappers should have is to create a drawable widget based on a native window handle. This enables you to mix gui frameworks, and would also make it very easy for us to incrementally port our code from juce to qt. Currenly, juce does this very well, and Qt does this very poorly.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5195106505849642714?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5195106505849642714/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5195106505849642714' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5195106505849642714'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5195106505849642714'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/05/one-major-feature-for-gui-frameworks.html' title='One Major Feature For GUI Frameworks'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6461395732943487584</id><published>2010-04-19T07:36:00.000-08:00</published><updated>2010-04-19T07:36:30.876-08:00</updated><title type='text'>Simple merging and branching with svn</title><content type='html'>Most of you probably already know how to do branches with svn and subversion, but I haven't been able to get off my butt to make it second nature until now.&lt;br /&gt;&lt;br /&gt;I found myself needing to make a rather large set of changes (adding a python scripting daemon, 8+ weeks of work) to my working copy  while still fixing bugs in the trunk. These changes were very experimental, and since we are nearing a release I didn't want to clutter the trunk with it. Plus, a co-worker could save weeks of critical work on the release if he could start using our scripting engine for batch processing. batch processing requires C++ that has nothing to do with the release, and nothing to do with my daemon work.&lt;br /&gt;&lt;br /&gt;So I find myself essentially supporting three features. The release code in the trunk is frozen, but I will want to commit my batch processing fixes as soon as the release is over. Unfortunately the release has dragged on for a couple of months and the trunk is still frozen. My daemon changes are finally stable and I'd like to start using that branch for script development to test it a bit before I merge the changes into the trunk. To make matters worse, I now need the changes from the batch processing in my daemon branch. I hope you follow me.&lt;br /&gt;&lt;br /&gt;It looks like I need a branch of a branch:&lt;br /&gt;&lt;br /&gt;trunk -&gt; batch branch -&gt; daemon branch&lt;br /&gt;&lt;br /&gt;The daemon branch is experimental and so highly private, but includes all of the changes from the batch branch. This way, I can commit the changes from the batch branch first without cluttering up the commit with the enormous changes from the daemon branch. My co-workers test the code a little bit, I fix some bugs, then I go all in with the daemon code.&lt;br /&gt;&lt;br /&gt;Whew, that's a complicated situation!&lt;br /&gt;&lt;br /&gt;The biggest problem was that I really sucked at merging and branching even with ONE branch, so I decided to finally dive in with both feet and learn the svn syntax. Turns out it's actually quite easy.&lt;br /&gt;&lt;br /&gt;If you want to get the changes from one revision to another, regardless of branch or trunk or whatever, you just do this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ svn diff -rLOWER:HIGHER&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The key is that you can do this anywhere at it will produce a patch file. You don't have to think about branching or merging at all to understand this.&lt;br /&gt;&lt;br /&gt;But how do you merge? I was always afraid of thumping my working copy with a merge because I didn't know if it would commit things, or what other persistent effects it would have. "svn merge" doesn't do anything to your working copy, it only updates the source just like 'patch', except it makes it easy to resolve conflicts using a text editor. If you want to get new changes from your trunk into your branch, just make sure all changes in your branch are committed, and do this from the branch dir:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ svn merge -r&lt;revision you last copied or merged from&gt;:&lt;current trunk revision&gt; ../trunk&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you want to see what changes it will apply to your branch, just switch 'merge' with 'diff'. There are two keys here: 1) keep track of the revision that you last updated your branch with. The syntax 'svn merge -rA:B ../source' means I want all of the changes from rev A to rev B in the source dir. svn doesn't even care if you already did this or not, it will try to apply them. Then try the code out, and if it works, commit the changes with a good message for next time that records the revision you merged from, like "scripting branch: merged changes from trunk, rev B".&lt;br /&gt;&lt;br /&gt;Since the changes don't commit anything, just try it out and revert the changes.&lt;br /&gt;&lt;br /&gt;But then I need to update my daemon branch (a branch of a branch) with those changes as well. I'll do this from my daemon branch dir:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;$ svn merge -rB:B+1 ../scripting&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Since all of the trunk changes from rev A to rev B are now included in the scripting branch, I just need to grab all those changes from that latest revision after I committed them with my useful message. That's rev B to rev B+1.&lt;br /&gt;&lt;br /&gt;Once you do this once or twice it's actually pretty easy. I hope this helps.&lt;br /&gt;&lt;br /&gt;I hear git is much better and much faster at this than svn since it does all the work on your own machine and doesn't require the server. It sounds like git is best suited for situations where you want to be able to do lots of little private commits for your own work between real commits to the team's repos.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6461395732943487584?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6461395732943487584/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6461395732943487584' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6461395732943487584'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6461395732943487584'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/04/simple-merging-and-branching-with-svn.html' title='Simple merging and branching with svn'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8645108081226357522</id><published>2010-04-17T10:22:00.001-08:00</published><updated>2010-04-19T07:01:04.722-08:00</updated><title type='text'>Why 'multiprocessing' Doesn't Always Work</title><content type='html'>I have written quite a bit about removing the GIL from our system, and I see a lot of comments that say "Why don't you just use multiprocessing." and "didn't you know that python is not safe for real-time work?" &lt;br /&gt;&lt;br /&gt;I wanted to write a blog post to address those very questions so that I had some place to direct those people to. I also added a page on my wiki covering this topic, with the powerpoint slides from a talk I gave at PyGameSF:  &lt;a href="http://trac2.assembla.com/pkaudio/wiki/PythonForAudioWork"&gt;http://trac2.assembla.com/pkaudio/wiki/PythonForAudioWork&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Multiprocessing is an incredible extension module thats solves many, many multiprocesing problems very well. Unfortunately, multiprocessing is a python module, and therefore runs in python and requires a GIL to be held. Every single operation in python requires the GIL to be held, because ref counts are being changed all the time.&lt;br /&gt;&lt;br /&gt;Every time you access an object attribute, increment an integer, call a method, print, compile - *every time* that you evaluate a frame in python the GIL must be held by some part of C/C++ code. For pure python applications, this C/C++ code is entirely in libpython. For C/C++ applications that embed the python interpreter, this code could be in your application itself (if it was you'd know because you made the calls yourself).&lt;br /&gt;&lt;br /&gt;Our problem is also somewhat unique - we write a C++ audio/musical plugin that the user loads into a mixer track in the host application. Modern audio hosts use a separate thread to process each mixer track, and wait for them each to finish before mixing their result and sending it to the soundcard.&lt;br /&gt;&lt;br /&gt;Since you can load a separate instance of our audio engine into as many tracks as you want, we have to ensure that our engine does not use any static data to prevent the track threads from contending over a lock protecting that data (which almost always results in periodic CPU spikes). Our state-of-the-art audio engine does this very well, until you enable the libpython-based scripting engine, which uses static data like it's going out of style.&lt;br /&gt;&lt;br /&gt;Since libpython uses a single statically-linked object to store a lock that locks the entire library, you CAN NOT use the library from multiple threads, PERIOD. Before even making such a simple call as PyObject_HasAttr(), you have to acquire that one GIL, which means that no two threads will ever execute python code in your host application at the same time, ever.&lt;br /&gt;&lt;br /&gt;That's a showstopper.&lt;br /&gt;&lt;br /&gt;We are doing a lot more than just making simple calls like PyObject_HasAttr (). We want to execute arbitrary python code written in our app's source editor using PyObject_CallObject().&lt;br /&gt;&lt;br /&gt;The accepted solution (from the BDFL) for this problem is to use 'process migration' which means creating a separate process each thread in your application that must execute python code. A process can be defined as a thread of execution with it's own address space, so this makes sense. Each process would get it's own GIL linked into it, and we'd all get on with our measly little lives.&lt;br /&gt;&lt;br /&gt;This is the solution I chose. I create one daemon process from my C++ code for each audio engine the user creates, and make calls to PyEval_EvalCode() and PyObject_CallObject() from within it. This works for us because each audio engine is completely independent of the other and so does not share data (sys.modules, etc...). Our code is also simple enough that we only need the *python language* itself, and don't require the use of complex extension modules.&lt;br /&gt;&lt;br /&gt;I hope this makes some sense to all of you. The basic idea is that our C++ threads need to run python code concurrently, and this is not possible using the current libpython implementation. Even such a magical module as 'multiprocessing' requires the GIL to be held before it can dispatch work to different processes.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;&lt;-- HOST PROCESS}  {CHILD PROCESSES --&gt;&lt;br /&gt;&lt;br /&gt;[audio thread 1: C++]--|                              |--[proc task 1:python]&lt;br /&gt;[audio thread 2: C++]--===[multiprocessing: python] ==---[proc task 2:python]&lt;br /&gt;[audio thread n: C++]--|                              |--[proc task 3:python]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;How many GIL objects do you see in the above diagram? If you said three, you were close. But actually there is four when you including the libpython that is linked into the host app itself. Our audio threads still have to contend for this lock to communicate with the child processes.&lt;br /&gt;&lt;br /&gt;In fact, in our case there are NO GIL objects! The host app no longer requires libpython and each daemon has only one thread running a libpython compiled without thread support! Sweet! Now our scenario looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;&lt;-- HOST PROCESS}  {CHILD PROCESSES --&gt;&lt;br /&gt;&lt;br /&gt;[audio thread 1: C++]----------- shm/semaphore ----------[proc task 1:python]&lt;br /&gt;[audio thread 2: C++]----------- shm/semaphore ----------[proc task 2:python]&lt;br /&gt;[audio thread n: C++]----------- shm/semaphore ----------[proc task 3:python]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No more locks, no more problems!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Python and Real-Time Priority&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Another comment that I frequently see is that "python is not safe for real-time work". While this is of course theoretically true because libpython makes calls like mutex_lock() and malloc(), the concept of "safe for audio use" is completely different. All that matters for use is that there are gaps in the sound.&lt;br /&gt;&lt;br /&gt;I took the plunge to see just how fast the CPython implementation was for *executing python code* (PyEval_FrameEx()), and as long as we don't have multiple threads contending on the GIL, CPython hardly puts so much as a blip on our audio engine's cpu usage. In an average use case, PyEval_EvalCode took up 0.4% of our audio thread's CPU. That pretty much makes python 100% AWESOME for control-rate work within an audio thread.&lt;br /&gt;&lt;br /&gt;Case closed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8645108081226357522?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8645108081226357522/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8645108081226357522' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8645108081226357522'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8645108081226357522'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/04/whey-multiprocessing-doesnt-always-work.html' title='Why &apos;multiprocessing&apos; Doesn&apos;t Always Work'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6873481168995472771</id><published>2010-04-16T11:29:00.002-08:00</published><updated>2010-04-19T07:01:20.473-08:00</updated><title type='text'>Creating and communicating with a child process using std/stdout</title><content type='html'>I posted some example code on my wiki that shows how to create a child process on a posix system, and communicate with it using stdin/stdout. Read it here: &lt;br /&gt;&lt;br /&gt;http://trac2.assembla.com/pkaudio/wiki/ChildProcessStdinStdout&lt;br /&gt;&lt;br /&gt;Some notable snippets:&lt;br /&gt;&lt;pre&gt;static int child_pid = -1;&lt;br /&gt;static int child_status = 0;&lt;br /&gt;static int child_crashed = 0;&lt;br /&gt;&lt;br /&gt;int child_exited(int wait=0)&lt;br /&gt;{&lt;br /&gt;  int status = 0;&lt;br /&gt;  //  printf("PARENT: waitpid %i\n", child_pid);&lt;br /&gt;  pid_t waitResult = 0;&lt;br /&gt;  if(wait)&lt;br /&gt;    {&lt;br /&gt;      do {&lt;br /&gt; waitResult = waitpid(child_pid, &amp;status, 0);&lt;br /&gt;      } while(waitResult == -1);&lt;br /&gt;    }&lt;br /&gt;  else&lt;br /&gt;    waitResult = waitpid(child_pid, &amp;status, WNOHANG);&lt;br /&gt;  //  printf("PARENT: waitpid!!! %i\n", waitResult);&lt;br /&gt;  if(waitResult &gt; 0)&lt;br /&gt;    {&lt;br /&gt;      child_crashed = !WIFEXITED(status);&lt;br /&gt;      child_status = WEXITSTATUS(status);&lt;br /&gt;      return 1;&lt;br /&gt;    }&lt;br /&gt;  else&lt;br /&gt;    return 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;  else&lt;br /&gt;    {&lt;br /&gt;      // child&lt;br /&gt;      dup2(childWrite, STDOUT_FILENO);&lt;br /&gt;      dup2(childRead, STDIN_FILENO);&lt;br /&gt;      close(childWrite);&lt;br /&gt;      close(childRead);&lt;br /&gt;&lt;br /&gt;      char *c_argv[] = { "child", 0 };&lt;br /&gt;      execve("child", c_argv, 0);&lt;br /&gt;      fprintf(stderr, "CHILD: ERROR spawning process\n");&lt;br /&gt;      abort();&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6873481168995472771?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6873481168995472771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6873481168995472771' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6873481168995472771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6873481168995472771'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/04/creating-and-communicating-with-child.html' title='Creating and communicating with a child process using std/stdout'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2257145040467614245</id><published>2010-04-16T11:25:00.001-08:00</published><updated>2010-04-19T07:01:29.793-08:00</updated><title type='text'>Replacing qmake with a custom python build step</title><content type='html'>Find the full script and wiki entry here: http://trac2.assembla.com/pkaudio/wiki/qmake_build_step.py&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Trying to integrate qmake into Visual Studio or Xcode can be a real pain in the ass. Instead, it's really not that hard to write a python script to update your moc, ui, and rcc files, since all qmake does is generate makefiles that do a simple date check for each file. Hack and destroy the following code to your liking, and add it as a build step in your favorite IDE:&lt;br /&gt;&lt;br /&gt;(Ah yes, and this code tends to run faster than make will!)&lt;br /&gt;&lt;br /&gt;This is the basics behind the algorithm, which also runs for UIC and MOC files.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;for hpath in HEADERS:&lt;br /&gt;        hpath = os.path.join(OUSIA, hpath)&lt;br /&gt;        fname = os.path.basename(hpath)&lt;br /&gt;        cpath = os.path.join(MOC_PATH, 'moc_' + fname.rstrip('h') + 'cpp')&lt;br /&gt;        &lt;br /&gt;        if not os.path.isfile(hpath):&lt;br /&gt;            print 'Skipping non-existing file: ', hpath&lt;br /&gt;            continue     &lt;br /&gt;        &lt;br /&gt;        dirty = False&lt;br /&gt;        if not os.path.isfile(cpath):&lt;br /&gt;            dirty = True&lt;br /&gt;            &lt;br /&gt;        if dirty is False and os.path.getmtime(hpath) &gt; os.path.getmtime(cpath):&lt;br /&gt;            dirty = True&lt;br /&gt;&lt;br /&gt;        if dirty:&lt;br /&gt;            headerfile = open(hpath, 'r')&lt;br /&gt;            while True:&lt;br /&gt;                headerline = headerfile.readline()&lt;br /&gt;                if headerline == '':&lt;br /&gt;                    break&lt;br /&gt;                elif 'Q_OBJECT' in headerline:&lt;br /&gt;                    cmd = MOC_COMMAND + ' ' + hpath + " -o " + cpath&lt;br /&gt;                    DISPATCH_SYSTEM(cmd)&lt;br /&gt;                    updates += 1&lt;br /&gt;                    break&lt;br /&gt;            &lt;br /&gt;        verify_files.append(cpath)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2257145040467614245?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2257145040467614245/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2257145040467614245' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2257145040467614245'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2257145040467614245'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/04/replacing-qmake-with-custom-python.html' title='Replacing qmake with a custom python build step'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2878714481340959549</id><published>2010-04-16T10:56:00.000-08:00</published><updated>2010-04-16T10:56:24.511-08:00</updated><title type='text'>I like this post</title><content type='html'>Well written, well said:&lt;br /&gt;&lt;br /&gt;http://artificialcode.blogspot.com/2010/04/professionalism-in-python-or-how-to-not.html&lt;br /&gt;&lt;br /&gt;"My take on that is if you are employed as a professional Python software developer, then not writing tests is lazy, unprofessional, and unacceptable…period."&lt;br /&gt;&lt;br /&gt;"Robert mentioned that Ward Cunnigham's idea of "clean code", was that it was obvious what a function did. This isn't as easy as it sounds. In fact, this is a lot of hard work, even with a language as beautiful, and elegant as Python."&lt;br /&gt;&lt;br /&gt;Dunning–Kruger effect:&lt;br /&gt;http://en.wikipedia.org/wiki/Dunning–Kruger_effect&lt;br /&gt;&lt;br /&gt;""Powerful tools kill quickly, and in surprising ways, and we are going to be careful.... " Often in a failed or troubled Python project, you will see a lot of code where someone was making a mess by trying to be cute."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2878714481340959549?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2878714481340959549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2878714481340959549' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2878714481340959549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2878714481340959549'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/04/i-like-this-post.html' title='I like this post'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-7610309377360796436</id><published>2010-03-30T11:53:00.000-08:00</published><updated>2010-03-30T11:53:59.844-08:00</updated><title type='text'>The Value of Writing Your Own Code</title><content type='html'>A lot of people will talk about how you shouldn't writing "another string class" or try to write "another msg passing framework". This is because tons and tons of people have done it in the past and it's stupid to repeat their work.&lt;br /&gt;&lt;br /&gt;This is true, but there is also something to be said about the value of avoiding external dependencies, and completely owning your code. When you own your code you understand it through and through, and you can fix problems quickly and expand it just as quickly.&lt;br /&gt;&lt;br /&gt;For example, we started the project using the excellent juce framework for the audio engine and basic string functions, and the Qt framework for all the gui stuff. We were effectively working for a software startup and needed to get a product out quickly to pay our salaries, so this totally made sense.&lt;br /&gt;&lt;br /&gt;Later on we ran into name conflicts on symbols like "T", "String", "ComboBox", and "macro" -  STUPID. Even later on, and continuing on today, we ran into linker problems including project config across multiple platforms, exported symbols related to creating new dlls, basically all kinds of stuff all across the board. We even ended up diving deep into all that platform-specific gui code that we were trying to avoid by using Qt by writing event filters and unit tests to ensure that their code worked as a plugin in an external host app.&lt;br /&gt;&lt;br /&gt;Well, Eventually I wrote a simple UVal class to hold atomic types and allow some basic serialization. Over time, this class grew with ascii string functions, then unicode, then url parsing, midi parsing, etc. Today it is completely self-contained, copiable, castable, serializable, basically it totally kicks ass, and can be used with zero dependencies.&lt;br /&gt;&lt;br /&gt;Now, the lesson is that if I had just sat down and written the stupid thing (among other similar self-standing classes) with a few good tests from the start, I'd have saved a shit load of time trying to smash all of our dependencies together over various platforms, binary configs, dll exports. I also can jump right in the code to remember how it works and get the thing to work.&lt;br /&gt;&lt;br /&gt;These days I use our "UVal" whenever I want a string, and I shudder whenever I see "juce::String", because it isn't portable when creating new light-weight binaries because I have to link in juce and all the Carbon/CoreAudio/IOKit/DirectX dependencies. So the lesson reads: "Just write your own damned string class."&lt;br /&gt;&lt;br /&gt;This works because code should be DISPOSABLE. You should be good enough with your tools to re-write things very quickly, and banging out a simple string/url/midi/blob class should not be a big deal. Even in languages like C or C++, your goal should be rapid prototyping and quick, easy, translation of idea to implementation.&lt;br /&gt;&lt;br /&gt;These days whenever I look for an external library I look for one of two things:&lt;br /&gt;&lt;br /&gt;1) Is it clean enough that I can copy it right into our source tree and rip it apart and modify it as if it were my own - because by then it will be. I did this with the oscpack sources.&lt;br /&gt;&lt;br /&gt;2) Is it a good enough example of a cross-platform abstraction that I can not run it but read it and copy the methods into my own similar classes. I did this with Qt and it's Thread/Mutex/Condtion/Semaphore/SystemSepmaphore classes.&lt;br /&gt;&lt;br /&gt;We use the following libraries unmodified in order to stay current with their respective authors:&lt;br /&gt;&lt;br /&gt;- Python&lt;br /&gt;- Juce&lt;br /&gt;- Qt&lt;br /&gt;- libfftw3&lt;br /&gt;- PACE (ultra closed source)&lt;br /&gt;&lt;br /&gt;I have ripped apart and stolen ideas (NOT code) from the following:&lt;br /&gt;- oscpack (for parsing)&lt;br /&gt;- Qt&lt;br /&gt;- Python&lt;br /&gt;- juce&lt;br /&gt;&lt;br /&gt;Looking back I would have started from scratch with our own basic widget classes (combobox, listwidget, tablewidget, button, knob, etc) and used ideas and/or code from the Qt classes. There were far too many bugs in Qt for us to wait for fixes from TrollTech, and their behavior is sometimes too complex from trying to comply with native behavior on all of their supported platforms (just select the god damned list item I click on!!!)&lt;br /&gt;&lt;br /&gt;Bottom line: own your code, write your classes, move on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-7610309377360796436?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/7610309377360796436/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=7610309377360796436' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7610309377360796436'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7610309377360796436'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/03/value-of-writing-your-own-code.html' title='The Value of Writing Your Own Code'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2223276731968166868</id><published>2010-03-24T06:43:00.000-08:00</published><updated>2010-03-24T06:43:26.595-08:00</updated><title type='text'>The GIL Goes West, Part 3: IPC with Shared Memory and Semaphores</title><content type='html'>I just finished the final step in porting my python scripting engine to support true multiprocessing.&lt;br /&gt;&lt;br /&gt;I originally took a leap of faith with stdio and system pipes to get the daemon working, but using  system io functions aren't reliable enough for realtime audio work. If the system gets bogged down, the stdio can block for too long and cause audio glitches.&lt;br /&gt;&lt;br /&gt;So I decided to re-implement my blocking Pipe class using shared memory and semaphores. This was a little scary because I have never used shared memory and frankly sort of tuned out in CS201 when they started talking about semaphores.&lt;br /&gt;&lt;br /&gt;But, I took the plunge. I took my time, wrote good tests, and clean classes. The tests passed, and the scripting daemon worked right away. The baby steps process looked like this:&lt;br /&gt;&lt;br /&gt;1) Write RPC protocol layer on mac.&lt;br /&gt;2) Write Pipe class,tests on mac.&lt;br /&gt;2) Integrate, debug Pipe on mac.&lt;br /&gt;4) Write Process class, tests on mac.&lt;br /&gt;5) Integrate and debug proc code.&lt;br /&gt;5) Write and debug accompanying windows proc code. (WAMMO, works!)&lt;br /&gt;6) Re-implement Pipe class using shared memory/semaphores/mlock on mac.&lt;br /&gt;7) Fill in the blanks on windows.&lt;br /&gt;&lt;br /&gt;I'm sure there are wrappers out there to do all this stuff, but it doesn't come up on the first couple of google searches and our project config is too fragile to add extra libs. I decided to just write the windows and mac wrappers from scratch to learn all the nuances of those system calls.&lt;br /&gt;&lt;br /&gt;Anyway, on with the goods. The performance using shared memory and semaphores is &lt;i&gt;outstanding&lt;/i&gt; on the mac. A quick profile shows that the overhead incurred by the  scripting engine has not noticeably changed. This is where the interesting part begins, though.&lt;br /&gt;&lt;br /&gt;Once you port a part of your code to run in a daemon, your profile stack data disappears into calls to ::read() or ::semop() ::pthread_mutex_lock(), or whatever. Profiling the daemon itself becomes easier, though, because all you see is the code for your module. I guess I need to get better at using the windows and mac profiling tools anyway.&lt;br /&gt;&lt;br /&gt;I am able to see that the time spent marshaling the rpc protocol data is negligible in the profiler. So I will just assume that the shm/sem performance is *totally killer*, and something I don't have to worry about.&lt;br /&gt;&lt;br /&gt;I did, however, install a cpu % display calculated on the top layer above the scripting engine's interface, so all of the above is displayed as a portion of the audio engine's overall cpu usage. It sits happily between 0% and 1%. Awesome.&lt;br /&gt;&lt;br /&gt;I can't wait to post the C++ classes for creating and communicating with a child process using system pipes or shared memory. They are extremely clean and work well on windows and mac.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2223276731968166868?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2223276731968166868/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2223276731968166868' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2223276731968166868'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2223276731968166868'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/03/gil-goes-west-part-3-ipc-with-shared.html' title='The GIL Goes West, Part 3: IPC with Shared Memory and Semaphores'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1626768627888241982</id><published>2010-03-19T12:35:00.000-08:00</published><updated>2010-03-19T12:35:14.787-08:00</updated><title type='text'>Fun with Shared Memory Pipes</title><content type='html'>So I've got this sweet python daemon that uses stdin/stdout for IO. It occurred to me that using such operating system pipes would add a possible bottleneck when using ::read() and ::write(). That is not a good idea from within an audio thread, because the results could be unpredictable. I  know pretty much *nothing* about shared memory, but it occurred to me that I could implement a pipe using a shared memory ring buffer to get around those possible performance penalties.&lt;br /&gt;&lt;br /&gt;(Thanks unnamed dude at PyGameSF for the idea)&lt;br /&gt;&lt;br /&gt;But, I have no idea how shared memory operations perform, how reliable that performance is, and how it differs on windows and mac. I have a hunch that it behaves just like using an OS mutex in your threaded code.&lt;br /&gt;&lt;br /&gt;So if you moved python to a new process for multiprocessing, and used stdin/stdout to talk to it from your host app, is this a good idea? I would implement a simple ring buffer and just write my packets as char data to it, hopefully using some kind of cross-process lock to signal that data is available.&lt;br /&gt;&lt;br /&gt;Time to start reading some man pages I guess.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1626768627888241982?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1626768627888241982/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1626768627888241982' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1626768627888241982'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1626768627888241982'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/03/fun-with-shared-memory-pipes.html' title='Fun with Shared Memory Pipes'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-7991642651590273440</id><published>2010-03-17T10:05:00.001-08:00</published><updated>2010-03-17T10:05:24.421-08:00</updated><title type='text'>An interesting video on GIL performance on multicores</title><content type='html'>http://blip.tv/file/2232410/&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-7991642651590273440?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/7991642651590273440/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=7991642651590273440' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7991642651590273440'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7991642651590273440'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/03/interesting-video-on-gil-performance-on.html' title='An interesting video on GIL performance on multicores'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5640941273943108879</id><published>2010-03-12T10:36:00.001-09:00</published><updated>2010-03-12T10:41:10.917-09:00</updated><title type='text'>More Process Migration, and Happy with Windows?!?</title><content type='html'>I've made a ton of progress on moving my python interpreter to a daemon process to get around the GIL. I tied up the synchronous RPC mechanism using OSC over pipes, and ran some profiling to see how it was working. Generally speaking, the new IPC stack added 0.3% overhead to the audio thread in ::read() and ::write(), running in the same process.&lt;br /&gt;&lt;br /&gt;I'm hoping that attaching those pipes to stdin/stdout of the daemon process will not add any more overhead. It shouldn't because they are all OS-level pipes, right?&lt;br /&gt;&lt;br /&gt;So the workflow for refactoring a C++ project that makes CPython calls directly to only making those calls in a daemon process looked like this:&lt;br /&gt;&lt;br /&gt;- Port all code to use an abstract interface for the scripting engine. Take two years to mix this work in with normal tasks.&lt;br /&gt;- Write an RPC protocol. I marshaled our UVal class over OSC, but anything will work as long as it's light weight.&lt;br /&gt;- Insert the IPC code behind the abstract interface to debug and profile the communication between app and engine within a single process. Work out call stacks (to allow for downstream calls to make upstream calls before returning) and other gritty details.&lt;br /&gt;- Implement cross-platform (Windows and Mac) Process and Pipe classes and plug stdin/stdout into the pipes described above. Pray.&lt;br /&gt;&lt;br /&gt;Praying seems to have worked. After a quite a bit of toil working with pipe, dup2, fork, and execve in XCode and a couple of simple test cases to test the process management, I got the daemon working. And it works WELL.&lt;br /&gt;&lt;br /&gt;Then I really started praying as I moved to finish the same code on windows. Once the code compiled, it worked the first time. Unbelievable!&lt;br /&gt;&lt;br /&gt;On that note, I have to hand it to the Windows guys, the fact that I had to sit down and crunch on the posix calls for an entire day, while simply reading an official windows tutorial (&lt;a href="http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx&lt;/a&gt;) got me up and running on windows really speaks well of the cleanliness of the API. Sure, I hate that they re-created all the standard types (BOOL? Seriously?! WTFF?!?!) and have a crazy proprietary API &lt;i&gt;and&lt;/i&gt; pass-by-reference call style for everything, but I never had to debug my code. Plus the Visual Studio debugger is FAST and very RELIABLE.&lt;br /&gt;&lt;br /&gt;Tell me though, if they can figure that crap out then why do I have to wait 2 minutes to move a folder from Downloads to Desktop?&lt;br /&gt;&lt;br /&gt;Anyway, the GIL continues to go west. My solution could have been cleaner, but at least now I have python running in another process, which should kill the toughest bug I've been assigned to on this project...and it only took two years to fix.&lt;br /&gt;&lt;br /&gt;NDA-safe implementation details to follow.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;MORE&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Creating a Child Process with Redirected Input and Output&lt;/i&gt;: &lt;a href="http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx&lt;/a&gt;&lt;br /&gt;&lt;i&gt;Pipe, Fork, Exec and Related Topics&lt;/i&gt;: &lt;a href="http://www.cs.uleth.ca/~holzmann/C/system/pipeforkexec.html"&gt;http://www.cs.uleth.ca/~holzmann/C/system/pipeforkexec.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5640941273943108879?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5640941273943108879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5640941273943108879' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5640941273943108879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5640941273943108879'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/03/more-process-migration-and-happy-with.html' title='More Process Migration, and Happy with Windows?!?'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6678780622858404161</id><published>2010-03-08T09:59:00.000-09:00</published><updated>2010-03-08T09:59:46.181-09:00</updated><title type='text'>Simple C++ Unit Tests Within Your Application's Code</title><content type='html'>As our project's code has grown, and the use cases have become more complex and hard to remember, I have shut out the practice of writing tests as a method to ensure the quality of my code.&lt;br /&gt;&lt;br /&gt;Our application runs as a plugin within many different host applications, and so our deployment environment is next to impossible to predict. As such, we are spending most of our time just writing the new code, compiling the entire plugin (500+ source files), and debugging it straight up to get everything to work. basically, we don't have time for tests.&lt;br /&gt;&lt;br /&gt;I know a bunch of you will say "but the time gained by forgetting tests is lost in maintaining the bugs you will create." Well, there is actually a window created by excessive feature requests and tight time constraints where you just don't have the time to deal with tests. You get it working, you submit the code, you deal with it later.&lt;br /&gt;&lt;br /&gt;But, after hiring a new developer to help handle my load, I have started to have a little more time here and there and I have started to inkle out a few tests here and there. Writing test is a skill that can become second nature with practice. Not only does it help verify your code, but it gives you a chance to massage it's flexibility by looking at it from a new perspective.&lt;br /&gt;&lt;br /&gt;We don't use a sophisticated testing framework or anything, but one technique that I find very helpful is to slap the tests for a class into a static class right a the bottom of the .cpp file, and put the test code right in the constructor. That way your code is run before your app code (during your runtime's static initialization phase) muddies up static data.&lt;br /&gt;&lt;br /&gt;Here is an example:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;class test_UValArgs&lt;br /&gt;{&lt;br /&gt;public:&lt;br /&gt;  &lt;br /&gt;  void test(const UValArgs &amp;args, const char *formats[])&lt;br /&gt;  {&lt;br /&gt;    for(int i=0; formats[i] != 0; ++i)&lt;br /&gt;    {&lt;br /&gt;      const char *fmt = formats[i];&lt;br /&gt;      try &lt;br /&gt;      { &lt;br /&gt;        args.checkTypes(fmt);&lt;br /&gt;      }&lt;br /&gt;      catch(ArgumentError &amp;e)&lt;br /&gt;      {&lt;br /&gt;        printf("test_UValArgs: FAILED \"%s\": %s\n", fmt, e.what());&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  test_UValArgs()&lt;br /&gt;  {&lt;br /&gt;//    UVal e;&lt;br /&gt;//    e.exc_setException("ArgumentException", "hey you guys");&lt;br /&gt;//    printf("%s\n", e.toCString());&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    UValArgs a0; a0 &lt;&lt; (int) 1 &lt;&lt; (int) 2;&lt;br /&gt;    const char *f0[] = { "ii|i", 0};&lt;br /&gt;        test(a0, f0);&lt;br /&gt;&lt;br /&gt;    UValArgs a0; a0 &lt;&lt; (int) 1 &lt;&lt; (float) 2 &lt;&lt; (double) 3;&lt;br /&gt;    const char *f0[] = { "ifd", "if|d", "if", "i", 0 };&lt;br /&gt;//    test(a0, f0);&lt;br /&gt;    &lt;br /&gt;    UValArgs a1; a1 &lt;&lt; "hey" &lt;&lt; (int) 3;&lt;br /&gt;    const char *f1[] = { "s", "i", "si|f", 0 };&lt;br /&gt;//    test(a1, f1);&lt;br /&gt;&lt;br /&gt;    UValArgs a2; a2 &lt;&lt; "hey" &lt;&lt; "you";&lt;br /&gt;    const char *f2[] = { "s|s", 0 };&lt;br /&gt;    test(a2, f2);&lt;br /&gt;  }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;static test_UValArgs _test_UValArgs;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When you are done with the test you can just use a '#if 0 .. #endif' or a comment block to exclude it from your code.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6678780622858404161?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6678780622858404161/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6678780622858404161' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6678780622858404161'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6678780622858404161'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/03/simple-c-unit-tests-within-your.html' title='Simple C++ Unit Tests Within Your Application&apos;s Code'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6598484538900918359</id><published>2010-03-05T18:36:00.001-09:00</published><updated>2010-03-05T18:40:37.857-09:00</updated><title type='text'>PyGameSF Talk</title><content type='html'>Last Thursday I gave a talk on embedding python as an audio scripting application at the San Francisco Public Library for the PyGameSF meet-up.&lt;br /&gt;&lt;br /&gt;It had been a while since I'd put anything up in the community on this topic, as I've sort of sat down as an ambitious developer after getting totally burnt out in the music industry. But, I was reminded of how much interest there is surrounding this stuff when the attendees excitedly tossed a multitude of quality questions out as I spoke.&lt;br /&gt;&lt;br /&gt;While the technical details of the Play engine are protected under NDA, I have posted the slides from my talk here: &lt;br /&gt;http://trac2.assembla.com/pkaudio/attachment/wiki/EmbeddedInterpreter/PyGame%20Talk.ppt&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Process Migration&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The two most important points of interest from the talk were taken directly from my experience embedding Python in a commercial audio thread:&lt;br /&gt;&lt;br /&gt;1) PyEval_EvalFrame takes up 0.4% of our audio thread's CPU time when executing some control-rate callbacks with some rather simple looping and app logic. That's a REALLY BIG DEAL. It means that CPython is very fast at executing the language sytax.&lt;br /&gt;&lt;br /&gt;2) Lock contention from the GIL causes CPU spikes, but only at low latencies. In the talk I pushed process migration as the logical solution, and shouted my schpeil on how once upon a time no one thought office apps could be written in javascript...and also how the same company that broke that barrier recently started using multiple processes like candy in their own web browser.&lt;br /&gt;&lt;br /&gt;I mentioned that I was almost done porting our engine to use a separate python process per audio thread in order to get around the GIL. I can't wait to write up the details of the implementation, as I think we all need to start thinking about multiple processes as a way of life.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6598484538900918359?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://trac2.assembla.com/pkaudio/attachment/wiki/EmbeddedInterpreter/PyGame%20Talk.ppt' title='PyGameSF Talk'/><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6598484538900918359/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6598484538900918359' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6598484538900918359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6598484538900918359'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/03/pygamesf-talk.html' title='PyGameSF Talk'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5112686739176209370</id><published>2010-02-04T07:46:00.000-09:00</published><updated>2010-02-04T07:46:54.083-09:00</updated><title type='text'>How Good Are We With Processes?</title><content type='html'>Consider this problem:&lt;br /&gt;&lt;br /&gt;Your C++ project includes libpython and special multiprocessing constraints require you to move the CPython interpreter code and GIL out of the main process. No, you can't use multiprocessing or any other python-based code because it requires the GIL. The GIL must move. The GIL &lt;i&gt;will&lt;/i&gt; move.&lt;br /&gt;&lt;br /&gt;You can use your nifty CS degree to easily abstract your use of the python interpreter into an abstract interface. Communication with the interface is easily serializable. You're well on your way.&lt;br /&gt;&lt;br /&gt;But wait, there's one problem. Clean, tight process management is something you've never worked with before - not to mention on Windows &lt;i&gt;and&lt;/i&gt; Mac. Your requirements are simple, but the challenge is hard.&lt;br /&gt;&lt;br /&gt;"All I want to do is start a process, get a read and a write file descriptor, and kill the process." Sorry, but it's not that simple. Unix has sockets, Windows does not. They both use radically different calls to manage processes. And what about shared memory? Sheesh...scary.&lt;br /&gt;&lt;br /&gt;You won't be firing off new processes very often, but you can't afford hung processes. You need 100% reliability. You can't afford much time to waste time debugging runaway processes. You just need the basic process management code to work - and all in C++.&lt;br /&gt;&lt;br /&gt;How simple can this be? Surely there is a library for this? is it just a little code to copy and maintain myself? Seems like it should be.&lt;br /&gt;&lt;br /&gt;If we are going to leave the GIL as is, shouldn't it' be a no-brainer to attack a problem like this? Is there a C++ version of multiprocessing, or at least something close? If we are going to accept process migration as a viable solution to true python multiprocessing, shouldn't we remove problems like this from the equation?&lt;br /&gt;&lt;br /&gt;Can we simply do this with better tools? &lt;i&gt;Should&lt;/i&gt; we just do this with other tools? I think so.&lt;br /&gt;&lt;br /&gt;The CPython interpreter is fast. It's like, really super fast, and we use it in a real-time audio application without so much as a &lt;i&gt;blip&lt;/i&gt; on the profiler. It is such a shame that such a fast, clean language can't be used by our several threads without overcoming this crazy process migration hurdle. I'd love to move it to a new process, but first I have to find out how!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5112686739176209370?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5112686739176209370/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5112686739176209370' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5112686739176209370'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5112686739176209370'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2010/02/how-good-are-we-with-processes.html' title='How Good Are We With Processes?'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-7980200598706541475</id><published>2009-12-11T11:08:00.001-09:00</published><updated>2009-12-11T11:10:35.647-09:00</updated><title type='text'>It's time to get serious about processes</title><content type='html'>No matter how hard it may be to say or accept it, I think that the real answer for this whole GIL/process thing is to just buckle down and start getting better at using processes.&lt;br /&gt;&lt;br /&gt;Opening the Chrome beta reminded me that using more processes should not be a scary thing. Before we got used to async javascript requests, we never would have thought to develop full-on applications using a web browser. But, the basic technology was there, someone just had to do it. No one would have thought that streaming video to a phone would work, but now they do it, and now we know that only 3% of AT&amp;T's users are causing the majority of their bandwidth issues.&lt;br /&gt;&lt;br /&gt;We just need more practice using processes, and we need better tools to use them. The multiprocessing module is a TERRIFIC example of this. Now it's easy to write tools from the process-domain. Other than the technical difficulty of writing code to manage child processes and use shared memory, I can't think of a single reason why we shouldn't just be using processes instead of threads.&lt;br /&gt;&lt;br /&gt;My motivation for this comes completely from the annoyance of the gil.&lt;br /&gt;&lt;br /&gt;Unfortunately, I have no idea how to reliably start and stop a child process on both windows and mac, and I have never used shared memory. It seems like a really great library to do just that and to map objects in shared memory as if they were in the same processes would be the real killer "app" here.&lt;br /&gt;&lt;br /&gt;I mean seriously...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-7980200598706541475?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/7980200598706541475/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=7980200598706541475' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7980200598706541475'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7980200598706541475'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/12/its-time-to-get-serious-about-processes.html' title='It&apos;s time to get serious about processes'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5157496337660775150</id><published>2009-12-10T13:29:00.000-09:00</published><updated>2009-12-10T13:29:24.992-09:00</updated><title type='text'>Something I really like about python</title><content type='html'>One thing I really like about python is that the language (syntax, parser, compiler, interpreter) itself is actually very small. A lot (75%0 of the functional code that I end up actually debugging and reading is just plain old python stuff that most of us can understand.&lt;br /&gt;&lt;br /&gt;Aside from the runtime stuff, most of the python interpreter is just a bunch of python objects that anyone can mess with. If I remove a dict entry from sys.modules, the module is reloaded. __import__ is just another python callable. Lots of core functionality is implemented as extension modules, like codecs, _codecs and posixpath.&lt;br /&gt;&lt;br /&gt;To a degree this speaks to the integrity of the language itself. As I understand it a project like pypy would test the language to the max, being able to implement itself within itself. I think the thinness of the core python code and the thickness of the 2nd layer of interpreter logic on top of that is equally interesting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5157496337660775150?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5157496337660775150/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5157496337660775150' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5157496337660775150'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5157496337660775150'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/12/something-i-really-like-about-python.html' title='Something I really like about python'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-4552979495673651192</id><published>2009-12-09T23:35:00.000-09:00</published><updated>2009-12-09T23:35:32.092-09:00</updated><title type='text'>My Experience Porting to CPython 3</title><content type='html'>I was trying to port our C++ app to python 3, but am sadly not having much luck. I use Tools/freeze/freeze.py to embed the .py sources of the python lib into the application, and also build as many C modules into libpython as possible using Modules/Setup.local.&lt;br /&gt;&lt;br /&gt;After porting PyString_AsString() calls to PyBytes_AsString(), and updating a few build scripts to use the new print function, I spent a ton of time debugging lib python trying to figure out why the frozen codecs.py isn't importing. The marshal module is demarshaling "encodings" and "zipimport" correctly, but fails on the code object for codecs.py. I still can't figure it out.&lt;br /&gt;&lt;br /&gt;So now I just have a bunch of #ifdef statements for the new C++ code and a lot of new files added to my project. Disappointing.&lt;br /&gt;&lt;br /&gt;Is it considered foolish to try to get python 3 working with our app? It would appear to be a good idea to get the new interpreter in before we release in a couple of months and our users start writing code for it. But, I've read plenty of stuff that says it's a bad idea right now. Good grief!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-4552979495673651192?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/4552979495673651192/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=4552979495673651192' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4552979495673651192'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4552979495673651192'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/12/my-experience-porting-to-cpython-3.html' title='My Experience Porting to CPython 3'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-4555629728839633700</id><published>2009-11-13T15:46:00.005-09:00</published><updated>2009-11-13T16:41:06.072-09:00</updated><title type='text'>Basic Embedded Scripting Schema</title><content type='html'>Consider this scenario: The CPython interpreter is embedded in a C++ app. Users can use a built-in editor to define a script or two with pre-defined callbacks, and can make calls on the application's engine. Users can write extension modules and packages, and can import and communicate other scripts written right in the editor. A standard library is included as frozen source in the application executable to be imported by the user's scripts.&lt;br /&gt;&lt;br /&gt;This poses a very interesting problem with regards to global data stored in the interpreter. Specifically, how would you handle importing modules with respect to the cache in sys.modules? How do you handle editing script A in the editor then recompiling it? What happens when you've written script B in the editor and it imports script A, and you edit and re-compile script A?&lt;br /&gt;&lt;br /&gt;Importing modules like 'random' and 'math don't post much of a problem, since they don't store local data.  But, how do you expose the engine's objects as globals? If our app is loaded as a plugin then there is more than one engine, but still only one set of __builtins__, one sys.modules, etc.&lt;br /&gt;&lt;br /&gt;What I have so far:&lt;br /&gt;&lt;br /&gt;Our scripts have the ability to manipulate the application engine, and can add gui controls to a little window for controlling run-time parameters. Access to these objects is provided by adding "engine" and "interface" objects directly to the module's __dict__ when the script is compiled.&lt;br /&gt;&lt;br /&gt;But, how are these objects added when importing a frozen module in the application's standard library using the built-in dotted-named import? I've implemented an import hook, but the dotted name import doesn't need it when importing frozen modules.&lt;br /&gt;&lt;br /&gt;Currently I define an import hook that removes every module from sys.modules right after it's imported by the original import mechanism. This causes the module to be reloaded from frozen or disk storage whenever it's imported. This currently works well for us.&lt;br /&gt;&lt;br /&gt;But what about that dotted-name import?&lt;br /&gt;&lt;br /&gt;from myutils import This, That, Other&lt;br /&gt;&lt;br /&gt;When This, That, or Other is imported using the above scheme, your import hook (set using __builtin__.__import__ = myimport) doesn't get called for This, That, Other, so you can't add the "engine" and "interface" objects. I'm sure there's another way to do this, but what is the other way to do this?&lt;br /&gt;&lt;br /&gt;Getting into the CPython code is a little intimidating, to say the least. I have no idea if I'm doing any of this import stuff the right way. Is there a right way?&lt;br /&gt;&lt;br /&gt;How have other people handled this? Any similar or slightly different situations out there?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-4555629728839633700?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/4555629728839633700/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=4555629728839633700' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4555629728839633700'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4555629728839633700'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/11/basic-embedded-scripting-schema.html' title='Basic Embedded Scripting Schema'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-3282047014695827839</id><published>2009-11-06T12:53:00.002-09:00</published><updated>2009-11-06T12:55:14.955-09:00</updated><title type='text'>An interesting thread problem</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Interesting problem&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I am trying to flesh out the thread locking for our embedded python interpreter. A user can write scripts for our application, and if a script defines a callback it can respond to events from the application (like a midi note or musical clock tick).&lt;br /&gt;&lt;br /&gt;As it stands, we are not using process migration to allow for true multiprocessing, but instead are just hamming a single lock from multiple threads to protect the CPython library. This is good enough for now - it works quite well at relatively low latencies.&lt;br /&gt;&lt;br /&gt;I compiled python without thread management to avoid an incredible number of 'NULL tstate' errors caused by unpredictable thread management by sequencing host applications. The app is solid, but now I want to integrate a simple stack frame mechanism to allow scripts to behave a little better when calling other scripts. Short intro, but the details don't matter anyway...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Here's the deal&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I have one audio engine per thread, and several scripts per engine. The currently executing script is stored as a pointer on the engine object using my function setActiveScript(), and when a new script is called it is swapped with the current one, much like PyThreadState_Swap(). This in effect creates a stack of scripts in the engine, where when execution returns to the original script NULL is passed to setActiveScript().&lt;br /&gt;&lt;br /&gt;This works great, but when there is more than one engine (and so more than one thread), I need to acquire a critical section lock and swap the engine for another one, while maintaining the current script on that engine. The script pointer is stored in the engine, but where to enter and exit the critical section is tough. Hairy.&lt;br /&gt;&lt;br /&gt;The function looks like this:&lt;br /&gt;&lt;br /&gt;Script *ScriptingApplication::instance()-&gt;setActiveScript(Script *)&lt;br /&gt;&lt;br /&gt;I haven't written much complex code in the last while, so lining out the algorithm and thread locks is kind of clunky at best. it doesn't help that Ableton Live (a host that loads our audio plugin) suddenly doesn't want to be debugged.&lt;br /&gt;&lt;br /&gt;*crash*. uggh.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-3282047014695827839?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/3282047014695827839/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=3282047014695827839' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3282047014695827839'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3282047014695827839'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/11/interesting-thread-problem.html' title='An interesting thread problem'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-4709054541894079059</id><published>2009-11-05T21:17:00.002-09:00</published><updated>2009-11-05T21:38:31.861-09:00</updated><title type='text'>Pure Art</title><content type='html'>There comes a point when a piece of art is so refined that the products, byproducts, and even messiest and most defiled anty-products of that piece of art look good. The old rule that the back of the cross-stich should look as nice as the front applies throughout all kinds of art, whether it's computer programming, music, or athletic prowess.&lt;br /&gt;&lt;br /&gt;You've got your face deep down in the last algorithm that will finish your crowning achievement of the last nine months of work. The goal is met, the task is complete, but the project is a mess.&lt;br /&gt;&lt;br /&gt;Now its done, and you start polishing and packaging it up, writing API docs, making CD art, distributing re-usable instrument tracks for the rest of the world to see - the piece is packaged and ready to ship.&lt;br /&gt;&lt;br /&gt;Ableton live is one of those pieces of fine art, where the purity of the design lends itself to producing beautiful musical sets, even among some of the crappiest work you've done. The layout of the clips, the coloring and grouping of the built-in tools, everything can end up being a work of art in it's own, not just the final audio dump that you'll stick on your new album.&lt;br /&gt;&lt;br /&gt;Go download the &lt;a href="http://cdn1.ableton.com/download/8736a17660353a4e1fad57724182aecd/AbleTen_Mum.zip"&gt;free Múm set&lt;/a&gt; on Ableton's site and check out the work that they've done. If you don't have Live just download the free demo.&lt;br /&gt;&lt;br /&gt;First off, everything sounds amazing. Any clip sounds good with any clip. Even a monkey could play a nice sounding song here. This is the meaning of the back of the cross-stitch work. The loops are clean, refined, polished, done.&lt;br /&gt;&lt;br /&gt;They also spelled their name with inactive tracks down at the bottom of the set, and spelled their name again in midi notes in each of those tracks. I know this is poking at nerdy details, but this set just emanates the very cleanliness and artistic presentation that such a flexible tool makes possible. It's just a feeling I get, man.&lt;br /&gt;&lt;br /&gt;This software &lt;span style="font-style:italic;"&gt;makes&lt;/span&gt; me want to be creative, whether I like it or not. Not only that, but it plainly shows the way to easy and readily available creativity, without having to wade through the much of documentation and technical cribby-crap.&lt;br /&gt;&lt;br /&gt;Ableton have nailed the solution to the music problem. They have nailed it, and then shown us what we didn't know we wanted to do in the first place. They've redefined the industry. While people preach this crap all the time, you almost never really see it.&lt;br /&gt;&lt;br /&gt;Because of this, Ableton Live is the best piece of software out there.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-4709054541894079059?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/4709054541894079059/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=4709054541894079059' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4709054541894079059'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4709054541894079059'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/11/pure-art.html' title='Pure Art'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5577486355580492597</id><published>2009-11-05T16:29:00.004-09:00</published><updated>2009-11-05T16:43:09.492-09:00</updated><title type='text'>Sell Out</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Music people&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Go download the free Ableton Live demo and then have a look at Adam Freeland's Live set on there site, &lt;a href="http://cdn1.ableton.com/download/fdab17e3d2734be0e73ed8e3d9c56d9c/AbleTen_AdamFreeland.zip"&gt;here&lt;/a&gt;. Fabulous.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Programming people&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What's the difference between music and programming anymore anyway? Bloody hell, all of today's music has been recorded, mixed, and sometimes even conceived on software.&lt;br /&gt;&lt;br /&gt;When I went broke a month ago I sort of sold out and took back my old programming job. At least they called me before I called them!&lt;br /&gt;&lt;br /&gt;Jackson Hole is a tough place to find a bartending job, especially in the off-season. In fact you'd be better off trying to break into the hooker scene in Amsterdam. Keeping journalistic ties with fasterskier.com has given me some opportunities to supplement my income while staying very much a part of the cross country skiing world.&lt;br /&gt;&lt;br /&gt;This time around though, I have don't have the pressure of deadlines. I'm also working on my python-based audio scripting engine, which is a piece that only I have knowledge of and so I'm sort of working in a social hole. Oh well, at least it's money.&lt;br /&gt;&lt;br /&gt;The good news is that I finally get to focus on Play's python-based scripting engine. We've paid a couple of guys to write some subtle portamento and legato scripts, but as of yet no one with notable python experience has gotten a chance to sit down and flush out the development workflow. It badly needs scripts written with good style and reusability concepts so that the infinite multitudes of users that write scripts for it will have a solid place to start.&lt;br /&gt;&lt;br /&gt;Build settings and complex symbol linkage, processor optimizations, and deployment schemes still scare the nuts off me. So, the goal these days is to do most of my work in Play itself instead of actually developing the application.&lt;br /&gt;&lt;br /&gt;The cool thing about this for Python is that we've found that the language works extremely well in a real-time audio environment. It is very fast, and imposes no noticeable CPU overhead on our professional sampling engine. I am excited to have some content and discussion-prone scripting topics on this blog, and end this needless bickering about my poor job experiences.&lt;br /&gt;&lt;br /&gt;Oh yeah, and post some pictures of sick ski lines.&lt;br /&gt;&lt;br /&gt;Yay&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5577486355580492597?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5577486355580492597/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5577486355580492597' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5577486355580492597'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5577486355580492597'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/11/sell-out.html' title='Sell Out'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6963036844264364014</id><published>2009-10-23T12:59:00.002-08:00</published><updated>2009-10-23T13:19:24.951-08:00</updated><title type='text'>Control</title><content type='html'>OK, I'll continue on with my tirade on programming lifestyle, and computer personalities.&lt;br /&gt;&lt;br /&gt;I'm trying to figure out how to handle subtle conflicts that arise over text chat interfaces, like AIM. The two problems I run into the most are misinterpreting other's remarks (generally for the negative, causing the other guy to seem grumpy), and the other guy answering your question or segueing so fast that you don't get a chance to finish your response.&lt;br /&gt;&lt;br /&gt;I have no idea how to get around misinterpreting someone else's typings. This usually happens when you never get any face time with the person, and is much harder to avoid when deadlines and strict business-like requirements add pressure to the situation.  Adding a spoken language barrier to the mix also adds a significant challenge. &lt;br /&gt;&lt;br /&gt;This problem is usually always personal (meaning it's YOUR problem), and really puts your ability to give other's the benefit of the doubt to the test. After a few years of problems with this I decided I didn't have the patience for that job anymore and decided to quit.&lt;br /&gt;&lt;br /&gt;As for the second thing, I am consistently "typed-over" by some hyper people, which is just like when someone talks over you and never lets you finish what you are saying. My current theory relates to how coders, and especially coders that "reaaally" get into their work (been there), and get so used to operating as kings in this beautifully controlled computer world that they forget that they can't control the other people they are trying to communicate with.&lt;br /&gt;&lt;br /&gt;Hmmm.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6963036844264364014?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6963036844264364014/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6963036844264364014' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6963036844264364014'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6963036844264364014'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/10/control.html' title='Control'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-827056490006470236</id><published>2009-10-15T07:20:00.002-08:00</published><updated>2009-10-15T07:27:41.142-08:00</updated><title type='text'>Is a Geek a Geek?</title><content type='html'>&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;Are geeky people into complex things because they are afraid of real productivity? After quitting my programming job I've starting taking a clean look at why geeks are drawn to complexity. Is it good or bad? Is it denial?&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;The other day while I was playing with my favorite music production program, I noticed something about the complexity of the interface that appealed to my geeky side.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;"Oh it's so fun, look at all the little lights and level meters and mixer sliders. So cool!"&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;But wait, why the heck is that &lt;i&gt;cool&lt;/i&gt;? What does all that chaos do to help me? Opening all the views and watching all the controls wizz around doesn't make my job any easier. In fact, it doesn't do *anything* for me except give me the false impression that I am associated with something successful and complicated, which maybe means that I'm super smart or something.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;Not true.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;I've since realized that I quit playing the violin and got into electronic music because I thought that I could get away with being creative by learning tons of geeky toys. In effect, I was trying to *engineer* creativity. So I learned the tools and specs, and even wrote and built my own tools and specs, and still my music wasn't getting as good as all the time I put into it.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;What I was missing was the *expression* - that flawed human glue that gave my music life, and can only come from playing a real instrument. Because of my unwillingness to break down and practice, my music had stayed exactly as inane and lifeless as the complex computerized tools I had learned to make it.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;This also applies to code. You know the apps that feel like the engineer wrote directly into the kind of experience he/she had envisioned? He/she wasn't caught up in the engine and gui communication abstraction or the details of the painting framework, but instead was able to grasp the big picture. This is just like writing a timeless song.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;Now dudes and dudettes, I grew up tearing apart computers and building super complex model airplanes and lego machines just like the rest of you. But, I'm digging here because I want to get &lt;b&gt;better&lt;/b&gt;, and I think learning about our greatest deficiencies is a step in the right direction.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;Sometimes you'll be working on a component and constantly alt-tabbing between iChat, Terminal, an Xcode window, and &lt;i&gt;steepncheep.com&lt;/i&gt; looking for skis and goggles. Sometimes you'll end up in a meeting where someone continuously talks off topic about his cool desktop widget or argument syntax modifier (don't look so guilty python guys ;)) when what you really need to do to make this app rip is optimize that boring-ass table schema.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;You check your email every few seconds and love the fact that you can reply without using the mouse. When you were twelve you had five monitors and felt like the center of the matrix, controlling the world through an alternate reality. "If only they knew."&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;How much of this complexity is just geeky madness? No smartypants, it's not ADD, it's an unwillingness to commit to the task and possibly too much caffeine!&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;When do the infinite xterms stop!?! How much do you perfect your editor and build environment for hours instead of biting down and just fixing the bloody algorithm?&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;I've obviously been there too.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;I stepped back and looked at the insane complexity of my music sequencer app and thought to myself. "What am I really trying to do here?" Is it watch smoothly animated audio levels or communicate a musical concept?&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;I chose the latter, pulled out my MIDI keyboard, and turned down the brightness of my display.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;Since I bit the bullet and learned a few real instruments, my techno has gotten much, much better.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;Red team go!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-827056490006470236?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/827056490006470236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=827056490006470236' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/827056490006470236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/827056490006470236'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/10/is-geek-geek.html' title='Is a Geek a Geek?'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-4251765991385949427</id><published>2009-09-29T09:31:00.003-08:00</published><updated>2009-09-29T09:47:49.576-08:00</updated><title type='text'>Music, Stealing, and Being Cool</title><content type='html'>Look guys, for all of you archaic rich white guys in the recording business that are freaked out about the internet ruining your profits, it's time for a face lift.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've never bought so much music in my life after I started listening to so much internet radio. Maybe I'm some kind of freakish standout, but whenever I have a decent job (I fluctuate) and hear something I like, I almost always buy it on the spot from Amazon or iTunes. When I don't have money, I don't buy it and wouldn't buy it anyway.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Whenever I buy music I buy a downloadable copy, and I always buy it without DRM. I have to say that I really miss having a tangible collection of albums with artwork though. I really like being at home with the computer off, walking over to my music collection, picking it up, and listening to the whole album (Steely Dan's Aja, for example). Playing scratched CD's or records totally sucks, but fondling the albums is fun.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What can we learn from this, RIAA and friends? I've never spent so much money on albums, and have NEVER bought singles before being able to hear music on pandora and other internet stations. Get it out there. Keep it free, make it available, and for crying out loud CHANGE YOUR BUSINESS MODEL!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's some things I recently bought:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;(Notice how I'm posting the links directly to the store, and notice how some of them I've probably had since the mid nineties...)&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.amazon.com/Maryjane/dp/B001IT005W/ref=sr_1_38?ie=UTF8&amp;amp;qid=1254246010&amp;amp;sr=1-38"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/41K35BCQ56L._SL500_AA280_.jpg" border="0" alt="" style="cursor: pointer; width: 280px; height: 280px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.amazon.com/Smash-Hits-Steel-Pulse/dp/B000002HBN/ref=sr_1_1?ie=UTF8&amp;amp;s=music&amp;amp;qid=1254246102&amp;amp;sr=8-1-catcorr"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51V2T75S1TL._SL500_AA240_.jpg" border="0" alt="" style="cursor: pointer; width: 240px; height: 240px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.amazon.com/gp/product/B000W1O2F6/ref=sr_1_album_3_rd?ie=UTF8&amp;amp;child=B000W1NBO4&amp;amp;qid=1254246169&amp;amp;sr=1-3"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/518M8p83XXL._SL500_AA280_.jpg" border="0" alt="" style="cursor: pointer; width: 280px; height: 280px; " /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.amazon.com/gp/product/B000W02060/ref=sr_1_album_1_rd?ie=UTF8&amp;amp;child=B000VZWNKE&amp;amp;qid=1254246242&amp;amp;sr=1-1"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/614U2UmU1bL._SL500_AA280_.jpg" border="0" alt="" style="cursor: pointer; width: 280px; height: 280px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.amazon.com/gp/product/B000VZKPGI/ref=sr_1_album_1_rd?ie=UTF8&amp;amp;child=B000VZFXEC&amp;amp;qid=1254246309&amp;amp;sr=1-1"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/51gyxZYaZNL._SL500_AA280_.jpg" border="0" alt="" style="cursor: pointer; width: 280px; height: 280px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-4251765991385949427?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/4251765991385949427/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=4251765991385949427' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4251765991385949427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4251765991385949427'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/09/music-stealing-and-being-cool.html' title='Music, Stealing, and Being Cool'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5063040943304600530</id><published>2009-08-28T22:58:00.003-08:00</published><updated>2009-08-28T23:12:31.366-08:00</updated><title type='text'>The Path</title><content type='html'>I'm having a lot of trouble getting back into programming - there's too much that bugs me about it. The duplicated compiler flags, the esoteric build configs, the unending design complexity that breaks all the rules and requires absolute perfection to feel happy about.Granted, I've always had exceedingly high standards, but why is it so hard to find the simplest joy in writing code any more?&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I can't even sit at the computer for more than an hour without feeling lethargic and anxious. How will I ever work with computers again?&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The only thing that sounds attractive at this point is sitting down with a plain text editor that includes the most basic editing functions, and write algorithms that include no less than 2 levels of functional displacement. Either I'm an extreme perfectionist, or finding the correct flow puts the level of productivity too low for reasonable work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I remember the metric, like "programmers should only write 10 lines of code a day," or something silly like that. I loved whizzing through the keyboard like oil on water, as a constant flow of ideas from my mind to the machine. My fingers were faster than my brain, which felt really good.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What does this mean? Am I moving away from code and into English or something else? Am I an artist living a scientists life? I &lt;i&gt;feel&lt;/i&gt; like this path will lead me to a higher level of skill, but am I the only one?&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5063040943304600530?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5063040943304600530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5063040943304600530' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5063040943304600530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5063040943304600530'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/08/im-having-lot-of-trouble-getting-back.html' title='The Path'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8126156248890907038</id><published>2009-07-23T13:13:00.001-08:00</published><updated>2009-07-23T13:14:26.593-08:00</updated><title type='text'>The Monster Awakens</title><content type='html'>&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Be free, but be clean. Take it one step further than the previous jokers. Use drugs, but own the effects. Live large and long, but not too rough.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;For everything that is green and good there is a black snake pit full of death and despair waiting to take it down. Don't trust the others. Make choices, make room, make love.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;It's raining outside and the wind is moving anywhere from a dead calm to a riotous torrent.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Three men walk buy ridiculously over prepared for a night time hike up a 1500 foot face. They have thick modern hiking boots with plenty of "support". Their pants have horizontal zippers half-way up the legging to convert into a goofy pair of shorts. They have external framed packs full of senseless garbage and useless recreational shwag, which can only ever possibly be used by that gorgeous climber girl accompanied by a Ken-doll additive in the REI advert. &lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Her, now, at dusk, It's too dark to tell but they might even have walking sticks to help them navigate the technical terrain offered by the rocky truck road that they are attempting to climb. Freeze dried food and goofy looking hats with expensive bug dope and sunglasses. All topped with plain, white, cotton T-shirts - the icing on the cake. These guys were ready for &lt;i&gt;anything&lt;/i&gt;.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Inside the vehicle it's quiet and dry, and there's no light other than the dim buzz from a typing machine and a rapid clickety clack of the keys.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;That anyone can learn to use a device like that at such speed is astounding. To some, it's a gateway into the rest of the world. They'd lost interest in the intimate vulnerability of one-on-one human contact, and had resigned to pushing the limits of modern communication over a massive and magical series of tubes called &lt;i&gt;the internets&lt;/i&gt;. Ahh yes, the etherial bliss of turning your life into an inane pile of attention defecation disorder. Why talk when you can type? Why call when you can text? Why chit-chat when you can tweet? What the hell does it all mean?&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;This poor average white kid renounced everything he knew for what he understood to be a conventional life of poverty. Rainy mountains outside, gusts of wind, not a sound from a man-made machine to be heard. The taste of rebellion was almost overwhelming. But what is rebellion other than doing something strictly because you aren't supposed to? Good god, what if it acutally starts to feel like &lt;i&gt;the right thing to do&lt;/i&gt;?&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Headline: "Rebellious van boy turns realist."&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Another gust of wind, more rain.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Removing all the traditional elements of homyness from your life instantly forces you to notice everything around you. A tent camping trip puts you in this same place - where you suddenly emerge through the floor to stand inside the world, instead of the world standing inside of you.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;If you are the kind of person that's trying to observe the world, this kind of perspective is absolutely essential. A parking lot is nothing more than a place to leave your car while you bound off into the park. It watches the car for you until you come back, when you thoughtlessly open the door and drive away.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;On another occasion, you may decide to sit in your drivers seat all night to get a grip on the idea of the parking lot as a place with purpose. After no more than 10 minutes the reality of the place starts to creep into your consciousness like an unseen enemy. &lt;i&gt;Other&lt;/i&gt; people come and go. Birds chirp. Dogs walk. Nothing happens, except silence.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;The best removal I've experienced in a familiar place was while staying a night in a friend's driveway in the mountains above town. The owners of the house were on a rafting trip and I decided to poach their power and real estate for a peaceful night in the boonies, just so I could have an opportunity to watch "Cocktail" with Tom Cruise in my neo-hippy van.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Half way through the movie the motion activated porch light clicked on and I felt a tingle in my spine. Swinging around, I saw a relatively small (it was about 36 inches long) cat-like animal meandering up the gravel driveway. It paid no attention to the light and walked slowly off the property and into the woods.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;I'd never seen a lynx outside the zoo, and had never seen a wild animal at a friends house. I was astounded.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;With a click, the cabin light is on. I installed 10W warm-white bulbs in the light near the back of the cabin, and 10W cold-white bulbs in the front. The warm light gives a homier feeling when reading, and the cold-white makes it a little better to see when cooking or dealing with other things in the cabin.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;The light changes the mood. It's serious now. I'm actually &lt;i&gt;living&lt;/i&gt; here. This spot is my &lt;i&gt;place&lt;/i&gt;, or at least the closest thing that I have to one. The gate on the road below ensures that no one will drive up this far, and anyone that has a mind to hit the trails this far up in the mountains in the middle of the night is alright by me.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Without the dark and the rain and the wind, I was in the world. But now, with the simple flip of a switch, I've crossed the line and now the world is in me. It is what I've made it, a small, grey, rectangular room with a bed and some pictures. There's plastic everywhere, and the faint hum of propane keeping the food cool.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Deep below, the urban jungle sits and waits with it's twinkling lights and vast expanse. It doesn't belong within it's surroundings, but as far as we're concerned it will be there forever. All it stands for at this moment is a reminder that I can see it and therefore I'm not &lt;i&gt;in&lt;/i&gt; it, which is good enough for me.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;An hour later the monster has arrived, it's essence is numbing. The parked vehicle rolls and shakes with incredible rage as sand and gravel hit the walls with force. Something has happened and the beast is outside, and angry. "Get out, get out of my house," it howls.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;The gusts come at random intervals and without warning.  They are incredibly strong and the van's suspension works while the coach lists from left to right. The wind is perfectly square with the broad side of the vehicle and it's full force is felt on it.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;I lost my wits over a couple of late weekend nights marked by the consumption of an inhuman amount of alcohol. Some times I wonder if the car will be pushed off into into the ravine patiently waiting only 6 feet away. How much force does it take to overturn a one and a half ton metal monster? If the car stays under control while pushing 80 down the freeway then surely there's no danger in parking a car in winds of up to 100 miles per hour...&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;The wind regularly reaches hurricane speeds at these altitudes within the city limits, but regularly goes unreported. Those who chose to build houses up here are considered crazy outsiders, so the typical weather monitoring stations and evacuation warnings seem unnecessary.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Tonight the harsh reality of being out here sets in at a primal level. Fortunately for the hungry monster outside, I'm locked on the wrong side of a gate that restricts access to the expanse of the Chugach State Park. But inside the van with the reading light on and the down comforter out, I am not in the world - the world is still inside &lt;i&gt;me&lt;/i&gt;. As long as my ski box stays on the roof of the car I'll be able to get some sleep.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;The next morning the mountains were as calm as sleeping babies. The dirt road was dry, the wind was gone. &lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;This climate here is bigger than us - it's truly unforgiving.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;When &lt;i&gt;normal&lt;/i&gt; places get a low pressure system you'll see a scattered blanket of green precipitation pixels covering the area. The system may be a few hundred miles long - roughly the size of Teton County in Wyoming - and may include sporadic fits of water and sun.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;But when weather comes in up here in Alaska, it comes in blocks that last for days.  Clouds of precipitation here look more like more like a giant green amoeba, and can include the entire state of Wyoming itself.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;Last night the wind began about 9:30, when I drove up the pullout at dusk. By 11 it was gusting to incredible speed and blowing debris all over the side of my van. By 3am the gusts had become steady hurricane-force hammering and there was no sign of it letting up.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; text-indent: 36.0px; font: 12.0px Helvetica"&gt;My hangover from the night before would have afforded my body about 10 hours of deep, deep sleep, but the last time I looked at the clock it showed 5 am, the wind still screaming "This is my HOUSE!" Desperate for sleep, I slept in until 11 am and woke to this picture-perfect episode of beach life. I could have easily lit a candle in front of the car. A burning incense ember would have smoked straight up  with beautiful designs of homeostasis delight.&lt;/p&gt;&lt;div style="text-indent: 36px;"&gt;&lt;span class="Apple-style-span"   style="font-family:Helvetica, fantasy;font-size:100%;"&gt;&lt;span class="Apple-style-span" style="font-size: 12px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8126156248890907038?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8126156248890907038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8126156248890907038' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8126156248890907038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8126156248890907038'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/07/monster-awakens.html' title='The Monster Awakens'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-537574200847241820</id><published>2009-07-14T12:06:00.004-08:00</published><updated>2009-07-14T12:11:31.622-08:00</updated><title type='text'>Sucked In</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-kPtlLn0YiA/SlzmZi8s1QI/AAAAAAAAAaA/tlEKEKdIdbg/s1600-h/IMG_2275.JPG"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 240px;" src="http://1.bp.blogspot.com/_-kPtlLn0YiA/SlzmZi8s1QI/AAAAAAAAAaA/tlEKEKdIdbg/s320/IMG_2275.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5358410983216567554" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;After doing a great job of moving on from a dead software job, a friend of mine managed to suck me into a small data reporting project for his renewable energy company's solar panel installations. I will not let them pay me so I can't &lt;i&gt;actually &lt;/i&gt;get sucked in to deep.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;When I asked I said "Oh that's so easy, you just slap together an http/python/chart/template stack. No problem." Considering I'm not interested in getting sucked into another software project yet, my first mistake was to say "no problem."&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;Anyway, I had a wicked hangover and some free time so I sat down at a coffee shop to find a good chart library for python. Googling for "python charts" I decided I didn't want to wade through a list of libs and almost gave up. Then I found google charts. Awesome.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;Basically you just call a url with all your chart data and it gives you a sick graph back. You can just put the url in the src attribute for an img tag and stick it in a web page and you've got a report.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;What these guys do is install solar panels for hot water heating in the Anchorage area. They have this cheesy little data feed coming off it that they could use to trouble shoot their installations and provide marketing data to future customers, but no reporting. Graphs. Tables. Matrix transformations. bleh. At least it's for a good cause.&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px"&gt;&lt;br /&gt;&lt;/p&gt; &lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;Meanwhile, getting sick of programming but fighting off a general interest and knack for code poses a very interesting problem: What kind of work feels healthy and what kind of work is too introverted. It's a steep hill for sure.&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p style="margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica"&gt;&lt;br /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-537574200847241820?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/537574200847241820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=537574200847241820' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/537574200847241820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/537574200847241820'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/07/sucked-in.html' title='Sucked In'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_-kPtlLn0YiA/SlzmZi8s1QI/AAAAAAAAAaA/tlEKEKdIdbg/s72-c/IMG_2275.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-100847038869514316</id><published>2009-06-21T13:48:00.010-08:00</published><updated>2009-06-21T16:26:54.914-08:00</updated><title type='text'>No More Computer Junk</title><content type='html'>&lt;div&gt;&lt;div&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: left;"&gt;I gave up the last of my residual computer junk to the AKLUG (Alaska Linux Users Group) the other day. It was like three towers and a ton of cables and mice and stuff that I finally realized I would never touch again. Now I'm down to just my macbook, some books, and a small box of essential stuff that I use on a regular basis, which feels really good.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-kPtlLn0YiA/Sj7CSL2m9yI/AAAAAAAAAZg/Y9ejRdTKBh0/s1600-h/IMG_0654.JPG" style="text-decoration: none; "&gt;&lt;img src="http://3.bp.blogspot.com/_-kPtlLn0YiA/Sj7CSL2m9yI/AAAAAAAAAZg/Y9ejRdTKBh0/s320/IMG_0654.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5349927025037997858" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 320px; height: 240px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style=" ;font-size:small;"&gt;The remainder of all my "techy" stuff that will come with me. Notice the inclusion of real, actual, books.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I became a bit of a loner kid by growing up an only child moving between my dysfunctional parents' houses a few times a week. Always on the go, I adapted to the transient lifestyle by becoming deeply involved in individualistic hobbies like legos, remote control cars, and video games. I was primed for a life on a computer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Families that don't spend much time truly opening up to each other on an emotional level create environments that raise solitary, bored kids. Their houses get bigger so they can stay further apart, they watch more TV as a "family activity," and their kids end up in doors playing video games and relating to their friends via proxies like text messages and online social networking. Families that spend more time relating their deeper emotions become closer, and less forced into loner activities like video games and facebook.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As I grew up I got into the habit of drinking tons of coffee and coke-a-cola while staying up all night coding my brains out, and as a result developed a significant problem with insomnia and poor resistance to asthma and allergies (sound familiar?). In college I spent 100% of my energy cranking on my senior project by walking between classes and on the subway with my head down working through design problems on my notepad. I was telling myself that if I was going to be the best I had to be putting all my effort into being the best. I was thinking all the time and never gave my chance to rest.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then, one day while on a business trip this last January I looked around the snazzy Hollywood studio that I was working for and started to notice how the dark, window-less environment was extremely conducive to solitary, inwardly confined work (although this was one of the better offices I've worked in). Later I slowly started to see how I'd built a lifestyle around controlled environments; working on a computer, living alone, working alone, even participating in non-team sports like cross country running and skiing.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-kPtlLn0YiA/Sj7CeDbi7wI/AAAAAAAAAZw/n3LrE1lOwlI/s1600-h/IMG_0649.JPG"&gt;&lt;img src="http://3.bp.blogspot.com/_-kPtlLn0YiA/Sj7CeDbi7wI/AAAAAAAAAZw/n3LrE1lOwlI/s320/IMG_0649.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5349927228935433986" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 320px; height: 240px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;i&gt;PK in the mountains.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I took a step back and noticed that all the energy and orderly living is centered around the desk, and ultimately the computer screen. The kitchen, bedroom, bathroom, and living area had become dirty, cluttered places with no chairs and empty walls. They had little value as places of habitation, and served only as compliments to all the energy and color that surround the computer desk.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This unbalanced lifestyle is counter-productive to realizing your potential.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Since I was in high school I've sporadically spent a lot of time training and trying to find what it takes to succeed at the top level. While I never managed to make the jump to the next level, I learned that succeeding only requires two things: a genuine, and deeply personal interest in the sport, and an adequate balance of all parts of life which enables you to train &lt;i&gt;well&lt;/i&gt; &lt;i&gt;enough&lt;/i&gt; to be the best.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-kPtlLn0YiA/Sj7CIjGChQI/AAAAAAAAAZY/b6NJ5XyXLSw/s1600-h/IMG_2127.JPG" style="text-decoration: none;"&gt;&lt;img src="http://1.bp.blogspot.com/_-kPtlLn0YiA/Sj7CIjGChQI/AAAAAAAAAZY/b6NJ5XyXLSw/s320/IMG_2127.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5349926859478041858" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 320px; height: 240px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;&lt;i&gt;A shot I took of the fastest skiers in the country while covering this year's US Distance Nationals.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This applies to any kind of success you want in your life. If you really really love something then you're all set to be the best. If you really really love it &lt;i&gt;and&lt;/i&gt; are content in the other parts of your life, then not only are you set to be the best but you also have what it takes to be the best. I believe that's the meaning of "talent," and it applies to everything I've tried to be the best at - music, endurance sports, and computer programming.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That's why "talent" is so complex. If someone wants to be the best ski racer because they simply want everyone to love them for being the best, they will become an ego maniac and will eventually hit the wall when the public praise doesn't make up for the price of commitment.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-kPtlLn0YiA/Sj7B4x-5qYI/AAAAAAAAAZQ/4vI74i7m-24/s1600-h/IMG_0640.JPG"&gt;&lt;img src="http://1.bp.blogspot.com/_-kPtlLn0YiA/Sj7B4x-5qYI/AAAAAAAAAZQ/4vI74i7m-24/s320/IMG_0640.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5349926588596726146" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 320px; height: 240px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;A friend of mine, a top mountain runner, slowly becoming a bionic man from repeated ankle rolls. Looks like something needs to change.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;If someone's got the genetics for a bone structure and cardiovascular system to make them a naturally fast track sprinter, they might also have a tough family life that results in a drinking problem or some other vice, and will never be able to see their potential through the bar bills and hangovers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;If someone only likes computer programming because it provides them a job where they only have to communicate through instant messenger, they might develop into a worker with tunnel vision and poor people skills that has a hard time knowing the difference between a sexy implementation and the user's &lt;i&gt;real needs&lt;/i&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-kPtlLn0YiA/Sj7Cwa0JXMI/AAAAAAAAAZ4/EW5SM5ROqXw/s1600-h/IMG_0651.JPG"&gt;&lt;img src="http://3.bp.blogspot.com/_-kPtlLn0YiA/Sj7Cwa0JXMI/AAAAAAAAAZ4/EW5SM5ROqXw/s320/IMG_0651.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5349927544450276546" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 240px; height: 320px; " /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;i&gt;&lt;span class="Apple-style-span"  style="font-size:small;"&gt;A friend demonstrating "no pain no gain" yesterday in the mountains behind Anchorage.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The point is that no matter what you're doing, you will do better the more you are able to balance your talents. That's why I think that programming computers from a social jail cell is about as awesome as writing powerful music having never been in love or had a rough breakup.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Purging all my old computer junk is a great start. Game on.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_-kPtlLn0YiA/Sj7BmtZmUEI/AAAAAAAAAZI/gjds-qxqVNk/s1600-h/IMG_0623.JPG" style="text-decoration: none; "&gt;&lt;img src="http://1.bp.blogspot.com/_-kPtlLn0YiA/Sj7BmtZmUEI/AAAAAAAAAZI/gjds-qxqVNk/s320/IMG_0623.JPG" border="0" alt="" id="BLOGGER_PHOTO_ID_5349926278128881730" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 320px; height: 240px; " /&gt;&lt;/a&gt;&lt;div&gt;&lt;div style="text-align: center; "&gt;&lt;span class="Apple-style-span"  style=" ;font-size:small;"&gt;&lt;a href="http://www.alaskamountainrunners.org/calendar.htm#cp"&gt;&lt;i&gt;Crow Pass&lt;/i&gt;&lt;/a&gt;&lt;i&gt;, &lt;/i&gt;&lt;a href="http://www.akhs.atfreeweb.com/Hikes/CrowPass.htm"&gt;&lt;i&gt;My Zion&lt;/i&gt;&lt;/a&gt;&lt;i&gt;.&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-100847038869514316?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/100847038869514316/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=100847038869514316' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/100847038869514316'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/100847038869514316'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/06/no-more-computer-junk.html' title='No More Computer Junk'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-kPtlLn0YiA/Sj7CSL2m9yI/AAAAAAAAAZg/Y9ejRdTKBh0/s72-c/IMG_0654.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1746076233083703314</id><published>2009-06-18T12:10:00.002-08:00</published><updated>2011-09-06T10:00:32.213-08:00</updated><title type='text'>Sick of Programming</title><content type='html'>I quit my job two weeks ago. I don't want to program at work any more. I'm sick of being inside and stationary, and I'm sick of working in an environment where people don't talk to each other.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Over the last few years I've worked for one company producing high-end music software. When I came in I was invincible, and after working for someone with a completely different approach to problem solving (right down to code style), I've become weak and ineffectual.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, those days are over. I'm going to get my style back and get back on the wagon of invincibility. Programming is art and should be a pure and unadulterated stream of conciousness from the developer to the machine. Python is art. Good design is art. Milestones are art. Good energy is art.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A lot of people tend to think that developing software means you have to work hard in a tunnel environment, like a battery sucked off the matrix. Well, I don't subscribe to this philosophy. I believe that you have to really reach your potential in all walks of life you have to get up from your desk and replenish your sense of life between blocks of code. You have to joke about TPS reports and Bill Lumbergh's ass and fling little paper shells at each other and keep a tally. The other guys around you need a recharge, too, and then you can sit back down and bang out the last few lines with clarity and conviction.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'm psyched to get back to coding for the sake of art, where the idea and the implementation are solid gold. I quit my job, gave up my place, and I'm going to go bar tend in Jackson Hole and program for fun. I've got some PyQt dev kits to write to simplify audio software development, and have a huge &lt;a href="http://www.google.com/search?client=safari&amp;amp;rls=en-us&amp;amp;q=remove+the+GIl&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8"&gt;GIL&lt;/a&gt; to deal with. We'll see what happens.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1746076233083703314?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1746076233083703314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1746076233083703314' title='70 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1746076233083703314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1746076233083703314'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/06/sick-of-programming.html' title='Sick of Programming'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>70</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8279726815646733749</id><published>2009-04-28T02:46:00.003-08:00</published><updated>2009-04-28T02:50:54.322-08:00</updated><title type='text'>Bliss</title><content type='html'>WindowMaker running a simple, nifty theme on two screens using emacs on an xterm is bliss. Yeah, sure, the big guys are all refined and awesome and stuff, but for development there is nothing better than WindowMaker and a few xterms.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Late at night I ran across some "current" window maker screen shots including that same old Matrix theme we all had back in '98. It brought back a whole different feeling that I've missed these last few conferment years.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What's bliss to you?&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8279726815646733749?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8279726815646733749/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8279726815646733749' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8279726815646733749'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8279726815646733749'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/04/bliss.html' title='Bliss'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6272359491367031867</id><published>2009-04-15T08:00:00.003-08:00</published><updated>2009-04-15T08:09:14.186-08:00</updated><title type='text'>Managing Precompiled Headers</title><content type='html'>You should only include third party headers in a precompiled header when using it for development. If you include headers from your own project, your build system will constantly have to recompile your pch every time you edit one of your own headers, which defeats the purpose of using precompiled headers in the first place.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;But, it just occurred to me that you can break this rule for release builds. By using a different pch for your release builds you can include all of your project's headers, which will make even large projects build extremely fast. Nice.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6272359491367031867?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6272359491367031867/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6272359491367031867' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6272359491367031867'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6272359491367031867'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/04/managing-precompiled-headers.html' title='Managing Precompiled Headers'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5025597039162401764</id><published>2009-03-06T12:38:00.004-09:00</published><updated>2009-03-06T12:46:31.186-09:00</updated><title type='text'>Automating Your Testing and Build System?</title><content type='html'>GOAL: For a tester to hit a "build" button to get the current trunk revision.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We want a fast bug report to build turnaround time, like immediate. A web page with a "bugs fixed" revision log entry, build errors, and build button. This would require a few things on the end of the developers to work:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;1) Unit tests. First test: revision builds successfully. Subsequent feature tests included as well.&lt;/div&gt;&lt;div&gt;2) Super stable trunk. The developers must take responsibility to keep the trunk as stable as possible by learning to use branches and patching techniques.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Has anyone else done this? I wrote something once in a Trac tool for a python app with extensive unit test reporting (made easy with an exception-based runtime), but never for a C++ application. Are there any web apps like this out there?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The most important thing is to remove the build phase from the project manager's work plate. &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5025597039162401764?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5025597039162401764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5025597039162401764' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5025597039162401764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5025597039162401764'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/03/automating-your-testing-and-build.html' title='Automating Your Testing and Build System?'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-4735798092683354125</id><published>2009-03-04T09:10:00.004-09:00</published><updated>2009-03-17T09:23:46.350-08:00</updated><title type='text'>La Musica Bonita</title><content type='html'>Flash forward fifteen years in the future. and electronic music is dead. The word "genre" has been whittled down from 800 permutations including funk, house, ambient, classical, minimal, rock, and indie, and now is used to differentiate between two musical environments - live and recorded.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Just like the merging genetic avenues of the human race, all of the technologies and methods learned during the electronic revolution have been absorbed into a single, advanced, tan-skinned entity, simply known as "music". Artists have learned to effectively use computers and other signal processors just as effectively as violins, violas, drums, and kitchen appliances to create music that their cultural parallels can relate to, understand, and enjoy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Music schools do not teach musical fundamentals with regards to the instruments or methods used to produce music, but instead students are encouraged to practice expressing themselves with rhythm and intonation, by singing and banging and watching and listening to their fellow learners. Before a student opens his or her creative eyes they are asked to open their ears and their mind, in an effort to help them connect to their own emotional purpose and meaning of the expression they will try to master.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Drum machines, sequencers, glitch racks, send tracks, software components, storage formats and recording techniques have all become so advanced that the majority of artists on the scene have reconnected with their abilities to directly express their thoughts and emotions through mastery of their instruments of choice. Industry standard production tools are ubiquitous, and every aspiring artist is free to explore their world of sonic pleasure in the comfort of their daily lives.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The primitive fetish with the mechanized and lifeless sounds of today are gone, and have been replaced with organic and humanized versions, giving an accurate and intimate view into the artist's thoughts. DJ's and mash-up architects can no longer escape the harsh scrutiny from the musical world, they are now known for what they are - regurgitators of counterfeit art, and the composers of harmony heavy and over produced dance tracks have found their rightful places as backup bass players and professional studio engineers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Groovy, baby.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-4735798092683354125?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/4735798092683354125/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=4735798092683354125' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4735798092683354125'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/4735798092683354125'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/03/la-musica-bonita.html' title='La Musica Bonita'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5944958169340514511</id><published>2009-03-02T22:47:00.002-09:00</published><updated>2009-03-02T22:53:47.166-09:00</updated><title type='text'>The Most Important Streaming Video Feature</title><content type='html'>There are a few videos that I watch online, like Family Guy, South Park, some random Adult Swim stuff, and netflix movies. I'm really psyched to have them available, but I can't believe that none of them use a calculated wait on the buffer to ensure that the video will playback smoothly. Yeah, sure we all have different speeds, but do some simple math and adjust the window accordingly! At least let us know how where the buffer is in relation to the playback cursor (South Park!) so we can do it ourselves if necessary.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think if you ask anyone out there that they would rather wait longer for the video to start than sit there and hit pause a hundred times to fill the buffer. Honestly! Sites that have these problems:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;www.adultswim.com&lt;/div&gt;&lt;div&gt;www.southparkstudios.com&lt;/div&gt;&lt;div&gt;www.netflix.com (albeit the best)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Is there something that I'm missing about the basic use of a ringbuffer? has this been done and found to be impossible? &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5944958169340514511?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5944958169340514511/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5944958169340514511' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5944958169340514511'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5944958169340514511'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/03/most-important-streaming-video-feature.html' title='The Most Important Streaming Video Feature'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1464578622344177545</id><published>2009-02-07T11:05:00.010-09:00</published><updated>2009-02-07T12:16:40.645-09:00</updated><title type='text'>The Sweet Setup</title><content type='html'>What's on my iPod right now: &lt;a href="http://www.amazon.com/Vegas/dp/B000W297V4/ref=sr_f3_1?ie=UTF8&amp;amp;s=dmusic&amp;amp;qid=1234038568&amp;amp;sr=103-1"&gt;Crystal Method: Vegas&lt;br /&gt;&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_-kPtlLn0YiA/SY3u8FWsAbI/AAAAAAAAAXI/Qc2146mLqhI/s1600-h/IMG_0287.JPG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 240px;" src="http://4.bp.blogspot.com/_-kPtlLn0YiA/SY3u8FWsAbI/AAAAAAAAAXI/Qc2146mLqhI/s320/IMG_0287.JPG" alt="" id="BLOGGER_PHOTO_ID_5300155052481839538" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;I am very psyched about my setup for making techno. I use a bottom-shelf macbook, an Evolution UC-33e, some bomber noise-cancelling headphones, and Ableton Live. I can go anywhere, it all fits in a backpack, and has all my bases covered. It would be nice to find a way to fit a small midi keyboard into the mix to smash out some bass lines or melody, but I'm pretty stoked about my setup.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The UC-33e is basically a midi mixer with faders and knobs for 8 channels. It's bus powered and pretty much does everything I need to jam. Once you start to settle into your own production patterns with knob assigments and such a simple controller with no labels or assignments really work well. Just like an instrument, as a beginner you just need to do a lot of experimentation to make your tools work for you. For years I thought a killer setup was a killer app and killer controller that gave me canned looping and functions to do some live techno producing. Well, if you want to do that just punt and go be a DJ.&lt;br /&gt;&lt;br /&gt;When put together a mix it's really important to have super quality monitors, and a room that doesn't suck your sound to peices. But, again the most important thing is that you are just used to your sound medium. I bought the terrific top-end $300 Bose noise-canceling headphones, and now I can work on the plane or in a construction site, and the sound is pretty good. If I really want to finish off a good production I do it at home in a studio environment. You spend most of your time being creative where the mix-down doesn't matter, so being mobile and flexible is really nice.&lt;br /&gt;&lt;br /&gt;What really makes everything possible for me is Ableton Live. It runs and does everything you need on today's cheapest laptops, and is so flexible and well designed that I never think about the role the software plays. Make yourself a default set with midi mappings for your controller, and start having fun.&lt;br /&gt;&lt;br /&gt;The macbook is great because it sleeps very well, and never gets in the way of my music. It is a very simple computer, CoreAudio is as solid as it gets, and with the Network midi bus you can midi sync and jam with another person's laptop over wifi. Now THAT's what I call bad-ass.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-weight: bold;"&gt;OK, now let's &lt;span style="font-weight: bold;"&gt;talk about style.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;The blending of electronic and organic styles can make for some pretty touchy and complex subjects when you are making music yourself. You are cramming your poor creative nerves into all of this technology, and you've seen the cool things that it can do but it's tough to find your niche. I'd like to do more complex looping and stuff, but for now I'm settling in to deep and progressive trance, and The Sweet Setup is very, very good at that kind of music.&lt;br /&gt;&lt;br /&gt;The core of my musical guts comes from arpeggiated synths, a delay, a simple bass line, and maybe some pads if I want to make it a bit softer. For the most part I use canned drums since I'm just not that good a programming them, though I'll usually do my own kick drums since they play so much of a role in the sidechaining compression and gutsy feel of the techno.&lt;br /&gt;&lt;br /&gt;Progressive is all about long sweeping transitions and effective use of spacious effects. You pull your listener into the sounds because they simply don't change as often, which makes them more engaged in the intricacies of the sounds. Having that manual control with the hardware controller makes all the difference in the world for expressiveness.&lt;br /&gt;&lt;br /&gt;Yes, you will get used to the nuances of your effects and sound-frequency space, and after a while you can actually become a performer that makes full use of the DSP palette, just like you always imagined that first time you saw a DJ fake you out with his stupid dramatic hand genstures just to hit the play button or turn up the bass.&lt;br /&gt;&lt;br /&gt;Further, I think you really know you're getting somewhere when you start using a compressor's controls in real-time. I usually use Live's built-in compressor with manual control over the threshold, and MAYBE the release as well. It's not just for post-production mix down anymore, baby!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Getting it on paper&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The real killer is getting your creative process down. Being my own worse critic, I've always pushed myself to make something decent as fast as possible. Unfortunately, having my standards way high in the stratosphere meant that I missed a lot of opportunities to just get into the patches and music that was right in front of me all the time! Several years I wasted when I could have been learning basic composition skills and the overall flow of music, where I could have nailed down my creative processes from week 1.&lt;br /&gt;&lt;br /&gt;The big lesson is that it doesn't take SQUAT to sit down and jam with people. You could get pretty far with a two-peice sine-wave band for crying out loud, so don't worry about the fact that you can't get that huge trance sound right away. Most of those sounds are far simpler than you think anyway.&lt;br /&gt;&lt;br /&gt;So the way I approach my creative process is to sit down with a simple synthesizer and try to think more about the expression of the music than the tools I'm using or the way it sounds. Music is a method for describing what you are feeling inside your mind and body, so plug in one of those canned drum loops and start playing with it. Yeah, go make it sound shitty, but also try to understand that the music in't about what goes on the recording, it's what you are feeling when you are playing it. Stick with that and you'll go places.&lt;br /&gt;&lt;br /&gt;Anyway, I usually pull in a patch that I know really well like the "Analog Bass" synth patch that comes with Ableton's "Analog", and start messing around on the keyboard. I usually assign the cutoff param to a knob on my midi controller, and the mixer fader to the fader on my midi controller. Then I find some drums and do the same with a cutoff and fader. Then I add some pads, and go from there. The rest is history.&lt;br /&gt;&lt;br /&gt;Remember, the best setup is a setup that doesn't get in your way.  Fun stuff.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1464578622344177545?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1464578622344177545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1464578622344177545' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1464578622344177545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1464578622344177545'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2009/02/sweet-setup.html' title='The Sweet Setup'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_-kPtlLn0YiA/SY3u8FWsAbI/AAAAAAAAAXI/Qc2146mLqhI/s72-c/IMG_0287.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2263045901171778943</id><published>2008-12-05T13:13:00.004-09:00</published><updated>2008-12-05T13:32:18.191-09:00</updated><title type='text'>Fear, Uncertainty, and Doubt</title><content type='html'>The python community thrives on discussion. Like really, long, heated discussion. Python is by far the cleanest and most artistic language I have ever seen, and the CPython API is equally as impressive. I've actually become very entertained the last several months just by reading discussions about language design, most prominently about discussions regarding the GIL. Sometimes the discussions get pretty heavey, and a lot of times participants get a little fired up. Recently I wrote the following response to this blog post, which you may have read on planet python:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://jessenoller.com/2008/12/05/python-30-whats-the-point/"&gt;Python 3.0: “What’s the Point”&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;My response:&lt;br /&gt;&lt;br /&gt;There are two opposing forces here, and you can see them just as well in discussions about the GIL.&lt;br /&gt;&lt;br /&gt;The first one is the progressive and more open-source oriented mentality that promote better features and cleaner code. These are the people that hang out on IRC, write really cool extensions, and generally have a very academic and intimate knowledge of the python api.&lt;br /&gt;&lt;br /&gt;The second one is a more practically goal and business oriented mentality, that promotes stability and proliferation. These people are more often than not getting paid to write the specific chunk of code in which they choose to discuss, and are blessed with not having to worry about the imperfections of the code as long as they make their deadlines.&lt;br /&gt;&lt;br /&gt;There will always be a compromise between these two forces. I like to fall into the first category, preferring to take my time with unit tests and a detailed understanding of my code, because I do not enjoy going back and fixing concepts that should have been completed the first time. But, I don't get paid for my clean concepts, I get paid to meet deadlines and to be able to maintain the code I've written.&lt;br /&gt;&lt;br /&gt;Your code doesn't need to be perfect to have fun AND make money, and your language doesn't either. But, you also need to have that bleeding edge branch to keep the spirit of the craft alive. I've never used ruby, and I'll never write java again, but one thing I can say about the python community is that there is a very large number of people that are involved in discussions across the spectrum, and this is nothing but healthy for the language, just like bleeding edge 3.0 releases and easily maintainable 2.5.1 XServe releases.&lt;br /&gt;&lt;br /&gt;Oh yeah, and in the words of the BDFL, "CODE TALKS." This applies to both groups.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2263045901171778943?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2263045901171778943/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2263045901171778943' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2263045901171778943'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2263045901171778943'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/12/fear-uncertainty-and-doubt.html' title='Fear, Uncertainty, and Doubt'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5003414825020185118</id><published>2008-12-02T18:17:00.003-09:00</published><updated>2008-12-02T18:39:00.938-09:00</updated><title type='text'>Writing and Selling a Small Commercial Product</title><content type='html'>So let's say you are a smart little developer that has an idea for a small niche software product. You're thinking you could spend X number of hours putting together your nifty tool, and then  publish it on your web page with a commercial license, and maybe an open source license as well. What sort of hurdles would you expect to run into? Would bug fixes be too much of a bother? Does publishing your code under an open source license help with these bugs? Just how easy is it to sell your code and publish it for free at the same time? Is it feasable to put into your commercial terms a clause limiting your liability for use of your code? Would selling a well-constructed piece of software make you more attractive to prospective employers? How often has a single person done this (&lt;a href="http://www.rawmaterialsoftware.com/"&gt;I know Jules did when he wrote juce&lt;/a&gt;)? Lot of questions!&lt;br /&gt;&lt;br /&gt;Having worked in the audio world for a couple of years I've got a couple of ideas for tools and wrappers I'd like to write and sell for a little extra cash in between jobs, so naturally this idea is interesting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5003414825020185118?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5003414825020185118/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5003414825020185118' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5003414825020185118'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5003414825020185118'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/12/writing-and-selling-small-commercial.html' title='Writing and Selling a Small Commercial Product'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8623918506580984323</id><published>2008-12-02T17:46:00.007-09:00</published><updated>2008-12-02T18:36:08.855-09:00</updated><title type='text'>Does Remote Work Imply Strong Encapsulation?</title><content type='html'>We have a C++ project with three primary developers. The managing developer #1 is in L.A, developer #2 is in Berlin, and I am in Anchorage. The manager works with the boss and product designers and developer #2. I work with developer #1, and almost never interact with developer #2 in Berlin because of the language barrier and because our work rarely overlaps. I have next to zero interaction with anyone else like the boss or product designers.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The problem is that I am afraid to add new features because the trunk is so fragile. I am constantly stepping on the manager's toes by committing test code right before a beta release, or writing code that doesn't work with this or that platform nuance, and all of these problems happened because I was just plain out of the loop. We have no online forum or dog bowl to establish a sense of community, and what's really bad is that I can't write anything interesting that isn't 100% in line with the manager's current priority 1 bug for fear of getting a stressed out phone call from him. This includes cleaning up our mistakes from the start-up period, and writing example python scripts for our new scripting engine, of which no one understands how to use correctly. All three of our code styles are completely different, and there are strange looking blocks of code that have no comments explaining the obscure bugs they fix. I also haven't been to LA to see them in 1.5 years.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So my question is, does working remotely imply that your role works like a black box, strongly encapsulating your function to avoid conflicts? Should I be given more interfaces to deal with, or should my manager work to provide this encapsulation? If you were to meet with your co-workers every, say 1 out of 6 months, how much would this affect your encapsulation? One month out of the year? As developers we can certainly work remotely, but at what point do you start to lose motivation as minion of many, and what can you do to promote interesting creative, and motivating work? I can't add interesting features or do anything other than feel like a robot intern lapping at the task pellet feeder, and being a motivated programmer I find this mind-numbing, and I want to quit.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What are your experiences? Thoughts?&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8623918506580984323?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8623918506580984323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8623918506580984323' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8623918506580984323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8623918506580984323'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/12/does-remote-work-imply-strong.html' title='Does Remote Work Imply Strong Encapsulation?'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-7802311780288745154</id><published>2008-11-28T11:06:00.002-09:00</published><updated>2008-11-28T11:20:57.909-09:00</updated><title type='text'>Static</title><content type='html'>I have a tremendous problem with radio interference in my house. My KRK studio monitors blast KMXS 103.1 so loud that I can hear it over music I am actually playing through the speakers. It's so loud that it's about the right volume for listening to the radio at work in an office.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The interference is definitely worse on one side of the house, and significantly better about 15 feet away. Unfortunately my place isn't that big so I can't move my stuff. Cell reception here is also bad, and Clearwire only works in one corner of the house - the customer service reps said they've never seen interference so bad.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Does anyone know how to help with this? It's been driving me crazy for 2 years, and I'm about to call the FCC.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;- My power and signal lines never cross.&lt;/div&gt;&lt;div&gt;- I rent, and so can't insulate the walls.&lt;/div&gt;&lt;div&gt;- I use a standard american 3-pronged 120V connector, and all electronics are grounded to the wall.&lt;/div&gt;&lt;div&gt;- Ferrites on the signal lines inside the powered speakers don't help.&lt;/div&gt;&lt;div&gt;- The interference is only high frequency, and is directly affected by moving signal cables and power bricks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I've only found a quite cable layout once, and as soon as I moved something I lost it. It's near impossible to find again. So frustrating. I used to like listening to The Police..&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-7802311780288745154?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/7802311780288745154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=7802311780288745154' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7802311780288745154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7802311780288745154'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/static.html' title='Static'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-79573589061251219</id><published>2008-11-22T14:54:00.003-09:00</published><updated>2008-11-22T14:56:22.702-09:00</updated><title type='text'>New Wiki Entry: Embedding Python in a C++ Application</title><content type='html'>Man, I've been a posting fool lately. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I wrote a rather comprehensive wiki on embedding python in your C/C++ application. The page includes descriptions and recipes for different scenarios. Enjoy!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;a href="http://trac2.assembla.com/pkaudio/wiki/EmbeddedInterpreter"&gt;Embedding Python in a C++ Application&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-79573589061251219?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/79573589061251219/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=79573589061251219' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/79573589061251219'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/79573589061251219'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/new-wiki-entry-embedding-python-in-c.html' title='New Wiki Entry: Embedding Python in a C++ Application'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8977330009803457406</id><published>2008-11-22T14:10:00.006-09:00</published><updated>2008-11-22T14:23:39.348-09:00</updated><title type='text'>Concurrency Contexts</title><content type='html'>I noticed my self saying "where the script is run", describing what thread was executing the script code in my C++ app. Is it more natural to think of a thread as a physical context, comparing it to a 'where' instead of 'what'? In the real world threads are represented by objects that do something, while no one actually thinks of something as having two different functions. The TV produces both light and sound, but this isn't by coincidence. Someone created the aggregate function of producing both light and sound by coupling two different objects that do one thing. Just as none of the speaker and screen's parts overlap (physically impossible), none of their code would overlap if they were made of software.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Applying the idea to threads, why does the code have to overlap between threads? Is sharing memory a prerequisite to concurrent execution, or is it simply an easy way out of your problem that could probably be better understood?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hmmm. In my case sharing memory between threads makes it very easy to work with the audio data, but maybe using separate processes would be a better analogy? One way or another, it seems like having ONE perfectly-defined abstraction for concurrent execution would be the way to go.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8977330009803457406?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8977330009803457406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8977330009803457406' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8977330009803457406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8977330009803457406'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/concurrency-contexts.html' title='Concurrency Contexts'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2677578498810483034</id><published>2008-11-22T10:35:00.003-09:00</published><updated>2008-11-22T11:30:04.398-09:00</updated><title type='text'>Back To Basics, Getting the Flow</title><content type='html'>Do you ever pick up your old, slow laptop and wish that it hadn't obsolescicized so fast? I absolutely love my 12" ppc powerbook. It isn't fast enough to play a decent live set using &lt;a href="http://www.ableton.com/"&gt;Ableton Live&lt;/a&gt; for which my white macbook is perfectly suited, and it only has one processor which makes it a turtle on the highway for development, but it is still appealing. Why? It's the aesthetics and the simplicity together that draw me to it. This has happened every time I've owned an obsolete laptop, so let's have a look at why.&lt;br /&gt;&lt;br /&gt;The biggest draw is that the laptop was a &lt;span style="font-style: italic;"&gt;great product&lt;/span&gt;. It was well built, felt great, and rarely failed. The aluminum case, full-sized keyboard keys, crisp DVD loader, rubber wrist guard edges, robust mouse pad, and of course it's elegant po'boy no wasted space design are irresistable. I also love my macbook, but all of the above stated features were lost with the intel CPU and white plastic. Fact is, I like typing on my little powerbook. Nothing has broken, and it still feels good.&lt;br /&gt;&lt;br /&gt;What's more intriguing, though, is my attraction to the simplicity that the single, slow processor forces upon you. When you use a slower machine you are forced to serialize your thinking, and to focus closer on one goal at a time. No room for ADD here, I can't configure and compile this or that while watching a youtube video. Just sit me down with a couple of 80x24 Terminals and give me emacs, make, and a python interpreter.&lt;br /&gt;&lt;br /&gt;There are two opposing methods for designing and coding a program. Faster, multi-core machines allow you to write crap code and compile and re-compile in short periods of time, for even the smallest of trivial changes (font color, anyone?). At the other end of the spectrum a developer could sit down with a paper, pencil, and eraser, and write the entire program out after completely understanding the problem. I once read an article about an older developer in a rather large project that wrote his entire module out on paper before typing it in, one char at a time. It compiled the first time and ran flawlessly for years with only one error caused by someone else's adjacent module. This is intruging.&lt;br /&gt;&lt;br /&gt;A more obvious factor involved in developing on a slow machine is that it forces you to write &lt;span style="font-style: italic;"&gt;fast&lt;/span&gt; code. Qt's painting on the ppc puts you into a bloody time warp; sometimes it's like watching paint dry. But, just like learning nordic ski technique, it's a fantastic excercise to bring out the weakest parts of your code. You can only consider your code to be tight and rebust when you've eliminated the weakest links in the chain. I am hard-pressed to ask if tighter, more robust solutions actually equate to more development time in the end. Do you think so?&lt;br /&gt;&lt;br /&gt;My first laptop was a hand-me-down toshiba with a 100MHz processor that I got from my employer in 1998. I put redhat-5.2 and windowmaker on it, and learned how to write my first C programs using a gigantic C/C++ reference. While running windows and any useful app was a crapshoot, here I had a fast windowing system and a really cool night theme. If I had my way, I would jump back to windomaker in a heartbeat. No dock apps, no weird compiz flare, just a keyboard shortcut to xterm and firefox. &lt;a href="http://lorenzod8n.wordpress.com/2008/01/27/an-evening-with-window-maker/"&gt;Here is a nostalgic blog post from another guy experiencing the same thing.&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So now I'm sitting at my desk on  a Saturday typing on my poor little powerbook, while my fat-cat macbook sits idle the the side. I've got a web browser, a text editor, and iTunes, and I've written an entire article without checking my email once in the process :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2677578498810483034?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2677578498810483034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2677578498810483034' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2677578498810483034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2677578498810483034'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/back-to-basics-getting-flow.html' title='Back To Basics, Getting the Flow'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2985862822805040996</id><published>2008-11-21T23:41:00.013-09:00</published><updated>2008-11-22T11:33:26.696-09:00</updated><title type='text'>Notes for embedding python in your C/C++ app.</title><content type='html'>As I've written about before, I've embedded python into our sampler application to create a control-rate scripting language. The python code is run with (*gasp*) real-time priority in the audio thread, and performs quite well, as long s no one does a while True: pass. There were a ton of hurdles for embedding the app into the program, but there was also &lt;span class="Apple-style-span" style="font-style: italic;"&gt;very little&lt;/span&gt; information available on the internets to help, so I thought I'd try to write some stuff down. Go Google.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size:130%;"&gt;&lt;b&gt;Basic Concepts&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are two cases that I can think of for embedding python into your application. The first one is to provide a scripting interface to your application. This means that you allow your users to write scripts to control your app, and you provide a special API for access to your data engine, or something like that. This is what I did.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The second one is if you want to actually write some of your application in python. An example would be that you would write one of the gui widgets in python, and set the widget to be a child window of your application's main window - interesting stuff. What you would have to do is write some funky wrapper code to get a window handle or class pointer from your python module as an unsigned long long or uuint and pass that to your gui tool kit. I have code to do this with Qt.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size:130%;"&gt;&lt;b&gt;Running scripts&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The first example above is the most straight forward. You include some kind of script editor and a "run" button in your app, and call PyRun_SimpleString() or some other method from the pyhton library to execute your code. If you really want to get funky you can intercept sys.stdout and print console output. This makes your app way cooler.&lt;br /&gt;&lt;br /&gt;I set my script source from utf8 like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;/* normalize the source */&lt;br /&gt;pySource = PyString_FromString((const char *) source);&lt;br /&gt;fixed_source = normalize_line_endings(pySource);&lt;br /&gt;Py_DECREF(pySource);&lt;br /&gt;if (fixed_source == NULL)&lt;br /&gt;goto set_source_error;&lt;br /&gt;&lt;br /&gt;/* compile the source into code object */&lt;br /&gt;code = Py_CompileString(PyString_AsString(fixed_source), modname, Py_file_input);&lt;br /&gt;Py_DECREF(fixed_source);&lt;br /&gt;if(code == NULL)&lt;br /&gt;goto set_source_error;&lt;br /&gt;&lt;br /&gt;setPythonCode(code);&lt;br /&gt;&lt;br /&gt;set_source_error:&lt;br /&gt;if(PyErr_Occurred())&lt;br /&gt;postException();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If I'm setting the source from a "frozen" module, I do it like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;PyObject *source = PyMarshal_ReadObjectFromString((char *) data, size);&lt;br /&gt;if(source == NULL)&lt;br /&gt;{&lt;br /&gt;PyErr_Print();&lt;br /&gt;goto set_frozen_source_exit;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;const char *c_source = PyString_AsString(source);&lt;br /&gt;m_source = c_source;&lt;br /&gt;&lt;br /&gt;PyObject *code = compile_source((const char *) pathname, source);&lt;br /&gt;if(PyErr_Occurred())&lt;br /&gt;{&lt;br /&gt;PyErr_Print();&lt;br /&gt;goto set_frozen_source_exit;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;setPythonCode(code);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;setPythonCode(code) looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;PyObject *d = NULL; // module dict&lt;br /&gt;PyObject *v = NULL; // tmp var&lt;br /&gt;&lt;br /&gt;/* initialize builtins */&lt;br /&gt;d = PyModule_GetDict(m_pyScriptModule);&lt;br /&gt;if (PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins()) != 0)&lt;br /&gt;{&lt;br /&gt;postException();&lt;br /&gt;return;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;/* Remember the filename as the __file__ attribute */&lt;br /&gt;v = ((PyCodeObject *)code)-&gt;co_filename;&lt;br /&gt;Py_INCREF(v);&lt;br /&gt;if (PyDict_SetItemString(d, "__file__", v) != 0)&lt;br /&gt;PyErr_Clear(); /* Not important enough to report */&lt;br /&gt;Py_DECREF(v);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The method that I used was to manually create an empty python module from scratch and compile the code from the editor each time the run button was clicked. This way you can intercept the compilation and module construction before it gets added to sys.modules. Scripts are grouped by instrument in our app, so I made the rule that __import__ would allow a script to import another script from the same instrument. I did this using an import hook. Maybe I'll write about that later.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size:130%;"&gt;&lt;b&gt;Embedding Code&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A really, really cool chunk of code included with the python library is the "frozen" app template. There is a python file to compile python source stored in a const char * buffer and store the byte-code in a giant char array, which you can use in your app later on. I used this to embed the standard python lib into our application, allowing it to be an entirely self-contained exe. Go check out Tools/freeze, and you can thank me later.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Part of our application code is also written in python. This means that I wrote some small wrappers and some basic functions as a python script, and added custom build steps to Visual Studio and XCode to "freeze" them into compilable C code, which is executed manually right after Py_Initialize().&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span style="font-size:130%;"&gt;&lt;b&gt;Static Data&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Python relies heavily on static variables. My experience is that it's a bad idea to try to call Py_Initialize() and Py_Finalize() more than once. Use a singleton class with an instance() method to do all your python initialization, and ensure it is only done once. Use the atexit() function to make sure that your lib is broken down when the app exits, even if you are writing some kind of dll or plugin. This method will work for both windows and mac, and save you tons of headache.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size:130%;"&gt;&lt;b&gt;Statically linked extension modules&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Once you link the python standard lib into your exe, you won't be able to stop. You'll write a couple of modules and want to link those in, too. You'll want to include PyQt so you can write gui code for your app as well. I wrote the API for our scripting engine using sip to generate the code for the python module, and that code is statically linked as well.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This all seems pretty easy, but you need to add --disable-shared to your python configure flags, and you need to do some special things to get the interpreter to initialize the modules correctly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First, explicitly declare the init functions and a 'struct _inittab' for the modules you statically linked:&lt;br /&gt;&lt;pre&gt;extern "C"&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;void initsip();&lt;br /&gt;void initmymod();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;static struct _inittab builtin_modules[] = {&lt;br /&gt;{ "sip", initsip },&lt;br /&gt;{ "mymod", initmymod },&lt;br /&gt;{ NULL, NULL }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Then, call the import function explicitly followed by with _PyImport_FixupExtension() to register it properly. This isn't documented anywhere, and I got the tip from some nice guy in #python-dev.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-size:130%;"&gt;&lt;b&gt;Thread safety&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At first I compiled python with threads, like any well-minded person would do. But then I got sick of having to manage all of the locks and thread states myself, and eventually compiled python without threads and started using my own static mutex. The performance is the same, but our thread code is gone and we don't have any more problems with excentric thread inits when host apps run our junk as a plugin.&lt;br /&gt;&lt;br /&gt;But, If you use blocking calls like read(), write(), or open(), or will use C extension modules, then using your own lock is probably a bad idea. Those calls and extensions will probably release the GIL when possible allowing other threads to get a little CPU, so you'll take a performance hit if you disable that. We never make calls outside our app, so using our own lock is fine.&lt;br /&gt;&lt;br /&gt;One bit of advice that I would give to coders with strict performance requirements is to separate your scripting engine from your main application code by way of some kind of abstract interface. We run our python code from multiple audio threads, so contention for the GIL causes CPU spikes at low latencies - as would any lock held in an audio thread, which is why they say NEVER use locks in an audio thread.&lt;br /&gt;&lt;br /&gt;Anyway, the only feasible solution to this is to migrate all of our calls to the python lib into another process. Defining a good, clean abstract interface to your scripting engine will make this a no-brainer when it comes time to implement an RPC layer.&lt;br /&gt;&lt;br /&gt;The unfeasible solution to this would be to patch the python interpreter to allow for separate interpreters to live in separate threads. But we don't want to get into THAT one now do we? *wink*. Well, if you really have a taste for the lions' den, then here you go:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mail.python.org/pipermail/python-list/2008-October/512902.html"&gt;http://mail.python.org/pipermail/python-list/2008-October/512902.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Notes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If anyone wants more information, I'd be more than happy to provide code examples and further explanation. This problem is a fun one if you know what you are doing!&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2985862822805040996?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2985862822805040996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2985862822805040996' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2985862822805040996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2985862822805040996'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/notes-for-embedding-python-in-your-cc.html' title='Notes for embedding python in your C/C++ app.'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8351513914336345942</id><published>2008-11-21T23:25:00.005-09:00</published><updated>2008-11-21T23:41:05.313-09:00</updated><title type='text'>Piano Overtones</title><content type='html'>I finally got a chance to a look into some of the code that affects the personality of one of our instruments. One of our script writers wrote a script to add overtones to a piano, which in our case this means a Steinway, a Bosendorfer, a Bechstein, and a Yamaha. Overtones are sounds produced by one string resonating another. The most commonly heard overtones are with strings of the same note an octave or two apart, but they can occur on other strings as well. The overtones that are triggered depend on which strings have the damper down, if the note is sustained, and how load the string was played. In other words, it's incredibly complicated.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The script needed enough cleaning up that I had to learn about the rules for piano overtones and for my poor little square brain into a round sound hole. I figured that even if I didn't get a chance to finish the script, I would at least get some better ideas for the scripting engine itself, and I'd learn something about pianos.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I can't wait to hear this script in action, because it will take an amazingly crisp piano and make it even more realstic, and the effect will be written in python using my embedded scripting engine. Very nice.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Our piano product is here:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.soundsonline.com/EastWest-Quantum-Leap-Pianos-pr-EW-171.html"&gt;http://www.soundsonline.com/EastWest-Quantum-Leap-Pianos-pr-EW-171.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.soundsonline.com/static/screenshots/qlp.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 450px; height: 350px;" src="http://www.soundsonline.com/static/screenshots/qlp.jpg" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8351513914336345942?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8351513914336345942/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8351513914336345942' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8351513914336345942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8351513914336345942'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/piano-overtones.html' title='Piano Overtones'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-7982285060437382224</id><published>2008-11-13T00:56:00.007-09:00</published><updated>2008-11-13T01:21:40.628-09:00</updated><title type='text'>Style Wars</title><content type='html'>&lt;div style="text-align: center; font-weight: bold;"&gt;The War&lt;/div&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;So I wrote this wicked scripting engine for our top-end sampler engine, but since I'm the main GUI gui as well (call me mister high-level), I've been to busy to write any scripts or oversee any of our script writers' work. This is important because the script writers are used to writing scripts for Kontakt 2, which has a horrible syntax and promotes some pretty ugly style. &lt;/div&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml"&gt;Consider Exhibit A:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="center"&gt;&lt;img src="http://lh4.ggpht.com/_-kPtlLn0YiA/SRv6SlEKO8I/AAAAAAAAAU8/Ic-t5-BL30w/%5BUNSET%5D.jpg?imgmax=800" alt="" /&gt;&lt;br /&gt;&lt;div align="left"&gt;&lt;br /&gt;OK, OK, so the code that you have to write to get anything done in Kontakt is pretty clunky. That's not to mention the fact that the editor is not resizable and the scrollbar is a total pain to use with the enormous scripts that ship with the product. So we hired these guys to write python scripts for us. The scripts that these guys are doing are &lt;i&gt;very&lt;/i&gt; cool in my opinion; they are writing realisitic note repetition, legato, portamento, overtones, to name a few that I'm actually told about. Also, as matter of fact I think maintaining this scripting engine and accompanying editing facilities is about the coolest thing I've seen.&lt;br /&gt;&lt;br /&gt;So pretty sick, huh? Well, it's cool until you go read &lt;a target="_blank" href="http://www.python.org/doc/essays/styleguide.html"&gt;The Python Style Guide&lt;/a&gt; then try to comprehend our scripts. Having my hands tied with C++ bugs, I haven't had the opportunity to write any example scripts to show everyone how it's done. The scripts are written like one huge C function, with tons of global declarations everywhere and incorrect use of parenthesis in conditions, poor variable names, and comments out the wazzu.&lt;br /&gt;&lt;br /&gt;I guess the only way out of this is for me to re-write them in my spare time to show just how beautiful they might be, and how read: &lt;b&gt;**RAD**&lt;/b&gt; this scripting engine could be. I need to re-integrate sys.path into my import hook so we can write some utility modules and get some friggin' re-usability around here. Being the only python guy around, I guess the success of the engine is up to me, and I'd better jump in there in my spare time for the sake of their creativity and my own sanity:&lt;/div&gt;&lt;div align="left"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div align="left"&gt;Consider Exhibit B:&lt;br /&gt;&lt;br /&gt;&lt;div align="center"&gt;&lt;img src="http://lh3.ggpht.com/_-kPtlLn0YiA/SRv6UNPrkNI/AAAAAAAAAVA/T-eKmNejq1k/%5BUNSET%5D.jpg?imgmax=800" alt="" /&gt;&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;The Style&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;So thinking back to the days when I was writing python 16 hours day, I remember that the code style was everything, and that it worked like a picture. Well, actually more like a sculpture, because it would change face during the development phase and would end up more or less in an unchanging state, like a picture. Modules become between 100 and 300 lines long, each has are one or two classes, the names are short and small, blocks are scimmable and there is no second-guessing about the structure of the object. This is flowing hierarchy at it's best - governments only which their bureaucracies could run this hot.&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;The difference is that you can step back and look at your program and get an immediate sense of it's character with a single glance, which is nothing that you can do with these scripts, other scripts, or any of our C++ code. Remember how your grandma told you that the back of the quilt sheets should be as nice as the front? Same thing here.&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;My only hope is that I can get my hands dirty prodding the scripting engine a bit by re-writing these scripts correctly and discovering the pieces we really need. These include:&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;- Re-add sys.path to __import__ for better file system support.&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;- Include some utility modules as examples for re-usability.&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;- Allow using emacs as an editor (part of above FS support).&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;- Refine the editor by...ehem...using it.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;" align="center"&gt;Consider Exhibit C:&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;div style="text-align: left;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-kPtlLn0YiA/SRv_Mm5PD_I/AAAAAAAAAVU/FOA4-D9i37o/s1600-h/emacs_scripting.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 291px;" src="http://3.bp.blogspot.com/_-kPtlLn0YiA/SRv_Mm5PD_I/AAAAAAAAAVU/FOA4-D9i37o/s400/emacs_scripting.png" alt="" id="BLOGGER_PHOTO_ID_5268084781204049906" border="0" /&gt;&lt;/a&gt;Code, style, editor. Nice.&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-7982285060437382224?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/7982285060437382224/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=7982285060437382224' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7982285060437382224'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7982285060437382224'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/style-wars.html' title='Style Wars'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_-kPtlLn0YiA/SRv6SlEKO8I/AAAAAAAAAU8/Ic-t5-BL30w/s72-c/%5BUNSET%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-934517554290436050</id><published>2008-11-10T21:24:00.003-09:00</published><updated>2008-11-10T22:33:53.812-09:00</updated><title type='text'>Flow</title><content type='html'>I've been reading this book by Mihaly Csikszentmihalyi called "The Evolving Self", which has a really good analysis on how and why people become involved in the activities they do. Mihaly uses a term called "Flow" to describe an ideal state where skills and challenge are in balance and the participant is lost in his or her work, and how achieving this state affects the quality of practicing, training, playing, and working.&lt;br /&gt;&lt;br /&gt;From the book:&lt;br /&gt;&lt;br /&gt;"All the evidence agrees hat when people in flow act at the peak of their capacity, it both improves subjective well-being and has the potential for socially positive consequences. In each case, flow seems to the be the engine for evolution propelling us to higher levels of complexity. But what happens when people aren't able to operate at full capacity, when their opportunities are either too daunting for them to experience flow?"&lt;br /&gt;&lt;br /&gt;I find this stuff intriguing and totally applicable to training and racing. The author performed studies on productivity relating to how often the participants experienced "flow," and found that the more interested the participants were in the work, the better their product became. This is a "less is more" perspective, and favors quality work over higher quantities of work.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/gp/reader/0060921927/ref=sib_dp_pt#reader-link"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/71KRF4WWDKL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU01_.gif" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Flow_(psychology)"&gt;Wikipedia: Flow&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Evolving-Self-Mihaly-Csikszentmihalyi/dp/0060921927"&gt;Amazon: The Evolving Self&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Mihaly_Csikszentmihalyi"&gt;Wikipedia: Mihaly Csikszentmihalyi&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;What does this matter to you? Well, if you are an artist, computer programmer, rock climber, or nordic ski racer, then you are involved in a process where you enjoy exercising your skills to achieve something. The book quantifies skills, difficulty, and gain in a way that helps us understand why we spend so much time doing the things we enjoy, and falls in line with an article I wrote about owning the process of training. What a great read.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;Lesson Learned:&lt;/i&gt; Fun over boring, quality over quantity.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-934517554290436050?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/934517554290436050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=934517554290436050' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/934517554290436050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/934517554290436050'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/flow.html' title='Flow'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1501513721293557684</id><published>2008-11-09T15:19:00.003-09:00</published><updated>2008-11-09T15:25:00.392-09:00</updated><title type='text'>Musical Supercomputing</title><content type='html'>Robert Henke has &lt;a href="http://www.monolake.de/interviews/supercomputing.html"&gt;an essay on his site&lt;/a&gt; about how live musical performances have changed now that we've got loads of recording and playback hardware available to bedroom producers. It's a very interesting read.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From the article:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;"""&lt;/div&gt;&lt;div&gt;This fragmentary text is the attempt to sum up some thoughts of mine about performing electronic music live. Since starting to put chapters online I got numerous very interesting comments and links to publications and i'd like to thank you all for the feedback! There is much more I would want to add but most likely I will not find the time and the text will stay fragmentary.&lt;br /&gt;"""&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1501513721293557684?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1501513721293557684/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1501513721293557684' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1501513721293557684'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1501513721293557684'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/musical-supercomputing.html' title='Musical Supercomputing'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6184715549677535365</id><published>2008-11-07T00:27:00.002-09:00</published><updated>2008-11-07T00:38:39.436-09:00</updated><title type='text'>I want I want</title><content type='html'>So I started a little project a while ago called the pksampler that was an attempt to build something that would allow me to improvise and play my techno tracks like I always thought the Djs did back when I was 17. Then Ableton Live came along and blew everyone's socks off with it's incredible workflow and reliability. I've still got a long way to go before I wrap my head around all the possibilities with Live, but one thing's for sure - there's still something that I'm missing.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I want to sit there and get involved in my tracks as they play. I don't want to just play canned loops and transitions, but I want get more involved. I want to stand over my awesome &lt;a href="http://www.xone.co.uk/3d/"&gt;Xone:3D&lt;/a&gt; and play the bloody song for a crowd of people. Do I need to just get better at my production? Do I need to learn to play the guitar, bass, and drums better? Do I need to learn more about midi and the possibilities of digital components? Do my tracks just need to sound better? I don't know. I've been chasing this forever. If I could figure this out, I could quit writing software for a living and actually become a ski bum for the rest of my life.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;People go to a rave and they see this guy playing all this awesome music and they think he's totally the bomb because they like what they hear. I want to make that real and build or acquire a music platform so I can spend some time getting good at it so I can write some tracks and perform them live. How How How How How?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I guess the pksampler still has some purpose after all.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6184715549677535365?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6184715549677535365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6184715549677535365' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6184715549677535365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6184715549677535365'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/11/i-want-i-want.html' title='I want I want'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2612927942535770363</id><published>2008-09-22T17:17:00.005-08:00</published><updated>2008-09-23T09:34:54.452-08:00</updated><title type='text'>Here you go</title><content type='html'>&lt;div&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_-kPtlLn0YiA/SNhENQEPECI/AAAAAAAAAQQ/PCHu-21ENAE/s1600-h/Photo+7.jpg"&gt;&lt;img style="cursor: pointer;" src="http://3.bp.blogspot.com/_-kPtlLn0YiA/SNhENQEPECI/AAAAAAAAAQQ/PCHu-21ENAE/s320/Photo+7.jpg" alt="" id="BLOGGER_PHOTO_ID_5249020360142032930" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Instructions: Take a picture of yourself right now. Don't change your clothes, don't fix your hair - just take a picture. Post that picture with NO editing. Post these instructions with the picture.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2612927942535770363?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2612927942535770363/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2612927942535770363' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2612927942535770363'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2612927942535770363'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/09/here-you-go.html' title='Here you go'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_-kPtlLn0YiA/SNhENQEPECI/AAAAAAAAAQQ/PCHu-21ENAE/s72-c/Photo+7.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-8994717934320733067</id><published>2008-09-18T16:09:00.004-08:00</published><updated>2008-09-18T17:50:11.977-08:00</updated><title type='text'>Computers, Music, Transitions</title><content type='html'>Both computers and electronic music are in the middle of a major transition, one that is pretty difficult to see while we are stuck in our coding and composing. Things move so fast these days that it's easy to forget how new these worlds are.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Computers&lt;/span&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The other day I was trying to explain to my Dad why he has problems communicating with a programmer he's hired to build some cost management stuff for Access. He constantly tries to get the lucky programmer to explain how the company will be fine without him, and he never understands the programmer's answers. My solution is to hire someone to work with the programmer that can asses the flexibility of the data storage with respect to well-accepted standards (xml, rel-db, etc...), and have a (very) quick look at the architecture of the application To make sure he isn't writing spaghetti. Any decent coder should be able to do this in an hour or two, but why does my poor Dad not even know how to approach the problem?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It is my belief that the industry is just too young, and the benefits of deploying code now are obviously HUGE (games, iPhones, VCR's, toasters, life). Software just has not matured to the point that it makes as much sense to the consumer public as an appliance like a TV or a car does, so that when it breaks you just call the guy that comes and fixes it for an hour or two at his flat $60/h rate. Shit, we're even used to the idea of that costing 1.5 times as much as you expected, which is some confort. Software developers are more like R&amp;amp;D experts, since every couple of years there is a high likely hood that they will be dealing with a major architectural change - where their work *environment* has changed enough that they are not just sitting down and using their skills, but they are also adapting their old skills to match. Sorry mister C/Perl/MyLang coder, but we're still just going to pay you for sitting down and using your skills. I want an estimate by Monday.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;The goal of our project is to build a virtual instrument, but we spend all of our time on basic stuff like figuring out how to move controls and show messages, just like every other mundane application out there. The following is my current bug list:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;-artf21115 : PLAY does not replace current instrument when changes not saved&lt;br /&gt;-artf21125 : Replace Dialog box Not Present&lt;br /&gt;-artf19771 : PLAY displays wrong amount of available RAM.. dialogue box no longer appears&lt;br /&gt;-Strange error box (!) when validating AU... same box comes up when loading saved Cubase project to.  picture attached to email&lt;br /&gt;-Artifact artf17139 : No sound when "unfreezing" Play virtual instruments in Sonar 7 Producer... now results in "FATAL ERROR" when unfreezing&lt;br /&gt;-Artifact artf15670 : No Audio Output in Sonar with Different Languages.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;All of these bugs are regressions, which means they were working at one time, but are not working now. Every one of our regressions are caused by a poor name choice or incomplete design abstraction that lead to errors in our code caused by new features. This happens because we never had enough time to do it right in the first place. Sound familiar? That's because being crunched under a tight deadline is nothing new, no matter what industry you are in. I think that the difference here is that the most basic design and development methodologies have not matured to a point where solutions can be read in a manual and reproduced under the deadline. We should be able to sit down with the task of adding a dialog box, make the change, and never look back.&lt;br /&gt;&lt;br /&gt;I hate to always wrap this stuff into a "python is the answer" thing and I won't do it this time, because while python helps a lot, it (actually!) isn't the answer. Somewhere down the road this stuff will get better, even with C++ and other useless languages like Java. All the good toolkits make it easier, but ONE toolkit would make it great. If you need some windows and some buttons, there should only be one place to turn. If you need some sound, there should be ONE toolkit for that. Dig?&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Techno&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;Along the same lines, music is going through the beginning of a similar young stage. While an avaid trance and progressive fan, I don't believe that we will be listening to this stuff forever. Think of modern electro as part of a transition period where we are developing new tools and learning how to use them effectively for the &lt;span style="font-style: italic;"&gt;next&lt;/span&gt; phase, whatever that is. Music is a way to communicate emotions, and express ideas that can't be explained using words. A good musician is an artist who has also mastered the technical nature of a musical instrument, so when he or she wants to get dirty and do some expressing, they can devote their energy to that instead of how to get the instrument to work.&lt;br /&gt;&lt;br /&gt;A lot of new songs appeal to listeners because they've got some killer sounds, and usually are produced so they get a lot of punch out of the speakers. Fact is that this appeal won't last very long, and the songs that really last are the ones that are great songs, not great sounds. Go listen to *anything* techno from the early nineties, and you'll see what I mean. Psychotrance is only 15 years old and I can't stand to listen to it any more!&lt;br /&gt;&lt;br /&gt;Where is this going? Who knows, but there are a few things that have never happened before. After PC's got fast anough for pro audio, we have started going through an incomprehensible amount of new music. I listen to internet radio all day at work and never hear the same track twice. We are also nailing down the hardware interfaces and software workflow. Ableton live has contributed more to this than anything else, IMHO. Further, the amount of publically available audio code out there is astonishing. We are seeing loads of people playing with new ideas like algorithmic composition that will lay the foundation for the macro-concepts to come.&lt;br /&gt;&lt;br /&gt;The reason that I think things will change is that music has temporarily lost its expression. This is a big deal because music *is* expression. If you want communicate to your listeners that your brain works like a computer and is recorded, automated, and predictable, then be my guest.&lt;br /&gt;&lt;br /&gt;For example, when I sit down to put together a concept for a trance track, I slap together a 4x4 kick drum, a side-chaining compressor, and some sort of chord or bass. How much expression is involved in that? Almost none. The chord progression is done with a midi keyboard, and is quite effective for a traditional harmony, but that's about it. Ideally, the entire peice would more closely mirror what was happening in my heart and body when I first wanted to sit down and start composing. While some of you may disagree, I don't think that an absurdly robotic and inane representation of a rhytmic emotion is happening in my body. Confused? I know, I know, but a human heart beat is more acurately reproduced as a human-powered drum.&lt;br /&gt;&lt;br /&gt;As we build and get more in touch with our tools the music will come back around to the traditional expressive stuff our parents grew up with. Maybe our brains will actually become absurd and robotic to match the music, who knows. What I do believe is that all this robotic music won't be around forever, and it will be replaced by live music sporting incredible human and technology interaction. Remember the chamber quartet or the drum circle? Good story tellers and bad story tellers? Free interpretation? Music is expression and nothing else, so I don't think we are supposed to go and get rid of all the boring recorded and  automatically sequenced music. I think it will disappear on it's own.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Togetherness&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Anyway, considering I write software and produce electronic music, this is important stuff. In some ways I think we are walking in the dark, assuming that current software and current techno are the amazing finalizations of our incredible accomplishments. The truth is it isn't the end - we aren't there yet - it's the start of something bigger.&lt;br /&gt;&lt;br /&gt;I have zero insight for how music will evolve since the last five years have given us so much change, but software is another story. This industry is young, and we don't know what we are doing yet. Can you ensure that your validation tool will function with 100% accuracy? When the productivity expectations of the customers and the producers are equal, we've made it. Until then, "Yeah, sure, we can make that deadline."&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-8994717934320733067?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/8994717934320733067/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=8994717934320733067' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8994717934320733067'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/8994717934320733067'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/09/computers-music-transitions.html' title='Computers, Music, Transitions'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-9091174401084814786</id><published>2008-09-16T23:27:00.003-08:00</published><updated>2008-09-16T23:38:25.189-08:00</updated><title type='text'>Nostalgiske Tenker</title><content type='html'>I miss my powerbook g4 12", because it's the best computer I've ever owned. Finally I had a compact laptop with more than enough screen, a full sized keyboard that felt really good, and unix running under a beautifully simple interface. Geek talk? Yes.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The only problem with the powerbook is that it is slow. Bit-blips ooze like cold honey out of their frame buffers, and gcc burns through parsely like a lost kitty. Poor gcc, poor PyQt. My macbook currently does everything I need it to. Sure, concurrent disks would be useful but it runs ableton live and is very good for developing C++ apps. Fix the bloody macbook, apple! 12"! 12"!!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The other day I downloaded the Doomsday engine and loaded (my?) DOOM2.WAD (note caps). I'm re-united with some seriously old, and seriously fun gaming. I'll never forget the first time I got locked in playing a Doom 1 deathmatch against John Kew and Steve Houston at John's place on Arctic. I quickly built myself a K5 90MHz with any parts I could scrounge up - and I mean *scrounge*. We spent more time getting our machines to work than playing games, but I was skipping track practice the first time I tried it. 12 years later I finally got control of the addiction...or have I?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-9091174401084814786?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/9091174401084814786/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=9091174401084814786' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9091174401084814786'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9091174401084814786'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/09/nostalgiske-tenker.html' title='Nostalgiske Tenker'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2620992724992209760</id><published>2008-09-04T08:29:00.014-08:00</published><updated>2008-09-08T17:54:14.194-08:00</updated><title type='text'>Lessons Learned</title><content type='html'>&lt;div&gt;Having moved to a C++ project with strict performance requirements, we've spent a ton of time on build config and memory related issues. Not only is the majority of our effort not spent on writing features, but this "wasted" time also happens to be the most agonizing. Being a hopeless idealist and having nothing but subjective and difficult to argue cases to present to my boss, I thought I'd just try to put it all on paper to remember for the next go around.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Developing a modern audio plugin with good platform support provides plenty of code management challenges. The plugin formats we support are AU/VST/RTAS, the platforms are Windows, Mac/ppc/intel, and all 32/64 bit. No one has ever bothered to count the total, but I do know that it amounts to a big pain. We use XCode 2.5 and Visual Studio 2005, and have incorporated qmake to use qt for the gui into both. Our main targets are a standalone app or a plugin, which in turn loads a separate plugin for each of our products that you've purchased. This means you have to maintain several build configurations over several platforms, and they all behave differently.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Lesson 1: Separate features and config&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Clearly define your problem domain, and try to separate your build and deployment environment from the development environment as much as possible. For example, our problem domain is to implement a high-performance sample playback engine and accompanying UI, so adding some new graphical classes and menus should not affect the build config, and visa-versa. When you write in C/C++, you will typically define config macros on the command line, add and remove files to be compiled, etc, and all of this stuff will change on each platform. For example, when I add a QWidget subclass, I have to add the files to XCode, add an entry in the qmake project to generate the meta source, add the meta source to the XCode, and do it all over again for Visual Studio.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Conflicting headers has also caused us plenty of problems. Our primary third-party libraries are juce, Qt, and python. Python and Qt conflict over the "check" symbol, and juce and Qt conflict over the T macro and others. The juce library is nice enough to include "using namespace juce" in it's headers, so we get conflicts with just about everything, including system frameworks like Carbon. To solve this problem I had to find the correct order of #include and #undef statements to get all the libraries to play nice together. Don't even bring up windows.h. Finding a solid scheme for including the fundamentals is very important, and you should never have to worry about it in your feature code.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In a nutshell, You should write features with 0% brain power spent on how your features will affect the build config.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Lesson 2: Unify your build environment&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Managing your build configuration is a pain in the butt. qmake does a really good job of flattening the tool chain, but as long as you are using more than one compiler you are going to have to have conditional variables built into the build config. This is almost always the case when you support more than one platform.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you can manage to flatten the config to a point where you do not need to separate changes for your different platforms, you've taken a huge step. Adding a new library to your code will cause a change to the config, so the cleaner the libraries you choose, the better. Qt, sip, and PyQt are examples of libraries that add little to no compilation and linkage config overhead to a project because their lack of dependencies allow them to be relatively self-contained. The sip code actually compiles with no special flags.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Lesson 3: Write modular code&lt;/b&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I know all of this stuff sounds elementary, but it's all very important. The more black boxes you write, the less they will change. Our project consists of a few key components; the audio engine, the gui, the product plugins, and the target exe/plugin (of which there are many). Trying to meet our stupidly tight initial deadlines, our project manager originally had everything compiled into a single target for each exe/plugin. Granted, this would have fixed the symbol visibility problem that we are having right now, but it added significant compile time and the code behaved differently everywhere.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It doesn't really matter how much intertwangling there is within the bounds of each component (your boss is going to assign those bugs to you anyway and you'll just go fix them), but it does matter that your major components are well separated. We aaaalmooooost nailed it in our project by creating engine, gui, and product libraries, but we unnecessarily mixed the headers and instantiated objects from each in the target exe's. A better approach is to provide a single header for each library that includes only pure virtual classes and some global factory functions. These headers should not define any types, and should not include each other.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;I Tilleg&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I like using our project as an example for project management topics because it has some relatively tough requirements. The audio engine must be written in C++ because performance is top priority, and the gui code could be written in python. Given that the engine is as small as possible and 100% independent of the other components, we could have written a small layer to move all of the application code into python. That way we could have added and tested new features with little worry to causing crashes and compilation/linking related issues.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As a result, the two most interesting problems that I would like to solve are:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;1) A 100% self contained AU/VST/RTAS wrapper with PyQt support.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For the plugin wrapper, a flexible engine =&gt; gui interface would be key for component communication, but also the build config for the compiled elements would need to require as few compiler options as necessary to make it easy to be compiled as a local target as opposed to linked as a library. This way, the developers would have total access to the code once it was included in their project and would not have to deal with any overhead related to integrating it into their projects. Including updates to said code could be tricky, but I'm convinced that the changes could be made small enough to remain manageable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-weight: bold;"&gt;2) A concurrent python interpreter.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A truely concurrent python interpreter would allow the language to be used in a realtime dsp engine while simultaneously used for the user interface. This has been brought up before and is a point of contention for the python project since the GIL is &lt;span style="font-style: italic;"&gt;really really &lt;/span&gt;tough to remove. I suppose if I was able to provide a patch with a build option to at least provide a concurrently capable interpreter the language could be used in very specialized multithreaded cases. This is a pretty specialized requirement though, so maybe that's good enough? We just wanted the language itself, and I could have easily patched the sip and PyQt extensions to accommodate the change.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2620992724992209760?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2620992724992209760/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2620992724992209760' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2620992724992209760'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2620992724992209760'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/09/lessons-learned.html' title='Lessons Learned'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1721567366164066040</id><published>2008-08-28T16:08:00.002-08:00</published><updated>2008-08-28T16:19:40.818-08:00</updated><title type='text'>Coding with good energy</title><content type='html'>I just read a &lt;a href="http://feeds.feedburner.com/%7Er/Jessenollercom/%7E3/377121149/"&gt;post on planet.python.org &lt;/a&gt;about writing entertaining comments and docs, and I found the topic quite interesting. Above all I like my code to work, but I also like to code when I've generally got a good level of energy. In this respect I consider writing code an art, and I also think that the more sleep you get, the better mood you are in, the more accurate your code is going to be. I mean, when my tasks get boring I tend to get lazier and write crappier code.&lt;br /&gt;&lt;br /&gt;This means that I really, really, like to add personality to my code. It should basically be as self-documenting as possible, so slapping in an occasional&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def cludgy(*args):&lt;br /&gt;  """ I have no idea why I'm writing this, and if x&lt;br /&gt;      ever equals 0, you should  probably double check mine.yoursForNow()&lt;br /&gt;  """&lt;br /&gt;  x, y, z = args&lt;br /&gt;  return y&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The more interesting, the better. In my opinion, better energy == better code == better art. I would say that with C/C++ you'll end up writing more comments, but with python you have more opportunity to spice up your code since you are writing more faster.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1721567366164066040?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1721567366164066040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1721567366164066040' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1721567366164066040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1721567366164066040'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/08/coding-with-good-energy.html' title='Coding with good energy'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-3290977713253686820</id><published>2008-07-23T14:55:00.008-08:00</published><updated>2008-08-07T15:46:23.996-08:00</updated><title type='text'>C++ and Python project config</title><content type='html'>Before I started writing commercial C++ code a couple of years ago, I had just begun to reach a wonderful state of Zen with python. I had developed good personal balance of prototyping, code organization, and debugging techniques that I still haven't seen the likes of with my C++ project. If anything, the biggest advantage that my python projects had over my C++ projects is impeccable project config. With no compilation and the guarantee that the code would run the same accross platforms, the fight was over before I even started coding.&lt;br /&gt;&lt;br /&gt;These days I spend 50% of my time either writing code or managing a Visual Studio or XCode build system to fit the needs of the compiled language's environment. Third party vendors don't accurately support audio plugin standards, their objects are compiled with a different runtime than ours, and their headers conflict with ours and cause others to bail completely (windows.h, anybody?). Strong typing causes twice the code bloat and twice the up-front design effort that the interpreted language took. The code is unreadable; the macros clutter up the logic, the indentation is all over the place, and there's just plain too much of it. Worst of all, our repository is totally fragile, which seriously stresses out my boss.&lt;br /&gt;&lt;br /&gt;When you code in C you get speed and easy debugging, which is important for projects like ours, which consists of a separated gui and dsp engine that is instantiated as an audio plugin with popular music sequencing hosts like Ableton Live, Pro Tools, Logic, and more. These days we are still writing for scalability and performance, so the engine has to be written in C. We debug our gui code and step into the engine on a regular basis, so writing the gui code (&gt; 50%) in python and trying to debug the engine would be very difficult. &lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Theoretically the gui code would have been so easy to write in python that we wouldn't have needed to debug it, and could have just debugged the engine using C++ breakpoints in XCode and Visual Studio as we do now, but I wouldn't know without trying it. One thing is for sure, coding with a clear conscience would have required a solid set of tests to work out all the bugs we've run into using Qt as a graphical toolkit from within a native application. With the tremendous overhead of writing unit tests for this stuff, we would never have met our initial project deadline, and I would never have had the opportunity to look back and grumble about our choice of language.&lt;div&gt;&lt;div&gt;&lt;br /&gt;Maybe it's possible to get around these problems with better plugin standards? Or maybe having a really really good python-based plugin dev platform to work with would help.&lt;br /&gt;&lt;br /&gt;Anyway, back to the topic. I originally wanted to write about the stylistic differences that separate python and C/C++ projects. Here's what I've found:&lt;br /&gt;&lt;br /&gt;Python induces highly modularized code that is still readable, while in C it's much easier to read code that is written in larger blocks. Remember that big, long function that you wrote in your first college class?&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;When I code in C++ I end up spending most of the time coming up with solutions that work for the syntax of the language, as opposed to using that time and energy to focus on the functionality of that code. I eventually stopped using a debugger with python because I was able to produce pieces of code that worked well from the start, or could be quickly fixed using print statements and some sort of unit test using an "if __name__ == '__main__':" block. With C++ I ended up writing verbose code that is easily debuggable, for example always using temporary values of built-in types to expose the state of the stack.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The biggest difference, though, is that I got very comfortable with being a style nazi when reading and writing python code. The difference is that it just doesn't matter what the code looks like in C++ as long as it runs. We have three primary developers in our project that all use whitespace differently, name our variables and methods with different conventions, and it's pointless and also unnecessary to try to change them. You just jump into the C code and fix the problem, leave the crazy indentation from your tabified copy and paste, then just compile it and make it work, and work fast.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I do miss the unified indentation, simple syntax, and no crashes, compiler flags, or linkage problems have cost us a lot of man hours, not to mention stress for my project manager. Most of all, I miss just sitting down and solving problems 100% of the time.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-3290977713253686820?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/3290977713253686820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=3290977713253686820' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3290977713253686820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3290977713253686820'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/07/c-and-python-project-config.html' title='C++ and Python project config'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-3677099853266828780</id><published>2008-07-16T09:39:00.000-08:00</published><updated>2008-07-16T12:21:33.434-08:00</updated><title type='text'>Multiple RT threads and the GIL</title><content type='html'>&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: 18px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: 18px; "&gt;The Problem&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Same old topic, new person. The GIL sucks. It makes programming easy, but it makes true parallel processing impossible. Audio sequencing plugin hosts use a different thread for each track, allowing their DSP to scale with the number of available processors. While python has performed beautifully for doing control-rate midi processing in our commercial plugin (http://www.soundsonline.com/) running in RT threads, the presence of the GIL causes brief CPU spikes when one or more threads take to much time to run their scripts. The lack of performance in a single thread is not a problem since the audio event will safely occur later, it's the fact that that thread slags all the other threads that are running perfectly fine that sucks.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Python has otherwise proven to be a &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;fantastic&lt;/span&gt; platform for our scripting engine, and it would even more &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;fantasticer&lt;/span&gt; if the GIL didn't get in the way. It would be a shame for such a great scripting engine to be blocked by such a small hurdle (although still a major design decision). A per-interpreter lock would solve the problem for us since each track is always independent from another and so never share objects.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One solution is to try and patch the python source to actually be able to &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;use&lt;/span&gt; completely separate interpreters. This means that all objects would live on one interpreter, and their accompanying functions would need to modified to take an interpreter as an argument. Loading extension modules would have to be disabled since they generally use static data. As of right now I don't know how hard this would be but if anything I'd get a good code read out of it. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Another idea I was playing with was to somehow find a way to use the fact that dlls use their own address spaces to maintain separate images of the python lib and therefore separate GILs. If there was a way to copy a dll and store separate instances of it, this would be possible. I wouldn't mind the extra footprint on the heap if I could get rid of those CPU spikes.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;The correctly pythonic answer to this problem is to use process migration. This would imply creating a daemon process for every instance of our engine. I don't know if this is a very nice thing to do to a plugin host, but it would fix the problem if we could get around all the shared memory and IPC overhead. But ummm, I think I'll read the python code for now.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;The Future&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At Present, making python available to the audio world is what interests me most. It would be great if we could use the language for control-rate audio scripting, graphical interfaces, etc. The biggest problem I've had with the current implementation is when using it with plugin instances, and I can see problems popping up whenever complex intra-process use is involved.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That's two major python no-no's: single-process scalability, and use in high-priority threads. I have the belief, though, that while processors have already become fast enough to get over the old "python is bad for real time use" performance myth, and we are going to see more cores, which makes true mutli-threading a very very good thing to have.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-3677099853266828780?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/3677099853266828780/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=3677099853266828780' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3677099853266828780'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/3677099853266828780'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/07/multiple-rt-threads-and-gil.html' title='Multiple RT threads and the GIL'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2284994471826733519</id><published>2008-07-16T08:55:00.000-08:00</published><updated>2008-07-17T15:17:27.692-08:00</updated><title type='text'>forste melding</title><content type='html'>Hello! I'm back after over a year. After becoming more involved in my C++ work for EastWest, I didn't have the time to focus on my python code. Now after implementing a python-based scripting engine for &lt;a href="http://www.soundsonline.com/"&gt;Play&lt;/a&gt;, I've slowly regained a grip on my personal artistic interests and have startup up my blog again.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I don't anticipate getting the traffic on this blog that I used to when I was more active in the python/pyqt/supercollider world, but it would be really nice to have a spot to ramble about music and code. I sure hope they have a good code highlighter...yay internet! I manually imported all of my old pyblosxom entries with the correct dates as well. Happy following.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2284994471826733519?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2284994471826733519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2284994471826733519' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2284994471826733519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2284994471826733519'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/07/forste-melding.html' title='forste melding'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-2798603156372632506</id><published>2007-05-08T16:18:00.000-08:00</published><updated>2008-07-16T10:54:10.901-08:00</updated><title type='text'>Configuration Management</title><content type='html'>Configuration Management is 90% of any software project. &lt;br /&gt;&lt;br /&gt;If you can make it 10% then you've done 90% of your work. Basically, the lesson of the day is do everything you can to code in python.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-2798603156372632506?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/2798603156372632506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=2798603156372632506' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2798603156372632506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/2798603156372632506'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2007/05/configuration-management.html' title='Configuration Management'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6014891109350101719</id><published>2007-04-11T15:49:00.000-08:00</published><updated>2008-07-16T10:52:30.026-08:00</updated><title type='text'>Alaska Beer Relays 2007</title><content type='html'>The Alaska Beer Relays, hosted this year by the Potter Valley Nordic Foundation, were a great success. Thanks to all who participated and volunteered.&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;object height="350" width="425"&gt; &lt;param name="movie" value="http://www.youtube.com/v/gWZF54Usno4"&gt;  &lt;embed src="http://www.youtube.com/v/gWZF54Usno4" type="application/x-shockwave-flash" height="350" width="425"&gt;&lt;/embed&gt;  &lt;/object&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6014891109350101719?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6014891109350101719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6014891109350101719' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6014891109350101719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6014891109350101719'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2008/07/alaska-beer-relays-2007.html' title='Alaska Beer Relays 2007'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-6741246258310660065</id><published>2007-04-07T02:07:00.000-08:00</published><updated>2008-07-16T11:02:05.743-08:00</updated><title type='text'>Massive Live Midi Sets</title><content type='html'>How I organize massive Live sets.&lt;br /&gt;&lt;br /&gt;For what it's worth, I've made at least a little progress here. I&lt;br /&gt;started by dragging all of my sets into one set, keeping the order of&lt;br /&gt;the tracks. Keeping the songs grouped vertically by keeping their&lt;br /&gt;tracks next to each other together, I started playing with the scenes&lt;br /&gt;trying to group together the best concepts within and between the&lt;br /&gt;songs. That means that you end up with a sort of checkerboard of song&lt;br /&gt;scenes (the chunk of scenes for each song being a sqquare), going from&lt;br /&gt;the upper left to the lower right, plus some extra scenese for&lt;br /&gt;meaningful transitions between songs.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I've got eight midi faders, so I hooked the firs one to every single&lt;br /&gt;drum track, and the second one to every single bass track, the third&lt;br /&gt;one to every stab track, etc. The scenes make sure that they don't&lt;br /&gt;collide with each other...&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;I also have started to develop my own pattern for how to use each knob&lt;br /&gt;above the mixer. For example, I do a lot of LP filtering on my bass,&lt;br /&gt;so i make sure that the top knob for the bass channel always does an&lt;br /&gt;LP filter-ish sort of thing. The second knob on the drums always makes&lt;br /&gt;the drums repeat at a higher tempo - usually by a delay. It took a&lt;br /&gt;while - but I finally realized that I didn't have to figure out how to&lt;br /&gt;make each midi fader/knob channel work for one channel, but to just&lt;br /&gt;connect it to every channel and make sure it basically does the same&lt;br /&gt;thing for each one - just like how the strings always work the same no&lt;br /&gt;matter what effect pedal is working on an electric guitar.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;The most important thing to remember is that you get all of your&lt;br /&gt;tracks into your set, and you still rely on setting up scenes for&lt;br /&gt;defining the parts of the songs, and the transitions between the&lt;br /&gt;songs. Hook each similar track to the same fader/trigger controls, and&lt;br /&gt;your off. Oh - then get a faster computer...bloody dsp...&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;a href="http://www.patrickkidd.com/pk/pklive.png"&gt;&lt;br /&gt;   Check it...&lt;br&gt;&lt;br /&gt;   &lt;img src="http://www.patrickkidd.com/pk/pklive_thumb.png"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-6741246258310660065?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/6741246258310660065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=6741246258310660065' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6741246258310660065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/6741246258310660065'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2007/04/how-i-organize-massive-live-sets.html' title='Massive Live Midi Sets'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-9199721692157215198</id><published>2007-03-02T10:42:00.000-09:00</published><updated>2008-07-16T10:53:45.307-08:00</updated><title type='text'>Energy, bias, and the world we live in.</title><content type='html'>I've been spending a lot of time relating to the world as a pool of&lt;br /&gt;energy lately. If you use the analogy that everything in the world,&lt;br /&gt;every action and every object represents a certain amount of a certain&lt;br /&gt;kind of energy, you begin to adopt this interesting relationship with&lt;br /&gt;your environment. By just calling it "energy", I've saved myself the&lt;br /&gt;time I could be wasting trying to come up with explainations for&lt;br /&gt;everything, and I have more time to react to the energy. There's good&lt;br /&gt;energy, bad energy, strong, weak, fluctuating. Once I realized that I&lt;br /&gt;wanted to be able to react to people and things better and that I&lt;br /&gt;didn't care why or how, things started to get a lot more interesting.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;A lot of it has to do with becoming more of an observer and less of an&lt;br /&gt;actor. Opening up your body and paying more attention to sensory input&lt;br /&gt;allows you to learn more about what's happening around you, and&lt;br /&gt;eventually allows your body and mind to react in more of a natural way,&lt;br /&gt;instead of a pre-conceived rationalized way.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;This stuff is inherently difficult or impossible to write about,&lt;br /&gt;because it has so much to do with letting go of using intellect to&lt;br /&gt;rationalize why things happen the way they do, and just letting your&lt;br /&gt;body react the way it feels right. It gets really interesting, though,&lt;br /&gt;when I start to observe all the usual religions and how they tell you&lt;br /&gt;to live and the things they tell you to do. I am starting to see more&lt;br /&gt;unified concepts that exist between them, and conversely how the areas&lt;br /&gt;that they conflict arise mostly from ignorance where the participants&lt;br /&gt;fail to see the big picture.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;I suppose I would now call myself a spiritual person since I am in&lt;br /&gt;touch with things that we don't see and touch. But, I don't really&lt;br /&gt;like that word so much because when you hear it you tend to think of&lt;br /&gt;God and Allah and angels, and most importantly reference to some&lt;br /&gt;religious. More specifically when I thing of "spiritual" I think of&lt;br /&gt;ignorance. But, it seems like the closest thing we've got to what I'm&lt;br /&gt;feeling.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;So I steer away from definitions and explainations. In fact, it's kind&lt;br /&gt;of counter-productive to write this stuff down except as inner dialog&lt;br /&gt;(my blog, my way!). Don't rationalize, don't define, don't put things&lt;br /&gt;in a box. It is possible to teach without text and it is possible to&lt;br /&gt;explain without using words. If you are what you beleive and feel,&lt;br /&gt;people and things have a way of detecting and reacting to it even if&lt;br /&gt;they don't realize it.&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;"Free yourself and you free the world" &lt;br&gt; &lt;br /&gt;&lt;br&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;- The Buddha&lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-9199721692157215198?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/9199721692157215198/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=9199721692157215198' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9199721692157215198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/9199721692157215198'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2007/03/energy-bias-and-world-we-live-in.html' title='Energy, bias, and the world we live in.'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-5963791113785565340</id><published>2007-02-22T00:14:00.000-09:00</published><updated>2008-07-16T10:55:34.971-08:00</updated><title type='text'>My tools rock</title><content type='html'>With my xone:3d, an FA-101, my keystation 49e and ableton live, I've&lt;br /&gt;got the coolest tools ever. With this stuff I can compose music and&lt;br /&gt;play with it moreand more like how I wanted to with the pksampler. I&lt;br /&gt;can actually see how I could spend time with my setup and learn to use&lt;br /&gt;it just like musicians get used to their instruments. So - finally - the tools are out of the way and the creativity is in. Maybe I should take violin lessons agian, hmmm&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-5963791113785565340?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/5963791113785565340/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=5963791113785565340' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5963791113785565340'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/5963791113785565340'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2007/02/my-tools-rock.html' title='My tools rock'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-7638916194034063921</id><published>2007-02-01T10:11:00.000-09:00</published><updated>2008-07-16T11:02:53.223-08:00</updated><title type='text'>M$ Is Missing The Point : A Whole New Vista</title><content type='html'>Today I caught myself saying that Vista is totally going to suck and&lt;br /&gt;then realized that I had no concept of what was supposed to make it&lt;br /&gt;good. &lt;br /&gt;&lt;p&gt;&lt;br /&gt;"The biggest difference is that apple are improving on things&lt;br /&gt;that already work. Microsoft's marketing is stil targeting the idea&lt;br /&gt;that they finally figured it out." - me&lt;br /&gt;&lt;p&gt;&lt;br /&gt;After thinking about it I realized that that company is still pushing the idea that they've relayed the foundation, but correctly this time. I don't want to get used to a whole new environment again. They should get the ideas for their products solid first, then try to get everyone to buy into it. My mac rocks - and has been the same for a long time. Stop changing everything!&lt;br /&gt;&lt;p&gt;&lt;br /&gt;Why does this matter? Why do I care if my stuff works?? Because I have to write code for it man!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-7638916194034063921?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/7638916194034063921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=7638916194034063921' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7638916194034063921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/7638916194034063921'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2007/02/m-is-missing-point-whole-new-vista.html' title='M$ Is Missing The Point : A Whole New Vista'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-130402213334709639.post-1568438960566858038</id><published>2006-10-03T12:34:00.000-08:00</published><updated>2008-07-16T11:05:51.065-08:00</updated><title type='text'>PKSampler's Future</title><content type='html'>So I've been spending a lot of time writing commercial music software and playing with ableton live.&lt;br /&gt;&lt;br /&gt;There is no better way to become a better programmer than to write&lt;br /&gt;code commercially. You can learn a lot more with deadlines, using new&lt;br /&gt;design patterns, and interacting with others than you can just writing&lt;br /&gt;"cool" software at home. It is obvious after getting used to ableton&lt;br /&gt;live that the pksampler is not going to provide the ground-breaking&lt;br /&gt;concepts that it would have had I released it a while&lt;br /&gt;ago. Fortunately, though, there is a lot of useful code in there. &lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;It would be nice to provide a sampler interface with some synths and&lt;br /&gt;midi support. I could go further with a pattern editor and&lt;br /&gt;adding/saving midi files or clips like ableton live. It would be&lt;br /&gt;important to stick to established standards as much as possible to&lt;br /&gt;keep it as palettable as possible for new people. Touchscreen&lt;br /&gt;usability would be vital, of course...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/130402213334709639-1568438960566858038?l=pkaudio.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://pkaudio.blogspot.com/feeds/1568438960566858038/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=130402213334709639&amp;postID=1568438960566858038' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1568438960566858038'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/130402213334709639/posts/default/1568438960566858038'/><link rel='alternate' type='text/html' href='http://pkaudio.blogspot.com/2006/10/pksamplers-future.html' title='PKSampler&apos;s Future'/><author><name>Patrick Stinson</name><uri>http://www.blogger.com/profile/06281564829886653770</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://bp0.blogger.com/_-kPtlLn0YiA/SH4uaJcgmwI/AAAAAAAAAO8/hkIQmNJGx4s/S220/mug.jpg'/></author><thr:total>0</thr:total></entry></feed>
