Saturday, March 12, 2011

jvorbiscomment

If this blog is to document all my code projects then I ought to mention jvorbiscommentjvorbiscomment is a small Java library for reading and writing Ogg Vobis comment tags (ie ARTIST, ALBUM, TITLE, etc). I wrote it for my "Music Hive" juke box program which I used for a couple years but never released.  I don't know of any real projects using jvorbiscomment but I certainly think they should.  I put so much thought and testing into it!  Copying the features list from the project site:

Features

  • Simple - Two static methods: VorbisIO.readComments and VorbisIO.writeComments
  • In-place Updates - Comment changes are written to the original file, not a copy of the file. This means updates will be faster and the file attirbutes, such as permissions and creation time, will remain intact.
  • Buffered Updates - A buffering scheme is employed to avoid re-writting the entire file when the comments are changed by only a small amount.
  • Unicode - Full support for Unicode text.
  • Tested - Many unit tests have been written in hopes of preventing file corruption. I have executed this library on my 3500 file Ogg collection.
  • Maintained - I am committed to maintaining this library. Reported issues will be addressed in a timely manner. Since this project has a very small and clearly defined scope, inactivity should be considered a good thing (many happy customers).

Standard GUI (stdgui)

I'd like to upload an idea my brain has been baking for the last couple years.  Why is it that writing a GUI program is so much more complex than a console program?  Console user interfaces are so darn simple:
  • You output text through stdout.
  • You read text from stdin.
  • Arguments are passed to you in a string array.
  • All major platforms and programming languages support this, out-of-the-box!  No additional libraries required.
So, if you wish to write a program, and you want it to be as portable as possible, writing a console program is the simplest solution.

Things are not so simple with GUI programs.  Here's a list of things that must be considered:
  • What language am I working in?  Which GUI toolkits have bindings for my language?
  • What platform(s) am I targeting?  Which toolkits are supported on these platforms?
  • How can I make my program look and feel like a native program?
  • How do I do X with my chosen toolkit?
  • Why are the language bindings incomplete and poorly documented?
  • Does my GUI meet accessibility standards for all platforms?
  • Why am I writing so much code just for a GUI!
You get the point.  Creating a cross platform GUI program is not simple.  I'd like to change this.  I don't think there's any technical reason we cannot have some sort of abstract, standardized GUI programming model akin to stdin/stdout.  We just have to make a few concessions:
  1. We must give up power and flexibility in order to gain simplicity and portability.
  2. Avoid the huge API, "toolkit" paradigm and instead use a specialized middle-man language to define the GUI.
So, if you need to write an advanced GUI program, look elsewhere, stdgui is not for you.  However if you want to write a portable GUI program with minimal fuss, stdgui is the solution.

Here's how I envision the stdgui system would work:
stdgui architecture overview


In list format, the big features of stdgui would be:
  • Language independent - By specifying the GUI using a middle-man, language we can keep the necessary C API small and thus super easy to maintain bindings for in all languages.
  • Platform independent - your GUI specification works on all major platforms.
  • Platform native - your GUI will use the native/preferred toolkit of the platform.  So on GNOME Linux it renders with GTK.  On KDE Linux, Qt.  On Windows it would use the native Win32 controls.  On Mac it would use native Cocoa.
  • Declarative - The majority of GUI's are static in nature and thus lend themselves well to a declarative language.  HTML is a prime example of this.
  • Simple Layout - The control layout mechanism should be simple enough to write by hand yet should also facilitate a WYSIWYG editor. (Toolkits like Swing give you 87 different layout managers and expect you to learn them all and know how to mix and match them to create the behavior you want.  Yuck!)  I'm leaning towards a "snapping" based paradigm where control edges stick together like magnets.  Only specified controls are allowed to stretch when the window is resized.
  • Dynamically linked - Your app links to an ABI, not a native toolkit.  That means if you switch from GNOME to KDE you don't have to recompile all your apps for them to render with Qt.  Just edit your libstdgui.so symlink.
  • Composite Controls - Larger apps often need to show the same groups of controls on different forms.  You should be able to define these in one place and simply reference them as needed.
  • Accessibility - By writing your GUI at a higher level of abstraction I would hope that ensuring proper accessibility features could become automatic.  For instance, making sure that labels are associated with text fields and assigning keyboard "accelerator" shortcuts.
  • Context Help - I really appreciate apps which give tooltips when hovering over a checkbox I don't understand.  The language should make it super easy to provide context help like that.
  • Dependencies  - Often times a one or more GUI controls should be disabled until a checkbox or radio button is selected.  Simple dependencies like this should be easy to declare.
  • Easy Dynamic Data - All non-trival GUI applications need to populate selection lists dynamically.  This should be made as easy as possible.  Many toolkits I've used make this harder than it ought to be.
  • No tweaking - stdgui does not give you fine grained control.  For example, you can't change the font of a button.  Such power is a slippery slope towards applications that don't "feel" native.
  • Simple Drag-N-Drop:  Making your application support common drag-n-drop types like files and text should be ultra-simple and sometimes even automatic.  Furthermore, whenever DnD is enabled you should get cut/copy/paste for free as well.
  • Control Extensions - What if you love the simplicity of stdgui but just need one custom/fancy control?  Create your custom control in the native toolkit and put it in a DLL.  When your app starts up it will register the custom control with stdgui so that it can be used.  If you fail to port this custom control to other platforms stdgui will degrade gracefully by showing a blank area where the control would have been.
  • Degrade Gracefully - If somebody runs your app against an old version of stdgui it should degrade gracefully.  For example, if stdgui 1.1 adds a feature where buttons can have icons, your program should still run against a 1.0 stdgui as well.  You just won't see the icons.
But wait, hasn't this been done before?  There are many cross-platform toolkits already.  What's wrong with them?
  • Mozilla XUL - The toolkit behind Firefox.  Super flexible, mature and declarative!  Overlays feature sounds really neat.  XUL might be very close to what I want.  I will investigate further.  Why isn't everybody using it?  There must be a catch...
  • wkWidgets - A great toolkit with native rendering.  This should be what you reach for if stdgui is too simple for you needs.  Problem: huge API, (over 500 C++ classes), and thus hard to maintain bindings for.
  • Qt - Perhaps the most polished toolkit out there.  Does some native rendering I hear.  Problem: huge API, (over 800 C++ classes), and thus hard to maintain bindings for.
  • GTK - Widely adopted and powerful toolkit.  Problem: huge API and development is focused mainly on Linux.
  • Swing - Problem: Java only
  • SWT - Problem: Java only
  • FLTK - Very lightweight and portable C++ toolkit.  Problem: no native rendering.
  • Fox Toolkit - Powerful and portable.  Problem: no native rendering and huge API.
  • RealBasic - Many swear by it.  Problem: BASIC only
Most of the above are unsuitable because they're "toolkits".  That's another word for big API.  Creating and maintaining toolkit bindings is a huge chore.  For this reason, young and niche languages will not support it.  To achieve ubiquity it's gotta have a small, stable C API.  I suspect this is possible but it needs to be proven.  Stay tuned...

P.S.  I found some discussions on this topic while cleaning out my bookmarks:
EDIT: stdgui is now a project on GitHub.

      Monday, March 7, 2011

      Getting ready for sabbatical

      One day last month I was feeling particularly whimsical and had a crazy idea.  Perhaps it was a hint of spring in the air, or a good night sleep, or the sobering knowledge that my wife was going to give birth in mere weeks.  The idea was simple:
      I should take a year off from the computer!
      At the time the idea really scared me.  I really love playing with computers - it's super stimulating.  And that is just the problem.  Whenever my mind is idle I find myself thinking about my current computer projects and I have trouble "being present" to the rest of life.  I don't want to miss my child's first year of life!  Secondly, I've always wondered what else I'd accomplish if I didn't spend so much time on the computer.

      So I'm going to do it!  By Monday, March 14th at midnight (00:00) my laptop and desktop will be boxed up and stored away.  Before then I have a few loose ends to tie up:
      1. Tidy up my AwareEngine project so that I'll be able to understand it when I resume the project next year.
      2. Write some blog posts about a couple project ideas I've had floating in my head lately.

      Wednesday, February 9, 2011

      Overlay Bittersweets

      So I implemented the overlay system described previously.  On the up side, I'm now rendering the water effect at about 35 FPS as opposed to my previous ~27 FPS.  Although the native code was refactored somewhat I'm pretty certain the gain comes from using a separate thread.  While the GPU is rendering the scene I'm busy preparing the next frame of water.  Sweet!

      The bitter part is that as soon as I add another layer on top of the water, performance drops drastically (~10 FPS for my test case).  There's no way I can render fog on top of water with this system.  It's too slow to do all this image compositing on the CPU.  I need to leverage the GPU...

      I've decided that the technology demo will have to ship without the fog effect.  When I come back to this problem I'll experiment with making a good looking fog effect using alpha mapped OpenGL textures.

      Friday, January 28, 2011

      Image Overlays

      The Aware Engine code got a bit messy after I added the water effect feature.  It had me worried because I still have to add a fog effect and video loops.  After sitting down with pen an paper I came up with a better architecture. I'll call it Overlays.

      Nothing revolutionary really.  It's basically a way of layering, (overlaying), small images on top of the pre-rendered scene image:


      This concept of an Overlay gives me a unit of abstraction for all these types of effects.  This is good because:
      • It allows me to deal generically with all these dynamic effects.  (Clean code)
      • Adding new effects in the future won't require re-architecting the code.
      • I can load and render all overlay effects asynchronously using a thread pool.
      The final point is a real relief to me because both the water effect and fog effects are CPU intensive and it would be a shame not to take full advantage of today's multi-core CPUs.

      Wednesday, January 19, 2011

      AwareEngine First Screenshots

      Okay.  So I've been working on the "engine" code for this tech-demo.  I'm calling it the Aware Engine.  Using my newly honed water-effect techniques I've created a rippling background for the menu.  A still image does not do it justice but:

      I've also applied the water effect to my lava using a mask:

      (click to zoom)
      The mask above is shown as a 360 degree equirectangular (aka panoramic) environment map.

      Next I need to generalize the masked water effect code and then I'll begin work on the smoke effect.

      I'm kind of struggling with performance issues too.  The water effect is calculated on the CPU per-pixel - I'm not leveraging the graphics card at all.  I've got it up to about 25 FPS on my laptop but I need more for the smoke effect.  Perhaps I'll use a second thread to asynchronously render the effect(s) and just set minimum system requirements to any dual-core CPU.  We'll see.

      Friday, January 7, 2011

      Cruxic Water Demo

      I've been working on the water and liquid effects for the broadcast-room technology demo.  Although the Riven scene doesn't have liquid, I got carried away and now have a separate room with liquid lava.  This sent me off on a long tangent exploring various pixel-based water effects.  I was assisted greatly by the many online tutorials and example programs so I'd like to return the favor by posting the code I came up with.

      I call this the "Cruxic Water Demo".  Here's a video:



      I'm releasing the code under the MIT license so you can pretty much do whatever you want with it so long as you keep the license attached if you redistribute either the source or derived executables.  Note, however that the Perlin noise code, Noise1234, is not mine and is licensed under the GPLv2.

      Download here  (source code and executables for Linux AMD64 and Win32)