Thursday, November 12, 2009

General rules of organizing music files into libraries?

 

I was trying to organize folders with mp3 files on my PC in a logical tree structure. Something like that

Artist_1
  FolderWithSongs_1
    song1.mp3
    song2.mp3
  Folder_2
    SubFolder_3
      song3.mp3
      song4.mp3
    Subfolder_4

Event_3
  Artist_2
    song10.mp3
    song11.mp3
  Artist_55

. . . .

Sometimes, there are several Albums belonging to the same Artist.
Sometimes there is an Event (Concert) on which several Artists perform.
It's OK to have two folders with the same name located in different nodes of hierarchy.

Such hierarchical structure works well on a PC, but on Android device it is quite different.

If I understand it correctly, Android treats each folder as an album. It also recognizes tags of mp3 files and reads album and other information from those tags. And obviously, Music players on Android do not present music library as a hierarchical structure (a tree). Instead it looks like a flat list of albums.
As a result,a nice and complicated hierarchy of folders with mp3 files, set on my PC + tag information embedded into mp3 files create a mess on Android, with many albums basically pointing to the same songs.
Also, having two folders (albums?) with the same name presents a problem - how to distinguish them?

I suspect that on Android I should use some flat folder structure (no folders inside other folders)...
Should folder names always be the same as names of albums contained in them? MediaMonkey seems to suggest folder names which are combinations of album names + artist names.

If folder structure in a media library on PC is hierarchical and different from a flat folder structure on Android device, how to synchronize them?

Basically, are there general rules of organizing music files into libraries, so that it is easy and convenient to use on Android (and other portable devices? I cannot figure it out :(

Wednesday, November 04, 2009

A problem with Music Player on Android Dev Phone 1: not indexing mp3 files

 

I found a solution for this Android bug on a Russian-speaking Google Wave devoted to Android! By the way, I encourage everybody to join Google Wave ASAP (no, I already used all my invitations).
A solution, or should I say - a workaround? - is to use Meridian Player http://sites.google.com/site/eternalsandbox/Home instead of Android's own Music Player. Meridian Player allows to forcibly re-scan media files.
As I was told on Meridian's forum, "Yes, it is an Android's media scanner issue, and I also don't know what's the actual behavior of the auto scanning. Before 1.1 it will do a full scan each time replugging SD card, but now it does not. Even manually invoke (by Meridian) sometimes fail...Hope they can fix this soon."
http://groups.google.com/group/meridian_android/browse_thread/thread/d3da70a557f1d545?hl=en

I wonder why Meridian developers know that, while Google Android developers do not.

Tuesday, November 03, 2009

How to install missing LaserJet 4MPlus driver on Windows 7

 

I found on HP forum site the following advice:

The Laserjet 4M drivers (and many others)  are actually available through the Windows Update process.  Try the following:  go to the Printers folder, select Add a Printer, select the appropriate port, then when the "Chose a Printer Model" dialog comes up select "Windows Update". 

Unfortunately, there was one strange Windows feature or probably a bug... as it always happens with Windows. A first bug I discovered in Windows 7, which is actually much better than its predecessors.

When I tried to installed my LaserJet 4MPlus network printer on Win 7 64 bit by clicking Add Printer, as you described above, there was NO Windows Update button visible. Finally, I selected an incorrect printer model and installed that printer driver. After doing it, I right-clicked on a printer, chose Printer Properties => Advanced => New Driver and ... what a miracle: Windows Update button suddenly appeared!

If you ask me how did I find this way, I would answer: a long practice working with a buggy Windows software.

Saturday, October 24, 2009

It’s a time for big new things

I actually wrote this (well, almost) message using AndroBlogger application (by Russian team from MFTI) on my beautiful Android Dev Phone 1 (i.e. HTC G1 “Dream”), but when I hit “Send” AndroBlogger crashed…  Despite this, Android is just beautiful, learning it is exciting. I’m easily connected to most social networks there, starting from Facebook and finishing with Russian friends net on Vkontakte.ru. And sure, Gmail, Contacts, YouTube, Google Voice are integrated and work perfectly. I had some problems with Android Music Player, which didn’t want index music files on a SD card. I didn’t find any info on Google, but help finally came from… people on Russian Google Wave devoted to Android.

I’m waiting for Acer AOD250-1613 10.1-Inch Black Android/XP Netbook to come from Amazon. Then, life will become even more interesting.

Google Wave is another exciting story. Sure, it’s an early alpha, but I managed to get invitation and play with it more and more.

And at this time I installed Windows 7 Pro 64 bit edition on my another computer. Installation was really smooth and so far I like it very much. The only driver I couldn’t find so far is for my ancient HP LaserJet 4M Plus. 

Tuesday, September 01, 2009

How to upgrade Android DevPhone 1 to Android 1.6

I was struggling against my Android phone recently… While HTC instruction was pretty clear, I couldn’t understand how to “Reboot the device into recovery mode by holding down the HOME key during reboot”. I was under impression, that that one has to hold HOME key during a shut up, not during powering phone up. Luckily, I found a correct answer here (hold HOME during powering a device.)

After successful upgrade, my DevPhone showed a message that all the custom data will be wiped out if I press a Send key, otherwise upgrade won’t be installed. So, it was necessary to set up my phone for AT&T access once again.

Tuesday, June 02, 2009

Classic ASP.NET: improper abstractions and ruined REST

http://herdingcode.com/?p=183

1. No one ever anywhere answered the simple question: how to avoid POST operations in a classic ASP.NET when GET operations should be used instead according to a common sense and REST.
POST - for changing data, GET - for reading. No one found any decent way to avoid "Web page was expired"  messages resulting from improper usage of POST. No way to PRG.

To me, this fact alone makes “classic” ASP.NET’s Web Forms approach inappropriate.

2. Yes you can find a workaround for anything, but you’re ending up battling against a framework rather than using it most of the time. And maybe even worse: you’re battling against MS tutorials and books which teach you that ASP.NET-in-24-hours-dataset-no-custom-code-monolithic development.

3. It’s pretty obvious to me, that event-driven model moved from Windows desktop development to Web does not correspond to Request/Response nature of Web and makes programming much more complicated, than even with a plain old ASP. I’d be pretty happy to have lain ASP + C# 3.5 + Intellisense, and believe me, my code would be at the same time more user-friendly and better structured than monstrous code-behind of those ugly master/detail ASP.NET pages.

4. I have nothing against Http Modules, Handlers, etc. They are powerful tools.
But I personally hate Web Forms so much, I think that all those words about Web Forms better in one situations and MVC in another is just a precaution: people understand that MVC is better but are afraid to talk.

Finally, everything is already said in this article and all the comments below.

Monday, June 01, 2009

“Mega” menu? Is it like almost unusable Office 2007 menu?

Usability guru Jakob Nielsen thinks that “mega” menus are good. But is it something similar to Office 2007’s “ribbon” menu?

Office 2007 menu is awful. It's a major step back from a standard and simple Office 2003 menu. Really hard to find what you need, you never sure which main menu bar link to click. My daughter told me to uninstall Office 2007 from her machine because she cannot find anything. If "mega" menu is something like that, I strongly disagree with Jakob Nielsen. The less pictures and other unnecessary graphical elements are in a menu - the better it is.

Wednesday, May 06, 2009

Rob Conery: I Suppose I’ll Just Say It: You Should Learn MVC

http://blog.wekeroad.com/blog/i-spose-ill-just-say-it-you-should-learn-mvc/

Comments under this article are as interesting as article itself.
I only hope I’ll be allowed to write my next ASP.NET project in ASP.NET MVC. I already bought Rob’s book.

Wednesday, February 11, 2009

Write deep Clone(). Forget about ICloneable.

I was chatting with my co-worker about implementing Clone() method for our hierarchy of classes. It's not easy to implement interfaces (think about ICloneable) for class hierarchies. Some tips might be found in Implementing Interfaces at C# Online.NET article, in Implementing Interfaces: ICloneable and IComparable article, and in Advantages of ICloneable? discussion.
As Zach said, it's easier just to implement a virtual Clone() method in a base class and to override it in derived classes as necessary.

I started to look for information about ICloneable and found the following quite unequivocal guidelines:

Caution. Avoid implementing ICloneable. As alarming as that sounds, Microsoft is actually making this recommendation. The problem stems from the fact that the contract doesn’t specify whether the copy should be deep or shallow. In fact, as noted in Krzysztof Cwalina and Brad Abrams’ Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries (Boston, MA: Addison-Wesley Professional, 2005), Cwalina searched the entire code base of the .NET Framework and couldn’t find any code that uses ICloneable. Had the Framework designers and developers been using this interface, they probably would have stumbled across the omission in the ICloneable specification and fixed it.
However, this recommendation is not to say that you shouldn’t implement a Clone method if you need one. If your class needs a clone method, you can still implement one on the public contract of the class without actually implementing ICloneable.

Accelerated C# 2008

Because the contract of ICloneable does not specify the type of clone implementation required to satisfy the contract, different classes have different implementations of the interface. Consumers cannot rely on ICloneable to let them know whether an object is deep-copied or not. Therefore, we recommend that ICloneable not be implemented.
The moral of the story is that you should never ship an interface if you don't have both implementations and consumers of the interface. In the case of ICloneable, we did not have consumers when we shipped it. I searched the Framework sources and could not find even one place where we take ICloneable as a parameter.
x DO NOT implement ICloneable.
x DO NOT use ICloneable in public APIs.
x CONSIDER defining the Clone method on types that need a cloning mechanism. Ensure that the documentation clearly states whether it is a deep- or shallow-copy.

Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries

Tuesday, December 30, 2008

Call a method only if a supplied argument is not Null

Suppose you have a C# method which only works correctly if its parameter value is not Null, otherwise it either throws an exception or returns wrong value. Sometimes you cannot guarantee that a parameter value is not Null, because it was passed from outside, was read from DB, etc. Instead of writing your custom code again and again, which checks a parameter value and only calls a method if it is not Null, it may be more convenient to re-use a common helper method. Overloaded CallIfArgumentNotNull() methods shown below are such helpers. I was somehow inspired by reading this article by Jon Skeet (lazy evaluation) .

    // If a first argument of type int? is not Null, a supplied method (second argument)
    // is called with a first argument passed in and its return value is returned.
    // If a first argument is Null, a default(T) is returned
    // (null for reference types, 0 from Integer, etc.)
    public static T CallIfArgumentNotNull<T>(int? arg, Func<int, T> func) {
      return (arg != null) ? func((int)arg) : default(T);
    }
 
    // If a first argument of type int? is not Null, a supplied method (second argument)
    // is called with a first argument passed in and its return value is returned.
    // If a first argument is Null, a third argument value is returned.
    public static T CallIfArgumentNotNull<T>(int? arg, Func<int, T> func, T defResult) {
      return (arg != null) ? func((int)arg) : defResult;
    }
 
    // If a first argument of type A? is not Null, a supplied method (second argument)
    // is called with a first argument passed in and its return value is returned.
    // If a first argument is null, a third argument value is returned.
    public static T CallIfArgumentNotNull<A, T>(Nullable<A> arg, Func<A, T> func, T defResult)
      where A : struct {
      return (arg != null) ? func((A)(arg)) : defResult;
    }