Friday, February 27, 2009

Copying a stream to another stream

It’s obvious that the ability to copy the contents of one stream to another is something that you’re likely to want to do fairly regularly. I vaguely recall that this will be added to some version of the .NET Framework but until that time, here’s a simple implementation that should do the trick. It could easily be converted into an extension method so it plays better in the .NET 3 world.

    /// <summary>
    /// Copies a stream to another stream
    /// </summary>
    /// <param name="copyFrom">The stream to copy from</param>
    /// <param name="copyTo">The stream to copy to</param>
    public static void CopyTo(Stream copyFrom, Stream copyTo)
    {
      const int buffSize = 128;
      byte[] buff = new byte[buffSize];
      int count;
      do
      {
        count = copyFrom.Read(buff, 0, buffSize);
        copyTo.Write(buff, 0, count);
      }
      while (count > 0);
    }

Tuesday, February 24, 2009

Spotify – the future of music?

I’ve just discovered Spotify (via Tim Anderson) and so far I’m thoroughly impressed. Previous implementations of this kind of thing (last.fm, Pandora) have restricted your choices of what you can listen to, making them feel more like listening to a radio station than listening to your own music collection. But Spotify lets you choose exactly what you want to listen to from its database. It doesn’t have every song by every artist, like most online music sources there’s no Beatles (obviously Jacko doesn’t need the extra cash, which doesn’t quite match with what I’d heard), some of my obscure musical preferences are missing (no Godspeed You Black Emperor) and even the artists they do have aren’t generally complete. But that’s a minor quibble, there’s a still a huge range of music available.

Streaming is super quick and the ads are currently pretty infrequent and unobtrusive. The bandwidth requirements seem pretty minimal too, I could happily work in a Remote Desktop session whilst listening and I didn’t notice any dropouts.

So is this the future of music listening? I certainly hope so. The big question is whether their business model works. Will the ads cover costs? Will the music companies suddenly get cold feet like they did with Pandora in the UK? Will their servers continue to be so snappy when they become super popular? If the ads become too frequent or in your face, listening might become painful. OK, you can get rid of the ads by paying $9.99 a month but if I was to pay for any online music service I’d want to have the physical bits (with no DRM) so I’d be sure I can still listen to them if the company folded.

The only thing I’d really like to see is the integration of the online stuff with my own music library. So if I want to listen to my own ripped music I can from the same player, rather than having to jump out to iTunes. But in the mean time, I’ve got a lot of new (to me) music to listen to.

Sunday, February 22, 2009

BPM for business users

Prototype activity From my time on the Metastorm forums one thing is obvious, most people implementing Metastorm solutions are not business people. Mostly they are technical people, with a few not so technical people. And it’s generally the not so technical people who are having the biggest problems getting to grips with the product. Is that a failing of the software? I’d say not, although it could arguably be a failing of the marketing of the software, which like most BPM products suggests a non technical person can use it from start to finish to produce a working system.

This situation reminds me of other areas of software development, like the development of websites, or application development. A while ago, people thought anyone with a copy of FrontPage could develop their own website or anyone with a copy of VB could knock together a working application. But these other areas have matured enough to recognise that actually those pesky developers are still required (or to put it another way, designers can’t code and coders can’t design) and the development environments are now set up in such a way that the designers can work with the coders to produce a working system. For a website, the designer can produce a HTML layout that looks good and then the coder can add the required code so it does something. In the world of Windows development we are moving to WPF and other technologies where the layout is separated from the code, so the designer can produce the pretty screens and the coder can then add code to do stuff without both sides stepping on each others toes too much.

And for me, that’s the approach that BPM will have to take at some point, realising that the business people can’t code and the coders don’t understand the business, so trying to put only one of these people in charge of the BPM system will never fly. I think Windows Workflow is a step in the right direction with its ability to create custom activities. The coder can create all the required custom activities and then the business person can plug these together like Lego as required. Or this could work in the opposite direction, where the business user produces their process and adds dummy activities where they need functionality to be implemented and the coder goes off and creates the required activities.

With that in mind, I created a simple PrototypeActivity that can be added to a workflow and lets the user specify the inputs and outputs that will be need to be implemented. The screenshot shows how it looks in operation (although a proper implementation would probably provide a better user interface). The code is below.

  public enum PropertyDirection
  {
    In,
    Out,
    InOut
  }

  public class ActivityProperty
  {
    private string propertyName = "";
    public string PropertyName
    {
      get { return propertyName; }
      set { propertyName = value; }
    }

    private string description;
    public string Description
    {
      get { return description; }
      set { description = value; }
    }

    private PropertyDirection direction;
    public PropertyDirection Direction
    {
      get { return direction; }
      set { direction = value; }
    }

    public override string ToString()
    {
      return direction.ToString() + " - " + propertyName.ToString();
    }
  }

  public class PrototypeActivity: Activity
  {
    public static DependencyProperty PropertiesProperty =
      DependencyProperty.Register("Properties", typeof(ActivityProperty[]), typeof(PrototypeActivity));

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [Browsable(true)]
    [Description("The properties the activity requires")]
    public ActivityProperty[] Properties
    {
      get
      {
        return ((ActivityProperty[])(base.GetValue(PrototypeActivity.PropertiesProperty)));
      }
      set
      {
        base.SetValue(PrototypeActivity.PropertiesProperty, value);
      }
    }
  }

Friday, February 20, 2009

Rude Swiss

Condom shop in BaselContinuing with the rude theme, here’s a photo from my not so recent trip to Basel in Switzerland. We may assume it’s the Dutch who have the monopoly on lewd behaviour and the Swiss are more interested in banking, cuckoo clocks and chocolate. But perhaps the racial stereotypes are incorrect, here’s a shop devoted to selling condoms. I’m probably showing off my ignorance, but how can you have a shop that only sells condoms? Are there enough varieties to fill it? I didn’t enter to find out the answer.

Friday, February 13, 2009

Rude snowman

Rude snowman

Perhaps it’s just my dirty mind, but the snowman that Jo and Lola made the other day ended up looking less like a man and more like, well something else entirely. The huge erection has now melted away…

Monday, February 09, 2009

Not getting album artwork from iTunes

I had a thought the other day, how does iTunes get its album artwork? I guessed it was some kind of web service so fired up Fiddler to see if anything was getting thrown around. And sure enough iTunes was throwing a HTTP request to some server, that looked something like this (this is somewhat simplified since you can also pass CDDB information which presumably increases the chances of getting a correct hit).

http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa?an=Cult&pn=Love

Put that in your browser and you’ll see an XML document is returned. It’s in Apple’s favoured XML format and it looks like there is a URL in there that can be used to retrieve the album artwork. Unfortunately, plugging that URL into your browser won’t return the image… At this point I kind of lost interest because I didn’t actually have any use for getting hold of album artwork (unless I wanted to automate the process for iTunes but I’m not that anal about getting artwork). But I did have a bit of a look round the web and found these two articles on doing the same thing. And it would appear Apple are pretty keen on people not downloading artwork via their own code. Dunnow why, copyright issues I guess, but it looks like even if it is possible to hack the system, Apple will change the way it works to stop your code working.

If you do want to download artwork, I suspect Amazon Web Services is going to be a better approach.

Saturday, February 07, 2009

How to confuse IE with a 302 redirect

It’s very simple, create a PHP pages called test.php, the contents of which are

<?php
  header("Location: test.php");
  exit;
?>

Now point IE8 (probably earlier versions of IE as well I’d guess) at the page and watch as it tries in vain to fetch the page. It eventually times out, after trying to fetch the same page over 1000 times (take a look with Fiddler to see the problem). FireFox and Chrome are much more sensible in this scenario and give up quite soon. As the dumb developer who caused this problem, it took me quite some time to figure out my redirect wasn’t working rather than the website being very ill

WPF ASCII grid part 2

This is the second in a series where I try to learn how to develop WPF apps. The first part is here.

So my next step was to put all the ASCII grid code into a custom control. My first attempt was to inherit from Grid and add the logic to create the cells in the inherited class. The problem with this approach was that the grid’s row and column definitions could be edited in Visual Studio which I didn’t want. So I decided to inherit from Panel and add the grid as a child control. When I did that, running the application showed up nothing at all. I finally realised that was the wrong approach, since the Panel class is designed to allow the end user to add their own child controls. I guess the WPF runtime is looking at the XAML to see which children should be added to the panel and there aren’t any. So finally I inherited from Control and then had to figure out how to add the grid as a child. Control doesn’t have a Children property so it’s not obvious how to add your own child controls. But it turns out it’s pretty easy to do. You just have to override VisualChildrenCount and GetVisualChild as shown below.

  public class AsciiGrid : Control
  {
    static AsciiGrid()
    {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(AsciiGrid), new FrameworkPropertyMetadata(typeof(AsciiGrid)));
    }

    private Grid grid;
    public AsciiGrid() : base()
    {
      grid = new Grid();

      const int width = 16;
      const int height = 16;
      for (int x = 0; x < width; x++)
      {
        grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), });
      }
      for (int y = 0; y < height; y++)
      {
        grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star), });
      }
      for (int x = 0; x < width; x++)
      {
        for (int y = 0; y < height / 2; y++)
        {
          int asciiValue = ((y * width) + (x + 1));

          // number
          TextBlock rect = new TextBlock();
          rect.Text = asciiValue.ToString();
          rect.SetValue(Grid.RowProperty, y * 2);
          rect.SetValue(Grid.ColumnProperty, x);
          grid.Children.Add(rect);

          // ASCII value
          rect = new TextBlock();
          rect.Text = Convert.ToChar(asciiValue).ToString();
          rect.SetValue(Grid.RowProperty, (y * 2) + 1);
          rect.SetValue(Grid.ColumnProperty, x);
          grid.Children.Add(rect);
        }
      }
    }

    protected override int VisualChildrenCount
    {
      get
      {
        return 1;
      }
    }

    protected override Visual GetVisualChild(int index)
    {
      return grid;
    }
  }
So I now have a standalone control in my application. The application looks exactly as it did before but I’ve now got an exceedingly useful re-usable ASCII grid control. OK, maybe not so useful, but this is a learning experience, so cut me some slack. The only thing to note is the changes required to the XAML to host the control, which looks like this.
<Window x:Class="Ascii.AsciiWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:Ascii="clr-namespace:Ascii"    
    Title="Ascii" Height="370" Width="413" Loaded="Window_Loaded">
    <Ascii:AsciiGrid x:Name="m_Grid">
    </Ascii:AsciiGrid>
</Window>

WPF ASCII grid part 1

Ascii

I thought it was about time I learned about WPF so thought I’d start with a very simple application, a grid showing the ASCII characters. It’s kind of pointless at the moment since you can find this information on the web pretty easily but I think I can make it somewhat more powerful and in the process learn more about WPF. This is what I’d like to add in the future and will hopefully blog about as I implement them

          • Turn the grid into a control
          • Show the extended ASCII characters
          • Make it look much sexier
          • Let the user choose the font
          • Let the user change the code page

The code currently looks like this. It’s all pretty straighforward. The first thing to note is the GridUnitType.Star enumerated value which means each column and row will be spaced equally in the window.

The other thing to note is the weird way the text blocks are assigned to the correct cells of the grid. It doesn’t seem a natural way to do it, but I guess once you know that’s how it’s done, it’s pretty straightforward.

    public AsciiWindow()
    {
      InitializeComponent();
      BindGrid();
    }

    private void BindGrid() 
    { 
      const int width = 16;
      const int height = 16;
      for (int x = 0; x < width; x++) 
      { 
        m_Grid.ColumnDefinitions.Add(new ColumnDefinition() 
        { Width = new GridLength(1, GridUnitType.Star), }); 
      }
      for (int y = 0; y < height; y++) 
      { m_Grid.RowDefinitions.Add(new RowDefinition() 
        { Height = new GridLength(1, GridUnitType.Star), }); 
      }
      for (int x = 0; x < width; x++) 
      {
        for (int y = 0; y < height/2; y++) 
        {  
          int asciiValue = ((y*width)+(x+1));

          // number
          TextBlock rect = new TextBlock();
          rect.Text = asciiValue.ToString();
          rect.SetValue(Grid.RowProperty, y*2); 
          rect.SetValue(Grid.ColumnProperty, x); 
          m_Grid.Children.Add(rect); 

          // ASCII value
          rect = new TextBlock();
          rect.Text = Convert.ToChar(asciiValue).ToString();
          rect.SetValue(Grid.RowProperty, (y * 2)+1);
          rect.SetValue(Grid.ColumnProperty, x);
          m_Grid.Children.Add(rect); 
        } 
      } 
    }

Read part 2

Wednesday, February 04, 2009

Bugs = complexity

Many moons ago I discovered a bug in some software I use on a fairly regular basis (I won’t tell you which software since it isn’t relevant to the story and I don’t want this to appear to be a critique of the company or their development process, though you can probably figure out who it is if you look round the rest of this site). The application allows you to write server scripts in JScript.NET. It also does some validation of these scripts but in certain circumstances this validation incorrectly flags up problems with scripts that aren’t actually problems. It was a fairly innocuous bug so I reported it but didn’t push for it to be fixed.

Fast forward a year or so and a new version of the software comes out with a new feature that validates your scripts when you try to deploy a project to the server. Generally a useful feature except the previous bug is still there. Meaning I now can’t deploy perfectly valid projects due to the interaction of the previous bug with this new feature. So a minor unfixed bug has blown up into a major issue.

Which got me thinking. The kind of bugs that don’t get fixed are these kind of things. They only occur in particular rare scenarios. If they happened all the time, the chances are they would get fixed, if they are serious enough. But they do add complexity to the product and testing. No longer can we assume doing A will cause B to happen. Most of the time it will be true but occasionally doing A will cause C to happen. So any testing of new features will have to take this into account. In fact, testing of any new feature will have to take into account any unfixed bugs that may impact the new functionality.

There are many reasons for trying to fix as many bugs as possible (keeping customers happy, trying to fight the constant entropy inherent in software development), may I add this to the list? 

Tuesday, February 03, 2009

Backups

My backup strategy over the last few years has been pretty lame. Every month, Outlook reminds me I should do a backup of my source and I burn a CD. This kind of worked for a while but I’ve been getting more and more nervous about it. Am I sure I’m backing up everything I need to? Most of my email is stored on the web in GMail but there’s heaps of other things on my PC that may be vital but I just haven’t realised it yet. Not only that, but I was getting to the stage where a single CD wasn’t enough and the time taken to burn even that single CD was starting to bore me.

So today when I popped into Maplin for a USB cable I thought I’d have a look at the external hard drives. The Toshiba Stor E looked like the best bang for buck, 500GB for £65. So far I’m impressed. It looks pretty robust, with an aluminium case and no pointless bling. Installation was exceedingly straightforward. Plug it in and Vista recognised it immediately. Then simply configure Vista to do an automatic backup every week and that’s it.

Admittedly my first backup is currently happening and it’s not super fast, but I guess that will improve once it’s done the first full backup. Once it’s finished I’ll have to check that it’s actually backed up everything I want it to, since the backup utility is pretty vague about what it’s going to do. And then I’ll have to think about taking my backup offsite, which for me means carrying the drive into the house. If my shed and house burn down, I’ll have bigger worries than having a decent backup. 

Sunday, February 01, 2009

Dan le Sac vs Scroobius Pip "Thou Shalt always Kill"

I just love this. It’s funny, has a great beat and what a beard!

One of the problems with working from home

However much it snows this evening, I can’t call the office in the morning claiming the weather is too bad for me to get to work.