Archive for the ‘C#’ Category

More optimization

Friday, October 10th, 2008

Not creative enough to think of a better title right now…

I just spent almost two hours hacking away at the Banshee visualization pipeline again and made one very important optimization: when the callback function is null (which happens when nobody in managed land is listening for visualization data) the visualization pipeline is effectively disabled. The only element that remains active is a queue, which provides a 5-second buffer so that visualization can be quickly resumed.

The patch is now over at GNOME’s Bugzilla, just waiting. Waiting for Aaron to commit it. Waiting for a chance to prove it’s all grown up now. Hoping to bring joy to audio enthusiasts all around the globe.

Yeah, I did watch Tommy Boy recently. … Why?

Optimizing the visualization pipeline

Thursday, October 9th, 2008

So apparently the visualization stuff in Banshee has been disabled since it’s a CPU hog. I don’t know why I didn’t notice it during testing (and I did check) but there seems to be a five-fold increase in CPU utilization with the visualization pipeline running. For me, this is an increase from 1-3% to 10-12% on dual-core 2.6GHz amd64.

After ruling out a few things I discovered the root cause. In OpenVP, PCM and spectrum data are represented as 32-bit floats, which means that the pipeline needs to convert whatever the audio format is into this one. Along the way it resamples the stream too, to provide a consistent frame rate of consistent-size slices. 512 samples 60 times per second is 30720 samples/sec. If anyone can show me a song found in the wild encoded at this rate I’ll give you… well, nothing, since I’m a college student and couldn’t afford to give you this pencil I have sitting on my desk.

Anywho, the conversion to float cannot be avoided but the resampling can be. By setting it to the more common 44100Hz sample rate CPU usage dropped to 4-6%. It’s pretty cheap to convert formats and throw duplicate data around, but interpolating data is a lot more expensive.

At some point the vis pipeline will be smart enough to split music into chunks of a size depending on the current sample rate. Until then this patch should be good enough. (I hope.)

Almost there

Sunday, August 24th, 2008

After a few hours of hacking using a wigdet that Michael and a few others pointed me at, I now have a working Banshee.OpenVP extension!

Much work still remains to be done, but what I have is a pretty stable foundation. Both the OpenVP 0.0.1 branch and Banshee.OpenVP are available over at the Google Code repo. They should both be stable enough to test, but since the build system isn’t in place yet I’m not asking the general public to try it out yet. But if you know your way around MD, autotools, and Banshee you might be able to get it working. (Please don’t ask for help with that part yet. If you get it working and hit a bug please let me know though.)

Ok, I guess not

Friday, August 22nd, 2008

Banshee.OpenVP is on hold indefinitely until a stable GTK+ widget providing an OpenGL context is available. All of the wrappers I have tried have serious issues that prevent this project from even making minimal headway.

Upcoming goodness

Thursday, August 21st, 2008

I’ve been working with several Banshee people this week and we finally got my patch committed. All this patch does is provide a managed event that acts as a PCM and spectrum data source. While simple, it is a required building block for the upcoming OpenVP extension.

Right now I am getting ready for the 0.0.1 release of OpenVP. The version number is intentionally scary; the API is far from stable and will be changing rapidly. The purpose of this release is to provide a stable target for the Banshee extension. Hopefully getting this in Banshee will generate interest in OpenVP, as well as giving Banshee some cool eye-candy. Everybody wins!

My understanding is that after OpenVP 0.0.1 is released and the Banshee.OpenVP extension is finished (it’s proof-of-concept quality right now) it will be absorbed into the Banshee source tree and maintained over there. Which means it will likely come with Banshee 1.4 by default. Awesome.

(Oh, and OpenVP has migrated from my personal Subversion repository over to its own Google Code project.)

.NET and XPath

Tuesday, July 1st, 2008

So I’m working on this XPath presentation for my team at work. I was trying to hack up a sample using some of the more interesting XPath functions, like string-join. PHP’s DOMXPath throws a fit when I use this function so I cracked open MSDN and saw that XPathNavigator in the 2.0 framework claims to support “the XQuery 1.0 and XPath 2.0 Data Model[s].” Nifty, huh? Especially since string-join is defined in those specs. (Note that this table claims it is available in XPath 1.0. Apparently nobody bothered to check the XPath 1.0 specification which does not mention it at all.)

PHP’s implementation must be broken then. Off I go and code a Winforms project that I can use to run my example. Right? Yeah, right…

For the sake of simplicity, I coded a small CLI program that will run an XPath query against an empty document:

using System;
using System.Xml;
using System.Xml.XPath;

public class XPathCLI {
    public static void Main(string[] args) {
        XmlDocument doc = new XmlDocument();

        XPathNavigator nav = doc.CreateNavigator();
        Console.WriteLine(nav.Evaluate(args[0]).ToString());
    }
}

Now let’s make sure it’s working:

$ ./XPathCLI.exe 'concat("hello ", "world")'
hello world

Looks good. Now let’s try the examples listed under string-join:

$ ./XPathCLI.exe "string-join({'Now', 'is', 'the', 'time', '...'}, \" \")"

Unhandled Exception: System.Xml.XPath.XPathException: invalid token: '{'
  at Mono.Xml.XPath.Tokenizer.ParseToken () [0x00000]
  at Mono.Xml.XPath.Tokenizer.advance () [0x00000]
  at Mono.Xml.XPath.XPathParser.yyparse (yyInput yyLex) [0x00000]
  at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000]

$ ./XPathCLI.exe "string-join({abra, cadabra}, \"\")"

Unhandled Exception: System.Xml.XPath.XPathException: invalid token: '{'
  at Mono.Xml.XPath.Tokenizer.ParseToken () [0x00000]
  at Mono.Xml.XPath.Tokenizer.advance () [0x00000]
  at Mono.Xml.XPath.XPathParser.yyparse (yyInput yyLex) [0x00000]
  at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000]

$ ./XPathCLI.exe 'string-join((), "separator")'

Unhandled Exception: System.Xml.XPath.XPathException: Error during parse of string-join((), "separator") ---> Mono.Xml.XPath.yyParser.yyException: irrecoverable syntax error
  at Mono.Xml.XPath.XPathParser.yyparse (yyInput yyLex) [0x00000]
  at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000] --- End of inner exception stack trace ---

  at Mono.Xml.XPath.XPathParser.Compile (System.String xpath) [0x00000]
  at System.Xml.XPath.XPathExpression.Compile (System.String xpath, IXmlNamespaceResolver nsmgr, IStaticXsltContext ctx) [0x00000]
  at System.Xml.XPath.XPathExpression.Compile (System.String xpath) [0x00000]
  at System.Xml.XPath.XPathNavigator.Compile (System.String xpath) [0x00000]
  at System.Xml.XPath.XPathNavigator.Evaluate (System.String xpath) [0x00000]
  at XPathCLI.Main (System.String[] args) [0x00000]

Ok, that didn’t go too well. Apparently Mono doesn’t like some of the syntax. Let’s use a node selecting expression instead:

$ ./XPathCLI.exe 'string-join(//something, "separator")'

Unhandled Exception: System.Xml.XPath.XPathException: function string-join not found
  at System.Xml.XPath.ExprFunctionCall.Evaluate (System.Xml.XPath.BaseIterator iter) [0x00000]
  at System.Xml.XPath.CompiledExpression.Evaluate (System.Xml.XPath.BaseIterator iter) [0x00000]

Uh… ok. Let’s start over on MS.NET. It must be a Mono bug, right?

>XPathCLI.exe "string-join({'Now', 'is' 'the', 'time', '...'}, \" \")"

Unhandled Exception: System.Xml.XPath.XPathException: 'string-join({'Now', 'is''the', 'time', '...'}, " ")' has an invalid token.
   at MS.Internal.Xml.XPath.XPathScanner.NextLex()
   at MS.Internal.Xml.XPath.XPathParser.ParseMethod(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParsePrimaryExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseFilterExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParsePathExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseUnionExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseUnaryExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseMultiplicativeExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseAdditiveExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseRelationalExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseEqualityExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseAndExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseOrExpr(AstNode qyInput)
   at MS.Internal.Xml.XPath.XPathParser.ParseXPathExpresion(String xpathExpresion)
   at System.Xml.XPath.XPathExpression.Compile(String xpath, IXmlNamespaceResolver nsResolver)
   at System.Xml.XPath.XPathNavigator.Evaluate(String xpath)
   at XPathCLI.Main(String[] args)

Let’s jump straight to the one that made it past Mono’s parser to crash in the evaluator:

>XPathCLI.exe "string-join(//something, \"separator\")"

Unhandled Exception: System.Xml.XPath.XPathException: Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function.
   at MS.Internal.Xml.XPath.CompiledXpathExpr.get_QueryTree()
   at System.Xml.XPath.XPathNavigator.Evaluate(XPathExpression expr, XPathNodeIterator context)
   at System.Xml.XPath.XPathNavigator.Evaluate(String xpath)
   at XPathCLI.Main(String[] args)

From this we can make a few conclusions:

  • Mono, MS.NET, and PHP do not support XPath 2.0. I cannot find any PHP documentation that claims a specific version of XPath support, but, as noted in the intro paragraph, MSDN claims XPath 2.0 support and MS.NET does not deliver. (Mono may be following the MS.NET implementation instead of the spec, so whether this is a Mono bug or not is debatable.)
  • Mono, MS.NET, and PHP do not support the {...} construct, which is present in the XPath 2.0 “Precedence Order” section but not actually defined elsewhere. This construct is not present at all in the XPath 1.0 specification. Whether this is a specification or implementation defect is left an open question.
  • Mono, MS.NET, and PHP do not implement the string-join function defined in at least XPath 2.0.

And from those conclusions we can draw a few more.

  • Nobody gives a whip about following the XPath specification.
  • The XPath specification is broken. Or confusing. Or (more likely) both.

The real question, then, is do people intentionally not implement the XPath 2.0 specification because they don’t want to, or because parts of it make no sense? It seems odd to me that an implementation would support concat and not string-join, especially since they are defined right next to each other.

In any case, if you’re not implementing all of it, don’t claim that you do. Incorrect documentation is worse than no documentation.

Banshee, meet OpenVP

Wednesday, April 30th, 2008

OpenVP, Banshee.

A week or two ago I was in #banshee chatting and posted a link to an album of some OpenVP screenshots. The developers were interested and asked me if I would try embedding OpenVP in Banshee. I have since submitted a patch that adds an interface that PlayerEngine classes can implement to become a visualization source, and also implements this interface on the GStreamer backend.

Once OpenVP is library-ized there will be a second patch adding an OpenVP extension, which will make Banshee do something like you see in the above screenshot. Probably not exactly as you see it there, since I’ll probably want to “take over” the Now Playing window and render there instead.

Basically what I’m saying is that all the ugly plumbing is done and right now it works. It just needs polish, and hopefully it’ll be ready when Banshee 1.0 is.

OpenVP under development

Saturday, December 15th, 2007

While thinking about how I was going to implement something in Kaffeeklatsch recently, I took a step back and looked at the class structure. What a mess. Over the next few days I drafted a new class structure that would better reflect the goals of the project and make implementation of new features simpler.

The last week or two have been spent implementing that new design and it’s very promising so far. Specifically, media player connectivity and presets have been overhauled. The OptionAttribute class has been removed in favor of a series of attributes from System.ComponentModel. The GUI designer is looking more slick than ever.

With the rewrite comes a new name: Open Visualization Platform, or OpenVP for short. Development is taking place in my public Subversion repository, so if you want to track it just svn co https://layla.chrishowie.com/svn/OpenVP. You will need a recent MonoDevelop to build the project.

Tursiops 0.1 released

Monday, December 3rd, 2007

As expected, the hacking on Tursiops continued most of last week. I’m a little late getting a release out there, but here it is. The archive contains two folders, one for i386 machines and one for amd64. The copy of Tursiops in each is identical, but the glue library is platform-specific.

If you want the corresponding source code, svn co https://layla.chrishowie.com/svn/Tursiops. This release corresponds to revision 126 if you want the exact code of this release at a later date.

The only known issue at this point is that the “refine search” function does not update the progress meter, and a refine operation cannot be canceled. This should be fixed in the next release.

Feedback is welcome — just comment here. Enjoy!

On CIL and coding

Tuesday, November 27th, 2007

Is it bad that whenever I code C# I can see exactly the IL that will be produced? Should I start developing with ilasm? Hmm…