XMLpitstop.com   |  VBnetexpert.com   |  Community Credit  
 
 
Pitstop Search:  
in
 
Sign in | Join | Help
 
 
  Blog
    Home  
 
  Entries By Date
 
<March 2008>
SunMonTueWedThuFriSat
2425262728291
2345678
9101112131415
16171819202122
23242526272829
303112345
 
 
  Blog Categories
   
 
  Archives
    August 2008 (1)  
    June 2008 (4)  
    May 2008 (2)  
    April 2008 (3)  
    March 2008 (3)  
    February 2008 (5)  
    December 2007 (4)  
    November 2007 (1)  
    October 2007 (3)  
 
  Syndication
    RSS  
    Atom  
    Comments RSS  

March 2008 - Posts

  .NET Flea Market  
 

The Zune Application is Guilty of Flash over Function. Kick It.

Don't get me wrong, I love the Zune, but the new interface is beautiful to a fault. Like Beauty and the Geek, it's nice to look at, but you can't really hold a conversation with it. It's like it's always in the bathroom fixing its hair or makeup. I was doing more poking around the Zune files and I found some command-line options to try. The most interesting one disables the DirectX effects and should make the UI a lot snappier for those that just don't have the horsepower or the desire for a really flashy interface. I think I know who you are.

The command-line options I found:

  • -animations:(true|false) Enable or disable fading effects.
  • -gdi Use GDI instead of DirectX, seems to disable animations and probably give some legacy support. This is mentioned in the Zune 2.3 release notes.
  • -switchtogdi Permanently switch to GDI rendering. makes registry entry change in general settings: HKEY_CURRENT_USER\Software\Microsoft\Zune\GeneralSettings\UseGDI=1
  • -dx9 Use DirectX9 compatibility? Probably.
  • -direction:(rtl|ltr) Use Right-to-Left rendering for languages that require it.

So for example, you want to start by disabling the fancy slide and fade animations to see what effect that has. Create a shortcut to the Zune.exe file, edit the properties of the shortcut and add -animations:false to the end of the command line.

That was nice, but you still have some issues, so you want to drop DirectX and go with a straight GDI application. I don't know much about Vista, but I have a nagging thought that Vista did away with GDI, so if you're on Vista, I don't know what will happen. So you create the shortcut and add -gdi to the end of the command line.

You want to mess around with some of the other settings (which I don't really see as valuable)? Go ahead, knock yourself and your computer out.

 
 
 
 

Workplace Cruelty

Back in a previous job, we had technical interviews for prospective employees. I went through one myself and it was tough. I was sure I bombed it, because one guy found a weak spot in my knowledge and kept drilling into it. As it turns out, I did ok and they hired me.

In a year's time I had climbed the ranks and suddenly found myself doing technical interviews on the other side of the desk. One of the things that I was tasked with was writing better technical questions for .NET programmers and analysts. I and the coder types I gathered with at work all pitched in make a great tech interview to be given over the phone before bringing in the candidate for a face-to-face.

Once I started doing the interviews, I discovered just how poor the pool of available talent was. I guess it might have been more a reflection on the headhunters sending us the candidates. But sometimes I thought I was asking a little much with some of the questions. I'm not going to divulge the questions, but I want to discuss one of them because it is pretty interesting. It's also the most devious. I only found one person who could answer it correctly. And to be fair, I couldn't have answered it myself.

And by the way, if you have the opportunity to cheat on a phone interview. For example, someone you know inside the company finds the document containing all the questions and answers and distributes it to your consulting company or just to friends. Don't be an idiot. We know when you are cheating. I had one case of blatant cheating where the answers given back to me were nearly word for word what was in my Q&A spreadsheet. The sad part was, we brought the person in for a face-to-face interview and asked questions from an alternate question pool (one that wasn't in a document on the network) and her skills were fine. She didn't even need to cheat.

But anyways, the trick question. The question was asking the difference between ByVal and ByRef and how they apply to classes and structures. There is a difference and those that didn't know it but tried to be confident when giving their answers were completely demoralized when asked to describe the difference.

If you've done any MCSA/MCSD certification training, you may recall this topic is discussed. I remember it from my training, but I also remember thinking at the time "who cares?" It can have consequences if you don't pay attention to it. It'd probably be one of those bugs that after days of research you'd share with your peers: "Hey, did you know..."

So here's the trick: There is no ByVal when you are passing a class to a method. There is only ByRef. So if you pass a class to a method using ByVal, you are working on the original class, not a copy. If you pass a structure to a class ByVal, you are working on a copy. You can pass a structure ByRef and you will work on the original.

Why? Because of the way .NET allocates memory. There is the Stack and the Heap. The Stack is small and efficient, the Heap is big and disorganized. but the Heap can hold lots of stuff. The stack is reserved for value types - small data structures like Booleans and Integers - while the Heap holds big things like Strings and Classes. A Structure is a value type even though it can have properties and methods like a class. A class is an Object type, and all objects go on the heap.

Since classes are big, when you pass a class to a method, it only sends a pointer to the class of where the instance of the class is on the heap, AKA, a reference, By Reference, ByRef, even though it says ByVal, it's not true.

But, but, what if a class has a structure as a property? And what if a structure has a class as a property? When does it reference it and when does it copy it? Well, let's see.

Make a class and a structure with the opposite inside each:

Public Class WithStruct
    Public struct As InsideStructure
    Public text As String
    Public number As Integer

    Public Structure InsideStructure
        Public text As String
        Public number As Integer
    End Structure

End Class

Structure WithClass
	Public cl As WithStruct
	Public text As String
	Public number As Integer
End Structure

Make some methods to modify the guts:

Private Sub ModifyInternals(ByVal obj As WithStruct)
	obj.text = "Modified"
	obj.number = -1
	obj.struct.text = "Inner modified"
	obj.struct.number = -10
End Sub

Private Sub ModifyInternals(ByVal obj As WithClass)
	obj.text = "Modified"
	obj.number = -1
	obj.cl.text = "Inner modified"
	obj.cl.number = -10
End Sub

Make the objects and call them and look at the results:

Structure (before and after):
Text:The text, Number:1, InnerText:Inside text, InnerNumber:10
Text:The text, Number:1, InnerText:Inner modified, InnerNumber:-10

Class (before and after):
Text:The TEXT, Number:2, InnerText:Inside TEXT, InnerNumber:20
Text:Modified, Number:-1, InnerText:Inner modified, InnerNumber:-10

Summary: The structure maintained its original values, but the class inside the structure was modified. The class was modified and so was its internal structure.

Is your head spinning yet? Good.

 
 
 
 

Read the Zune Collection in .NET from Zune's own API

I was installing the latest version of the Zune software and actually read a bit of the license agreement. This line caught my eye:

Distributable Code. The software contains code that you are permitted to distribute in programs you develop if you comply with the terms below.

Oh, really? Programs that I develop? This reinforced a suspicion I had that there was a usable API in the Zune software. And there is. It is ZunedbAPI.dll. I don’t know much about it, but I do know how to read the Zune collection (formerly known as the library). It's as simple as adding a reference to that DLL, found in the Zune program folder. A pre-caveat: There are dependancies with this DLL, so you can either run your custom app in the Zune folder, or you can use trial and error to find out which DLLs are needed. I chose the former out of convenience.

So what are some of the objects you’re going to be dealing with to read the library? There’s the MicrosoftZuneLibrary namespace and in it are some objects you will learn to know:

  • ZuneLibrary
  • ZuneQueryList
  • ZuneQueryItem

ZuneLibrary is the start of everything. But just creating an instance of it will not do anything. You also need to call the Initialize method on it:

Dim zuneLib As ZuneLibrary
zuneLib = New ZuneLibrary
zuneLib.Initialize()

And you MUST clean up after yourself. These objects are very sensitive to being left hanging and when the GC comes along, it’s going to throw up all over your program. So always call Dispose when you are done with it. Never just let it fall out of scope.

So you now have a connection to the Zune collection. The queries are a little bit limiting; there’s nothing free-form about them, but you can use them to get the raw data and work it from there. There are methods like:

  • QueryDatabase
  • GetAlbumsByArtists
  • GetTracksByAlbum
  • GetTracksByPlaylist

And others for you to discover. These methods take some parameters that might need explaining. Once one is explained, you should be able to apply that logic to the others. Let’s look at the first one: QueryDatabase. Its signature is:

Public Function QueryDatabase(ByVal QueryType As EQueryType, 
	ByVal LibraryView As Integer, ByVal SortType As EQuerySortType, 
	ByVal SortAtom As UInteger, 
	ByVal propertyBag As MicrosoftZuneInterop.QueryPropertyBag) 
	As MicrosoftZuneLibrary.ZuneQueryList

The first parameter is an enum. That makes it easy to pick a query type. Look at some of the choices:

  • EQueryType.eQueryTypeAllAlbums
  • EQueryType.eQueryTypeAllPhotos
  • EQueryType.eQueryTypeAllTracks

I’m kind of sticking to these, because the others probably have parameters taht need to be sent in a PropertyBag and I haven’t worked them out yet. So the easy example is to list all albums. Pick the proper enum and continue.

The next parameter is the library view. I’ve not found this to work with anything but zero. Then in the next parameter you specify the sort type. It’s an enum and doesn’t need explanation.

The next to last parameter refers to an “atom”. This is a Uint value for a column. There’s no indication of this, but the atoms are listed in the enum: SchemaMap. The difficult thing is figuring out which atoms apply to which file types. I have a bit of code at the end of this post to help with that.

So you need to choose which column you want to sort by by using the value from the SchemaMap enum. If you pick an atom that isn’t valid, your call will error out. It’s pretty rough. You can always specify zero and it doesn’t seem to care.

Last property is the PropertyBag. This is important for some queries for sure, but I haven’t taken the time to figure out how to instantiate one and put the values into it. So for now, using Nothing is the proper value.

The query will come back into a ZuneQueryList object. Or will be Nothing if the query failed. Like if you set an invalid library view value.

What’s this look like in code? Here’s a query for all artists:

Dim artists As MicrosoftZuneLibrary.ZuneQueryList
artists = zuneLib.QueryDatabase(EQueryType.eQueryTypeAllAlbumArtists, 
	0, EQuerySortType.eQuerySortOrderAscending, 
	CUInt(MicrosoftZuneLibrary.SchemaMap.kiIndex_DisplayArtist), Nothing)

Not bad. Now, how to get at the stuff inside the QueryList? It doesn’t have any Item property. It does have a Count property, so you could loop through it, but how do you get the fields?

The answer is the GetFieldValue function. Let’s see one of its signatures (it’s overloaded):

Public Function GetFieldValue(ByVal index As UInteger, 
    ByVal type As System.Type, ByVal Atom As UInteger) As Object

Seems pretty straightforward, the Index is the index of the item you want, the type is the datatype you expect, and the atom is, well, an atom. Using the SchemaMap enumeration, this is easy.

There is another way to get an item, and that is using the ZuneQueryItem object. You instantiate it using a query list and an index. Once you have a ZuneQueryItem, you can use the GetFieldValue function on it, which has a similar syntax, obviously missing the index parameter.

Let’s see that in code. I have a listbox called lstArtists and a custom class that holds the ID and name of the object (overriding the ToString method to display the name):

For i As Integer = 0 To artists.Count - 1
	lstArtists.Items.Add(CStr(artists.GetFieldValue(CUInt(i), 
		GetType(String), 
		CUInt(MicrosoftZuneLibrary.SchemaMap.kiIndex_DisplayArtist), ""))
Next

Or maybe the other way, when you select an item:

Dim i As MicrosoftZuneLibrary.ZuneQueryItem
i = New MicrosoftZuneLibrary.ZuneQueryItem(artists, lstArtists.SelectedIndex)

That’s it. You can now query the Zune collection! Always be sure to clean up after yourself.

Now, here’s that code that I said is helpful for finding out the atoms on an object. Create a form with a DataGridView and add this method.

Set up your main code to perform a query and get a ZuneQueryItem from the results. Then create the display form and pass that QueryItem to this method.

The method:

Public Sub ShowItem(ByVal i As MicrosoftZuneLibrary.ZuneQueryItem)
    Dim val As String
    
    For Each v As MicrosoftZuneLibrary.SchemaMap In 
    	[Enum].GetValues(GetType(MicrosoftZuneLibrary.SchemaMap))

        val = CStr(i.GetFieldValue(GetType(String), CUInt(v)))
        If val Is Nothing Then val = CStr(i.GetFieldValue(GetType(Date), CUInt(v)))
        If val Is Nothing Then val = CStr(i.GetFieldValue(GetType(Integer), CUInt(v)))
        If val Is Nothing Then val = CStr(i.GetFieldValue(GetType(Guid), CUInt(v)))
        dgFile.Rows.Add([Enum].GetName(GetType(MicrosoftZuneLibrary.SchemaMap), v), val)
    Next

    Me.Show()

End Sub

If anyone finds out anything further about the Zune API, I am found on ZuneBoards. Look me up there.

 
 
 

 
Copyright © . All Rights Reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems