Monday, September 14, 2009

PostgreSQL and phpPgAdmin on Ubuntu Server

I was struggling to get the phpPgAdmin application to work on a virtual machine running Ubuntu 9.04 today. As it turns out phpPgAdmin's default installation is by default targeted at desktop environments which is by all intents and purposes stupid (to say the least).

So what's so "desktop-ish" about it? Well as it turns out the default configuration accepts connections from localhost only which is completely unusable in a server-like environment with no graphical environment and no web browser whatsoever.

The default behavior also manifests itself in a very non-verbose manner. At first the log entry

"GET /pgphpadmin HTTP/1.1" 403 268

is not saying very much. It'd be better if the error message said something more verbose and direct the user to change the access rules or better yet to have a configuration step during installation that asks for this rather than to have poke around some configuration files.

To change it's default behavior one has to edit the file /etc/apache2/conf.d/phppgadmin (which is a symbolic link to /etc/phppgadmin/apache.conf) and change the default access policy from 127.0.0.1/255.0.0.0 ::1/128 to all.
To do that simply comment out the line that reads

allow from 127.0.0.1/255.0.0.0 ::1/128

and remove the comment from one line below that reads

allow from all

That does the trick. Of course that opens the ability to connect to this server from the outside world, but since this is a server installation it's not uncommon to access it from far far away, is it?


Happy hunting!

Thursday, September 10, 2009

The size does not matter

I've just finished a very inspiring conversation with a friend of mine and I want to share the outcome with the rest of you.

So it started quite innocent. He talked how he liked the Flex framework with some server-side code, I talked about the discovery of Apache Wicket... Just a normal conversation between 2 fellow programmers.

Then after some time he expressed his bad feeling about dynamic languages and all. Well, I've asked if he'd like to see the waves of a WiFi transmitter where he immediately replayed that he ain't got a microscope laying around....

At that time it was quite obvious that he thinks of them as something that really is there. That they are something he can take for granted. That's an assumption even if on a very theoretical level. He made an assumption and to that end he expressed his behavior as dynamic.

This fact lead to a conclusion that human beings are in fact in their nature more suited to the dynamic part of programming languages than anything else. We choose to think about programming as a very static thing whereas it is completely dynamic in its very nature. We can never predict what the user will give for an input to our carefully design form, do we? We can never predict what kind of weather condition will be fed to our application's flight planning routine - it's just a wild guess that we can cope with all of that.

On a more structural level it's a lot better to define the actual interface required for the part in question to work as expected than to say that this part must definitely be of some special type. Hell, the duck and a canary are birds and are similar in a lot of different ways. Did they evolve from the same species? Maybe yes but, on the other hand, maybe not. The fact remains the same that we can talk about the wings of a duck as well as of the wings of a canary and we all know that they move more-less up and down to create some lift to allow the bird to fly!

At the end of the day both ideas (the static and the dynamic one) have their advantages and disadvantages. It's just takes the openness of one's mind to realize the similarities and advantages of both solution to pick the right one for the job.

Happy hunting!

Sunday, August 30, 2009

Re-encoding AVCHD video using FFMpeg

There's been some changes to how ffmpeg operates starting from revision 19459 and simply pointing out the input and output files with libx264 will not do the trick anymore. This is due to the fact that ffmpeg now recognizes the subtitles track and doesn't know how to deal with it in the resulting MKV file. To overcome this issue add the -sn to the parameters and you're done.

Also some of the x264 options don't have working default values so one must specify the preset for video encoding. Here's an example:

ffmpeg.bat -i 00001.MTS -acodec aac -ac 2 -ab 128k -sn -vcodec libx264 -deinterlace -s 1280x720 -vpre ./libx264-hq.ffpreset -crf 23 -threads 2 00001.mkv

To make it work make sure you've copied the libx264-hq.ffpreset file from ffmpeg archive into the folder with your MTS file to be re-encoded.

Also you can adjust the -crf 23 parameter to steer the final size and quality of the resulting MKV file.

Enjoy!

Joining MTS files (AVCHD)

I've been looking for a long time to find out how to join 2 consecutive MTS files from my Sony SR-11 camera. The case is simple: re-encode the recorded material into a smaller resolution and/or DVD format.

If you'd just take all the files the camera spitted out and join them afterwards a number of issues would emerge: jittered frames at the splitting points, audio desynchronization - you name it.

The solution couldn't be simplier but it was nowhere to be found directly on the net (google could have done a better job this time):

copy /b 00001.MTS + 00002.MTS + 00003.MTS output.mts

This example will join the files 00001.MTS, 00002.MTS, 00003.MTS into output.mts without doing any re-encoding, loosing synchronization or anything like that. And it's doing it extremly fast.

Enjoy!

Thursday, July 30, 2009

NHibernate and ASP.NET - UpdateModel problem

Using NHibernate as a persistence layer is fun. Not only does it hide the complexity of a database completly but also allows one to use an object model instead of playing around with database query results.
In the case of NHibernate it's even better as it provides session management for web applications so with minimum effort you can just use lazy loading from within your views very easily.

At some point though problems will emerge. One of them is using ISession.Get without specifying the type (which might be unknown at the time of querying or might depend on the actual request from the page) with Controller.UpdateModel method. Here's how it goes:

1. UpdateModel is a generic method that expects the actual type that's being mapped to as the generic parameter.
2. It then passes the processing to TryUpdateModel which is a generic method as well.
3. TryUpdateModel takes this generic parameter, retrieves it's type metadata and uses it (among other things) to fill in a ModelBindingContext structure.
4. This ModelBindingContext is then passed on to IModelBinder.BindModel method.

It's all nice and dandy if we can specify the model's type. But if we don't know the actual type it results in processing of a model of type Object and none of the properties will get mapped. Because of the fact that there's no specialized model binder for type Object it gets passed on to the DefaultModelBinder implementation held by ModelBinders.Binders.DefaultBinder.

There's however an extremly nice and easy solution to this. We're going to use the decorator pattern to wrap up the current default model binder and provide it with the necessary information from NHibernate's ISessionFactory.

Here's an example implementation of such a model binder that can provide this additional implementation. I've called it NHibernateAwareModelBinder.


public class NHibernateAwareModelBinder : IModelBinder
{
private readonly ICollection mappedClasses;
private readonly IModelBinder defaultModelBinder;

public NHibernateAwareModelBinder(
ICollection mappedClasses,
IModelBinder defaultModelBinder)
{
this.mappedClasses = mappedClasses;
this.defaultModelBinder = defaultModelBinder;
}

public object BindModel(
ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
if (bindingContext.Model != null)
{
string modelType = bindingContext.Model
.GetType().FullName;
if (mappedClasses.Contains(modelType))
{
bindingContext.ModelType =
Type.GetType(modelType);
}
}
return defaultModelBinder.BindModel(
controllerContext,
bindingContext);
}
}

And here's how you'd use this class in your Application_Start event:

ModelBinders.Binders.DefaultBinder =
new NHibernateAwareModelBinder(
SessionFactory.GetAllClassMetadata().Keys,
ModelBinders.Binders.DefaultBinder);

As you can see we're using the current default model binder as the actual binder but we're decorating it's behavior with type resolution. Nice, isn't it?

Have fun!

Saturday, July 11, 2009

Localizing ASP.NET pages using resources

Localizing ASP.NET pages using resource files is an easy thing to do. It requires just a few steps to get everything up and running but all of those steps have to be completed because otherwise it will not work.

  • Set the UICulture and Culture attributes on a page to "Auto"
  • Create an ASP.NET folder named App_LocalResources
  • In App_LocalResources create a resource file using the following pattern:
page.ext.lang-variant.resx

for example:

Default.aspx, en-us -> Default.aspx.en-us.resx
Default.aspx, pl -> Default.aspx.pl.resx

  • On the element that needs localization set the attribute meta:resourcekey to something meaningful, for example:

<asp:Label ID="LblText" Text="Hello, world!" runat="server" />

becomes

<asp:Label ID="LblText" Text="Hello, world!" meta:resourcekey="LblText" runat="server" />

  • Add resource key for the property to modify using the following pattern:

resourcekey.property

for example:

LblText.Text

  • DO NOT FORGET TO REBUILD AND RE-RUN THE APPLICATION!


Here's a complete and working solution for you to play around

ASP.NET-Localization.zip

Have fun!

Thursday, June 11, 2009

StyleCop and FxCop integration in VS 2008 Express

Recently I took interest in improving the quality of the applications I write by forcing them to be checked by StyleCop and FxCop during the build.

StyleCop was really easy to implement - just one line, well documented, nothing one would struggle with:

1. Install StyleCop using MSI installer
2. Add the following line to your project right after the line that imports C# tasks (by default it's nearly at the end of the project file!):

<Import Project="$(ProgramFiles)\MSBuild\Microsoft\StyleCop\v4.3\Microsoft.StyleCop.targets" />

FxCop on the other hand wasn't so easy to find out but it was just as easy to manage:

1. Install FxCop using MSI installer
2. Add the following task to <AfterBuild> target:

<Exec Command='"$(ProgramFiles)\Microsoft FxCop 1.36\FxCopCmd.exe" /file:"$(TargetPath)" /console'/>

That's it. Alternatively you could just add a post-build event using project options editor. This event would then look like that:

"%ProgramFiles%\Microsoft FxCop 1.36\FxCopCmd.exe" /file:"$(TargetPath)" /console

Pretty easy, ain't it?

Here you have a ready-to-check example of the above.

FxCop+StyleCop-example.zip

Enjoy!