25 September 2012

Video screensaver

On my old XP pc I used to have a video screensaver, where I could enter a list of filenames of movies that then would be played on all connected monitors. Very cool! I used to collect all the trailers of CG movies I could get and use that list for the screensaver.

It's not the one I used, but apparently microsoft even made an official video screensaver (for XP). Now on windows 7 I'd like the same, and it should be possible according to this site. I tried but failed to accomplish this with the "windows live essentials".

So I wrote one myself. It turns out that a windows screensaver is very easy to write. I also messed around with various video playing methods in C#, using directx or directshow but none of them were as easy as using a simple media element from the WPF. Since I wrote this for .Net 3.5 that functionality is available.

Only downside to the media element is that it's not easy to synchronize them, so there is a small difference in the starting point of the movies on all screens. But most of the time it is small enough to ignore. It's something that I still want to fix so I might write an update on this post.

If you like you can download it here. The configuration is simple: turn on or off the audio, and provide a folder where to look for files. It only searches for .mov, .avi and .wmv files and does not search recursively. It could use some extra testing so if you run into trouble, you know how to find me :)

Installation: unzip the scr file to a location you like, right-click it and select 'Install'. And you need the .Net 3.5 framework of course.

Edit:

I uploaded an update with some bugfixes: the screensaver used to crash if you specified an empty path to search for videos, and there was an issue with the media element on my and steven's laptop if our extra monitor was connected. It is a known issue with Microsoft but it seems they do not bother to fix it. Luckily there is a workaround.

Edit 2:

By request, here is the link to the git repository I've set up. I converted the project to a vs 2012 solution; somehow I don't have the small sync issue anymore, but I suspect that this is because of my newer graphics card that I have in the meantime.

05 September 2012

ccnet 1.8.* and powershell

Two weeks ago I finally got my Windows Server 2008 R2! Hurray! I can now start on my buildserver for all the projects that I'm working on.

It cannot be over-emphasized how important it is to have a buildserver for your project. In fact, it is even an item in the c++ coding standards book: "Use an automated build system"
Some people ask me what the use is of a buildserver, and I answer them: "Do you want to take the responsibility to release a product that has not been build by a buildserver? Do you want to release a build that has been put together manually by somebody of the team, in the hope he remembers to take all the right steps, that he is completely in sync with the cvs, without locally changed files? Or even worse, say you want to release a second version, this time another person must do the build (the first one is on holliday), are you sure he knows all the steps, that he is in sync and that he has the correct compiler installed?"

This is only one reason why you'd use a buildserver, I can think of many more. Even for a small project, that only you yourself work on, it is good to let the buildserver build it. One reason (there are more): small one-person projects tend to become bigger projects and attract more developers and before you know it there is a small team working on it, or it is used in a bigger project. I've seen this happen more often than not.

But that's not the topic that I want to write about. For years I've been using ccnet, an open source, .Net based build server. Extremely easy to use, very versatile.
Recently the latest version 1.8.0 was released so I installed it on my new server. I haven't had the time yet to review the new features because I need my projects up and running fast.

One of the important features I always use is the assembly version labeller, which for me looks like:

<labeller type="assemblyVersionLabeller">
<major>1</major>
<minor>2</minor>
<incrementOnFailure>false</incrementOnFailure>
</labeller>

In combination with perforce this gives me a version number as an environment variable that looks like 1.2.{buildnumber}.{versionnumber}. From that number I know what build it was, and with what version on perforce it was build. With this number it is key to incorporate it as mush as possible in the application; in the installer, in the exe, in the assemblies, etc. Because with this information, if your application is in the field and you start receiving bugs and feedback, you always know exactly about which version people are talking, you know exactly with what files that exe was build that had a specific error, you know when they fucked up and when you did. It's something I've learned from dire experience at Larian. There were a lot of versions of Divinity II made and the first ones did not have a good version number, which made it impossible to track bugs and user's versions.

So for C# exe's and assemblies I use this powershell script:

$version = [environment]::GetEnvironmentVariable("CCNetLabel","Process")
foreach($arg in $args)
{
$file = [System.IO.Path]::Combine($arg, "Properties\AssemblyInfo.cs")
$old = "`"[0-9]+.\s?[0-9]+.\s?[0-9]+.\s?[0-9]+`""
$new = "`"" + $version + "`""
(Get-Content $file) | % {$_ -Replace $old , $new} | Set-Content -Path $file
}

As argument you give it the folder of your assembly, and it will change the version numbers to the ccnet label version number. This needs to be done before the devenv task and the result is an assembly or exe with correct version numbers if you look at the details of the file. This is extremely convenient to ask a user what version of a certain file they have, or to check yourself what version you're using.

And then hell started for me, somehow the script that I've used on several other ccnet servers, didn't work on the new one. I had the executing policy correct (even for 64bit Windows) which is the common pitfall, but no luck.
To make a long story short: the 1.8.0 and 1.8.1 version of ccnet place the arguments for your script before your script instead of after in the command line, a typo I guess. Luckily it is open source so you can easily create a quick fix until it is fixed in a new version (it really is easy, the source compiles right out of the zip).

But what I forgot was that the "scriptsDirectory" parameter must be absolute or the task takes the default one (which does not exist for the LocalSystem user). You'd expect that you can give a relative path as in all other ccnet tasks, but not for the powershell task. Apparently this is a bug that's always been in there, but I forgot. I looked in the source to fix it but it appears te be a little more tricky than I imagined.

In any case, you're warned now, and you can follow this thread on the ccnet user group if you'd like to know if it gets resolved. There's also some more info there.