Possible downtime of the site

January 25th, 2008

My Web Hosting provider is upgrading their servers sometime during the next days (between 25-28 January), so this website will probably be down for ~1hour… That is, if everything goes right.

If you’re one of the employers I had/will have interviews with, and you’re reading this, I really hope the site won’t offline for too long.

czPlayer 0.2.0 released

January 7th, 2008

I’ve been working hard on czPlayer, and here is the result. Version 0.2.0 released.
The API is mostly incompatible with the previous 0.1.1 version.
I’ve made a lot of changes to this version and added some new features, so I decided to jump the version number to 0.2.0.
All the internal refactoring I’ve made will hopefully allow me to add some new features I have in mind, like DSP effects (both internal and user provided) .
Needless to say, I’m not particularly confident about the stability of this version, with all the changes I’ve made. Some functions were not even tested yet. But like I said in earlier posts, there is always something to fix or improve, so I better release and work from there, than to keep fixing/improving stuff and never release.
I have so many crazy ideas for features! But most of them will not be implemented, because of the targeted platforms.
Codesize and performance have priority, not features… well… at least for czPlayer.
That leads me to another thing I’ve been thinking about…
Maybe I’ll eventually fork czPlayer into Mobile and Non-Mobile versions, so that I can go wild on all the things I want to implement. Hehe
Most of what I dislike in czPlayer (both internal, and in the external API), are a direct consequence of the compromises I had to make to support the targeted platforms, and have the same API for all of them.
Nuff said… You’ve got to ask yourself one question: “Do I feel lucky? Well, do you, punk ?

If so, go ahead, download the new version and give it a try:
Download lastest czPlayer demo.

Simplifying code using states

December 19th, 2007

Lately I have been refactoring czPlayer to add more features and make future maintenance easier.
Some parts of the code are almost 10 years old, when I first started playing with sound coding.
Needless to say, my code style and quality has improved a lot in 10 years, and it’s a funny thing to look at code this old. :)
As I was refactoring the code, I found a lot of ambiguities and redundancies caused by member variables added over time.
Let me explain….
I had a class responsible for MOD processing, and some of the member variables were:

[code='cpp']
class MODModule
{
// ...
bool m_loaded;
bool m_playing;
bool m_paused;
bool m_reachedEnd;
};
[/code]

What’s the problem with this approach ?
Let’s see…
Suppose I want to call methods on the MOD object (e.g: Pause(), Resume(), etc)
I need to make some checks in each method.

To pause…
[code='cpp']
if (!m_loaded || m_playing || m_paused)
return SOME_ERROR;
m_pause = true;
// ... do pause stuff
[/code]

Then to resume…
[code='cpp']
if (!m_loaded || !m_paused)
return SOME_ERROR;
m_paused = false;
// ... do resume stuff
[/code]

When the MOD finishes playing, I needed something like this…
[code='cpp']
// ... some code that checks for end
m_reachedEnd = true;
//ups... How about m_playing, m_paused?
//We need to change their values, so we don't break code elsewhere
m_playing = false;
m_pause = false;
[/code]

And similar things when playing, stopping, etc.
See the problems?

  • We need checks for multiples variables
  • We need to make sure the variables have valid values in relation to each other
  • What if we want to add an extra state? For example, “bool m_fading”. We would need to examine a lot of code to check how the other variables are used, and hardwire this new one somewhere. Every time you need to add an extra variable, you’ll need to check more and more code to make sure everything is ok.

Now look at the meaning of the variables. They are mostly mutually exclusive.

  • If it’s playing, it can’t be paused and hasn’t reached the end.
  • If it’s paused, it’s not playing, and hasn’t reached the end yet.
  • … and so on….

The more data members a class has, the harder it gets to keep the object in a valid state, so, the less data to manage, the better. Less maintenance and less bugs.

One technique I use a lot when trying to simplify code is to look at it with state diagrams whenever possible.
Here it is what happens (kind of) with instances of the MODModule class:

mod_states.png

I can easily translate it to code with enums.

[code='cpp']
enum MODState
{
MOD_STATE_NOT_LOADED,
MOD_STATE_STOPPED,
MOD_STATE_PLAYING,
MOD_STATE_PAUSED,
MOD_STATE_REACHED_END
};

class MODModule
{
// ...
MODState m_state; // Now we have only one variable
};
[/code]

This approach is a lot easier to maintain, and less error prone.
Now the code in most functions become something like this:

To play…
[code='cpp']
if (m_state!=MOD_STATE_STOPPED)
return SOME_ERROR;
m_state = MOD_STATE_PLAYING;
// ... do play stuff
[/code]

To pause…
[code='cpp']
if (m_state!=MOD_STATE_PLAYING)
return SOME_ERROR;
m_state = MOD_STATE_PAUSED;
// ... do pause stuff
[/code]

To resume…
[code='cpp']
if (m_state!=MOD_STATE_PAUSED)
return SOME_ERROR;
m_state = MOD_STATE_PLAYING;
// ... do resume stuff
[/code]

To stop…
[code='cpp']
// We cannot stop if it's not even loaded yet, or it's already stopped
if (m_state==MOD_STATE_NOT_LOADED || m_state==MOD_STATE_STOPPED)
return SOME_ERROR;
m_state = MOD_STATE_STOPPED;
// ... do stop stuff
[/code]

The code may look similar, but it’s a lot less error prone, easier to follow and maintain.
Looking at the State Diagram, I could easily squeeze in a “Fading” state and understand the conditions to enter or leave that state.

As a bonus, using enums will enforce more rules and help you out with errors the compiler might catch. Always prefer compile-time errors over run-time errors. ;)