" />

Add to Technorati Favorites



 

...where sanity comes to die.
Visit my blogBlur the lines between genius, insanity, and utter stupidity.WALDOLand Music CentralDevelopment WorkAbout MeContact MeWALDOLand Site Map
 

 Monday, March 24, 2008

Well it's about goddamn time!

I get home and flip on my laptop. I look up and there's an alert from Apple. I have new downloads available. I open the dialog and, voila. Safari version 3.1 (525.13) is ready for download!

Apple finally released a version of Safari for Windows that doesn't crash INSTANTLY!

Yay.

Thank God. It's been months since Apple released a version that didn't crash within 3seconds of starting up. I haven't been able to do successful Safari development or testing in months. That's really great when you're about to release a large scale production website. Uh, we hope it works.

Everybody and their momma would tell Apple about it. Apple would keep releasing Safari like it worked. We'd all fire up Safari and guess what? Same thing.

Apple: "It works now."
    Users: "Uh, no it doesn't."
Apple: "OK, it works now."
    Users: "Uh, no it doesn't."
Apple: "How about now?"
    Users: "Nope. Nothin'. Still broke."
Apple: "Now?"
    Users: "Nada."
Apple: "I said it works. Now leave me alone!"
    Users: "Hello? Is anyone there?"

Labels: , , ,

 Saturday, January 26, 2008

Yet another reason why MySpace Sucks and Facebook Rules

Just the simple fact that the blogs in MySpace can't be cross-posted or imported.

If I write a blog post on this site, I can let Facebook import my XML Feed and blammo, instant cross-post into their Notes feature.

With MySpace, I literally have to manually copy and paste every blog post I write and re-post it in MySpace. For someone who posts regularly, this is an incredible pain in the ass. On top of that, MySpace's wysiwyg editor is complete crap. If I post markup that for example, has a <table> tag in it, MySpace thinks they're clever and scrubs it out and replaces it with bad markup. Their scrubbed markup is not even close to XHTML-compliant (or even HTML-compliant), so I'm limited in what I can actually post to MySpace.

Labels: , , , , ,

Saw this and thought it was awesome

HTML tattooTo all my tech geek friends, you should find this hilarious.

I was surfing the web and stubled across this image of a dude who has HTML markup tatooed on the back of his neck. More specifically, a closing </head> tag, followed by an opening <body> tag.

To quote Desirea, awesome. :)

Labels: , , , ,

 Sunday, December 16, 2007

Facebook vs. MySpace

You know, Facebook kicks so much ass over MySpace.

MySpace is good for a public identity. Like if you're a band or a comic or a celebrity or something and you need a web presence, MySpace is the way to do it. It's a quick way to get a feature-laden web site up for free with built-in publicity. Easy. Simple. Done.

Facebook on the other hand is much better for the personal level of social networking. In stark contrast to MySpace, you're not riddled with random friend requests, otherwise known as MySpace Spam. Friends on Facebook are grouped by their affiliation with you (high school, college, job, etc.) making them much easier to find because they are targeted searches. you will actually have a network of your friends. MySpace is kind of a free-for-all. Any random schmuck will try to be your friend.

Facebook is MUCH cleaner, prettier, more functional than MySpace. MySpace offers its users the ability to customize their layout, but that usually leads to someone putting as much garbage as they can in a layout, which then makes the layout slower, offensive, or non-functional to the casual viewer. When I just want to add you as a friend, I don't want to sit and wait for your layout to load, with your f***ed up graphics and your music player blasting Omarion at me. I just want to add you ass a friend. Some of m best friends on MySpace have the poorest choices in layouts.

Facebook has the ability to add and or design fun web applications which can be installed like plug-ins to a user's profile. This alone creates business/developer/strategic partnerships with Facebook, something MySpace is currently unable to capitalize on.

Facebook is geared much more to Web 2.0. If you don't know or understand what Web 2.0 is, then don't bother reading this section. Rather than having pages laden with large blocky advertisements and javascript errors like MySpace does, Facebook is slick, easy to use, easy to navigate, and takes advantage of those things that should be used when designing in Web 2.0, like AJAX. The bottom line is that Web 2.0 is supposed to be all about the user experience (usability). MySpace is clunky kludgy, hard to use, riddled with errors, and undergoes maintenance nearly every other week, which usually doesn't fix some of its major issues. Facebook on the other hand is clean, cutting edge, feature rich, functional, and very rarely (although I have spotted a few, no question) has errors. Or at least has significantly fewer errors than MySpace.

I've even heard multiple companies (including the one I work for) including Facebook applications as part of their overall product base. How often does that happen? Although, granted a lot of media (TV/Film/Radio/Music/Comedy) includes MySpace as part of publicity campaigns, so I will give them credit for that.

It seems like you could break down your major social networking sites like this:
Professional: LinkedIn
Media/Entertainment: MySpace
Personal: Facebook

Facebook just seems like more of a personal touch to me. Although yes, I will continue to use both, I'm going to begin gravitating more toward Facebook.

Labels: , , , , , , , , , , ,

 Tuesday, December 11, 2007

Most Searched

I was checking Google Analytics and Google Webmaster Tools on Friday and I was presented with a slightly disturbing fact.

The most searched term in Google that produces a top-ranking hit on my site is:

"He-bitch man sex"

Trailing just behind are
  • '09 Camaro
  • Transformers Soundtrack and
  • Harumi Nemoto

Who knew I was so popular among the he-bitch man sex crowd?

Actually I should stop typing that before Google thinks I'm an authority. It's like "My Tivo thinks I'm gay!"

Labels: ,

 Sunday, November 18, 2007

Son of a bitch! It worked!

The goddamn Towel Trick worked! I finally tried that shit on my XBox 360 and it worked! No more Red Ring of Death for me!

Dude, I'm back! I've been playing Call of Duty 3 for the last few hours. I'm so going out and buying Guitar Hero 3 now.

Labels: ,

 Sunday, November 04, 2007

Need to find that receipt

I really need to find that receipt for my XBox 360. I really want to play Ace Combat 6 and Guitar Hero III.

Right now I've still got the Red Ring of Death. The warranty extension from Micro$oft for soldering bullshit parts to the motherboard is still valid so I can still return it but dammit I need that receipt.

Labels: ,

 Tuesday, October 30, 2007

No longer supporting legacy development

As I'm sitting here reinstalling software on my laptop, I've made a decision. In order to save hard drive space, I have decided not to install any Visual Studio 6 components or Visual Studio 2002/2003 components. Therefore I will no longer be supporting any legacy app development. All of my applications that were built with earlier versions of the studio will be ported to Visual Studio 2005 if code was not already developed in parallel. Visual Studio Add-Ins will continue to have backwards compatibility with 2002/2003 versions, but will be built by, deployed by, and targeted to Visual Studio 2005/2008.

Labels: , , , , , , ,

 Sunday, October 28, 2007

Well I fucked up my PC again.

Here I am on a Sunday night, backing up my files from my laptop yet again. I have to reinstall my OS because some shit I installed trashed my Wireless adapter, causing my services (services.exe) to crash every time I boot up. F-Guk! I have another three days of reinstalling software to look forward to.

What prompted me to install this crap ass software was me getting banned from allmusic.com. I needed something to disguise my IP address. I should have just went with TOR like everyone else. Instead, I went with the first thing I found on Google and tried to download a cracked version which had several trojans in it. My Anti-Virus software stripped out the trojans like it should have, but left the installer in a fucked up state. Dammit. Should have known better, but this is why I do this type of shit on MY PC.

Oh well. Maybe this time I won't install quite so much shit. I may actually have room for my music library (which is well over 45 GB) and my software to coexist on the same box. At some point, probably not until after Christmas, I will buy a new laptop with a substantially bigger hard drive. I'm going to try for 200 GB at least. I'll probably end up selling my laptop to Alan for cheap, or just giving it to someone who needs a laptop.

Labels: , ,

 Saturday, October 27, 2007

Banned!

Summummabitch!

As some of you know, I've been scouring content from the web to make my MP3 collection pages more SEO friendly. So of course with my huge collection of songs it would take until the end of the next millennium to gather reviews, artist bios, and lyrics manually. Naturally, I built a tool.

Now of course, my tool has to be as unnecessarily sophisticated as it can be, which means I'm doing major website scraping, multithreading, thread pumping and dynamic throttling. I ran my tool for every artist/album/track in my collenction against AMG and other sites. Over 30,000 website hits in a matter of a few hours. Collected everything I could. Sweet.

Of course as I'm reviewing my results, I realize there's a major bug in my screen scraping routine. D'oh! I go to run my tool again, and suddenly, I get no results. I check my search result manually and this is the message I get any time I do a search on AMG from my home laptop:

Through traffic monitoring of our websites we have identified your IP address accessing allmusic.com at a rate and speed inconsistent with the noncommercial and personal use permitted by our site's Terms of Service. As a result, further access to allmusic.com has been denied. Because IP addresses can be shared by numerous users, your access may be being denied based on the aggregate use of your IP address rather than your own individual use. To ensure that this is not the case, simply create your own individual user account by becoming a Registered Member of allmusic. [Click on the “Register” button in the upper right hand corner of the home page.] Once you’ve become a Registered Member and are logged in, you will once again have full access to allmusic, and will continue to have access, as long as your usage remains consistent with our Terms of Service. If you are already a Registered Member of allmusic, simply ensure that you are logged in when you use the site. Thank you. - xxx.xxx.xxx.xxx
Dammit!

Though technically, it is for personal use, I suppose I could see how after reviewing their logs they could interpret my usage as a Denial of Service attack. Come on, what If I were a search engine spider? Hehe. I just thought that was way too fuckin' funny! Now of course, you know me. I'm not going to let this stop me, but this was great! Hah!

Labels: , , , , ,

 Thursday, September 20, 2007

Aptana Javascript IDE

Someone at work asked me the question "Do you know of any good javascript editors out there with documentation and intellisense built-in?"

Visual Studio has never been really smart about javascript. Yes, it does provide intellisense, but only at a very minimal level. Only if you are typing within a <script></script> block contained in an HTML or ASPX page, does it provide you with anything, and even then, InterDev left a better footprint of intellisense. VS doesn't validate syntax, or even precompile classes in javascript. VS is very limited. Perhaps in future versions, Micro$oft will

Believe it or not, I didn't have an answer for him. I had been doing javascript for so long (almost 10 years now) that I didn't really have a personal need for intellisense. Everything I put together, I usually knew what I was looking for. Javascript has just become so native for me, that I rarely have to look up documentation for a method or property.

But in the spirit of being a good sport, I decided to see if I could find him one. I did a little research on the net. I came across a few, that looked like they had potential, but I wasn't really love with any of them.

That is, until I stumbled upon Aptana.

Aptana is a full-blown javascript IDE with massive intellisense, syntax validation, and precompilation which lends itself to intellisense. It totally rocks, dude! Nice. But don't take my word for it. Go check it out for yourself.

http://www.aptana.com/

Labels: , , , , , ,

 Tuesday, September 11, 2007

Dammit, Red Ring of Death

I blame this on Sydd. ;)

I have been playing a lot of XBox 360 lately. I talked to Sydd for a second on MySpace and he mentioned that he had the Red Ring of Death. Of course the very next time I go to turn on my XBox...Dammit!



In bumming around the internet, I actually found a video blog article that demonstrates how to solve the red ring of death with TOWELS...yes, towels. I haven't tried it yet, but it sounds just bizarre enough to work.

<a href="http://www.techeblog.com/index.php/tech-gadget/video-fix-the-xbox-360-s-red-ring-of-death-with-towels-" target="RedRingFix"><img src="http://www.waldoland.com/images/blogimages/xboxtowel.jpg" style="border: 0px;" /></a>

Xbox 360 Three red lights ( The Ring of Death )
VIDEO: Fix the Xbox 360's Red Ring of Death with...Towels?

Labels: ,

 Thursday, August 02, 2007

Johnny Depp? Hardly.

So I decided to have a little more fun with the facial recognition software on MyHeritage.com.

Yet again, not one brother.

This time, it came up with Johnny Depp, Leonardo DiCaprio, Ricky Martin, and Darren Hayes. Well, at least it's one Puerto Rican. It's not entirely a snow white cast.

BTW, who the hell is Darren Hayes?

http://www.myheritage.com

Labels: , ,

My Celebrity Look-alikes

This was an interesting little diversion.

I see more and more of these popping up all over MySpace, so I decided to give them a try.

MyHeritage.com uses facial recognition software to take a photo of you and match it up with photots they have of celebrities. I took a stock photo of myself and gave it a whirl.

The funny thing is that there's not a single brother in the bunch. None of these guys even look remotely like me :o)

But whatever. It was fun. Give it a try. All you need is an E-Mail address.

Labels: , ,

 Monday, July 23, 2007

So, do you have a MySpace page or something?

It just makes me laugh sometimes how technology is so well integrated into popular culture today. I was watching TV the other day and the commercial for the new episode of Psych on USA, featuring Lou Diamond Phillips came on.

He just blythely leans in to someone and says, "So, do you have a MySpace page or something?"

Has MySpace become the new substitute for getting digits? Did I miss this memo? Phenomenons like MySpace and Friendster and blogging in general have become so pervasive to modern society. So prolific that it's difficult to imagine a kid surviving without the ability to text his buddy in the next room.

Have I gotten so old that I think all of this is just silly?
Oh, yeah. BTW - Check out MY MySpace page

Labels: , , , , ,

 Thursday, July 19, 2007

Apple ITC File Format (revised)

I recently updated this article with new information and new code samples. Enjoy.

I've been developing some projects relating to iTunes lateley. iTunes 7.0.1 has a new feature called CoverFlow. It is the ability to view your music library by its album art. I thought this was phenomenal. In fact it almost has made a convert out of me, using iTunes almost exclusively now.

iTunes CoverFlow

Having the ability to see all of your album art at once is fantastic, but it also shows you how woefully incomplete your library is. Of course, me being the obsessive-compulsive perfectionist/completionist that I am, I had to find album artwork for EVERY song in my library.

I used the 'Get Album Artwork' function in iTunes to obtain my missing artwork. Everything was going swimmingly. iTunes found and downloaded high resolution album artwork for nearly every album I had in my library (over 8,500 songs). I was doing fine until I began playing those same songs in MusicMatch Jukebox and noticed that the artwork that iTunes had just downloaded was not showing up in MusicMatch.

Was this a coincidence? I had to be sure. I discovered that the 'Get Album Artwork' function in iTunes DOES NOT save the downloaded artwork into the actual MP3 files. Instead it creates .itc files in the folder

%USERPROFILE%\My Documents\My Music\iTunes\Album Artwork

The .itc files contain images and metadata for each album which has downloaded artwork. CoverFlow reads the files into memory and holds them there until the application quits, so that it can display album art images quickly and smoothly.

That's fine. Good for Apple. They have their own system for optimizing album artwork images. But what about poor little ole' me, who wants those images embedded in his MP3 files?

There have been a number of suggested ways to accomplish this thrown about the web. The easiest I can think of is to use the 'Get Info...' command in iTunes, switch to the Artwork tab, Cut the downloaded image from the viewer and re-paste the same image. This will embed the image in the actual MP3 file. This is effective, but also very tedious if you have a large number of files.

Another suggested way was to write a program which hacks the .itc files themselves. For some reason, this appealed to me.

Many places where I've found ways to carve up an .itc file suggest simply removing the first 492 bytes and the rest of the file is JPEG/PNG image data. That would be great if it worked consistently. What I've discovered on my own is that it does not work 100% of the time. Frequently I have found .itc files where the image data did not start until after the first 500 bytes, or other variations on that number.

Based on that inconsistency, I decided to inspect the format of an .itc file myself and see if I could infer a file specification myself. The .itc file seems to consist of four sections: a File Signature, a "Null Buffer", a Data Header, and Image Data.

File Signature

The fourth byte of the file would seem to be self describing, indicating the length of the entire File Signature. In the sample file below, the fourth byte has a value of 1C (28). The File Signature itself seems to have a fairly consistent structure, which has the sequence 69 74 63 68 (itch) beginning at index 4 and 61 72 74 77 (artw) beginning at index 24, terminating the File Signature.

"Null Buffer"

Following the File Signature is 256 bytes of 00 (null).

Data Header

The Data Header contains metadata about the file/artwork itself. So far, every .itc file I have inspected has had the fixed-length signature of 28 bytes, followed by the fixed-length null buffer of 256 bytes. Here is where the variable file size comes into play.

Just like the File Signature, the Data Header is self-describing. The length of the Data Header is a factor in determining where the actual image data begins. This is important because this is where the .itc files I have inspected may vary from the norm.

NEW!

Disposable information (4 bytes)
The first four bytes of the Data Header would seem to be disposable information for our purposes.

"item" sequence (4 bytes)
The next four bytes of the Data Header is the sequence 69 74 65 6D (item).

Data Header Length (4 bytes)
The next four bytes are an unsigned integer value indicating the overall length of the Data Header. In the sample file below, the Data Header length has a value of 00 00 00 D8 (216).

Disposable information (16 bytes)
Immediately following the Data Header length is 16 bytes of disposable information.

Disposable information (0-4 bytes)
When the value of the Data Header length is 212, the next section of metadata begins immediately. If it is 216, the next section is offset by an additional four bytes of disposable information.

Library Persistent ID (8 bytes)
The next 8-byte sequence is the iTunes Music Library Persistent ID to which this track belongs. The Library Persistent ID is a hexadecimal string converted from those bytes. In the example below, you can see the sequence D4 CC CA A6 22 F6 CD DC, which corresponds to my Library Persistent ID (which is the first part of the .itc file name).

Track Persistent ID (8 bytes)
The next 8-byte sequence is the Track Persistent ID if this track. Like the Library Persistent ID, Track Persistent ID is also a hexadecimal string converted from those bytes. In the example below, you can see the sequence 3D 82 AC 91 DD 2D 58 B0, which corresponds to the Track Persistent ID (which is the second part of the .itc file name). You can use the Library and Track Persistent IDs together to discover information about the track, using the iTunes Music Library.xml file.

Download/persistence indicator (4 bytes)
The next 4 bytes are either the string sequence 64 6F 77 6E (down) or 6C 6F 63 6C (locl), which when "down", indicates that the CoverFlow artwork was downloaded and not persisted in a music file's tag information. It also corresponds to the appropriate subfolder beneath the Album Artwork folder. The opposite is true of "locl".

Pseudo-File Format (4 bytes)
The next 4 bytes would seem to give a hint as to the format of the embedded image. When the four bytes equate to the string sequence 50 4E 47 66 (PNGf), the image format will be of PNG (portable network graphics) type. When the sequence is 00 00 00 0D, the image is a JPEG (joint photographics experts group) image.

Disposable information (4 bytes)
Four more bytes of disposable information.

Image Width (4 bytes)
The next four bytes are an unsigned integer value indicating the width of the embedded image.

Image Height (4 bytes)
The next four bytes are an unsigned integer value indicating the height of the embedded image.

Image Data

Once the size of the Data Header has been determined, the next block is the actual Image Data, starting immediately after the Data Header, and continuing to the end of the file. In the sample below, the next four bytes are the sequence FF D8 FF E0 (ÿØÿà) which, as some of you may know, are the signature for a JPEG image.

Apple ITC file strucure



So far, I have been able to consistently extract the image data from .itc files on my own machines. This has been very useful to me in collecting album artwork downloaded from iTunes without having to automate iTunes itself.


Since this is by no means official and an inference of the structure, it is entirely possible that you may find the structure to be different. I simply look for patterns in the chaos. If you find that this does not give you the ability to consistently extract album artwork then please let me know.

Labels: , , , , , ,

 Wednesday, July 11, 2007

Why didn't I think of that sooner?

I had been spending a lot of time working on my website. I can remember a good portion of time went into writing an HttpModule to identify pages generated by Blogger and apply an HttpFilter to produce server generated content based on static markup in those pages.

A brief explanation...

Blogger (the way I have it configured) generates HTML pages for each post, organized by date, an index HTML page for the home page, archive pages, etc. All of them static HTML, generated from a template. Then Blogger FTP's them up to my site. Simple for static content, right?

My HttpModule knows, through its own configurations, which folders on my site contain blog HTML files. If one is requested, it attaches an HttpFilter which scours the content using Regular Expressions, looking for markup that I designate. When it finds that markup, it replaces it with dynamic content, such as UserControls containing menus, Ad rotators, links, etc. It added a little overhead to the processing time of rendering a static page, but for the dynamic content, it was worth it for me.

I spent a couple of weeks building this very slick solution. It ostensively converted static content to dynamic.

A couple of days ago, while working on another section of the site using a Master Page, it hit me. Blogger lets me configure the names of files that it generates. It doesn't HAVE to be .html. Why couldn't it be .aspx, inherit a generic BlogPage class, and use a Master Page?

Holy crap what a great idea! Why hadn't that come to me in like a year? That would save me so much time and effort in updating my blog template.

I used to use a Master Page (several, actually) for the rest of the site, fish out the static content for a page once it was rendered, then apply it to my blog template so that my posts could look and behave like the rest of the site. This meant that any change to my Master Page, or to configurable dynamic content would mean that I would have to update the template and republish my entire blog. This also meant keeping a huge amount of static markup in my template which made diagnosing problems that much more difficult.

So I'm sure the question all of you want answered is, "So how do I use Master Pages and blogger content together?"

Well, I'm glad you asked.

  1. Start by creating a BlogPage base class in your App_Code directory.
    Public MustInherit Class BlogPage
        Inherits System.Web.UI.Page

        Protected WithEvents TitleContent As System.Web.UI.WebControls.Literal

        Private Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
            ' Apply the TitleContent's inner Text to the title, overriding the Title
            ' property defined at the page-level

            If ((Not Me.TitleContent Is Nothing) AndAlso (String.IsNullOrEmpty(Me.TitleContent.Text.Trim()) = False)) Then
                Me.Title = Me.TitleContent.Text.Trim()
                Me.TitleContent.Visible = False
            End If
        End Sub


    End Class

  2. Then create a Master page for your blog content.
    <%@ Master Language="VB" Inherits="MyBlogMaster" CodeFile="MyBlogMaster.master.vb" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server" id="head">
        <title>My Blog Master Page</title>
    </head>
    <body>
        <form id="aspNetForm" runat="server">
            <!-- BEGIN BODY CONTENT -->
            <asp:ContentPlaceHolder ID="BodyContent" runat="server">
                INSERT BLOG CONTENT HERE!
            </asp:ContentPlaceHolder>
            <!-- END BODY CONTENT -->
        </form>
    </body>
    </html>

  3. Update your Blogger settings to generate .aspx pages, rather than .html pages
    Blogger settings

  4. Update your Blogger Template to generate ASPX pages (Web Forms with no codebehind) that will inherit from your base page and consume your Master Page.
    <%@ Page Language="VB" MasterPageFile="MyBlogMaster.master" AutoEventWireup="false" Inherits="BlogPage" title="My Blog Page" %>

    <asp:Content ID="BodyContent1" ContentPlaceHolderID="BodyContent" runat="server">
    <asp:Literal id="TitleContent" runat="server" Visible="false"><$BlogPageTitle$></asp:Literal>

    <Blogger>

    <BlogDateHeader>
    <p class="dateheader"><$BlogDateHeaderDate$></p>
    </BlogDateHeader>

    <a id="<$BlogItemNumber$>" />
    <BlogItemTitle>
    <p class="posttitle" id="BlogItemTitle<$BlogItemNumber$>">
    <BlogItemUrl><a href="<$BlogItemURL$>" title="<$BlogItemURL$>"></BlogItemUrl>
    <$BlogItemTitle$>
    <BlogItemUrl></a></BlogItemUrl>
    </p>

    </BlogItemTitle>



    <div class="post-body">
    <p>
    <$BlogItemBody$>
    </p>
    </div>

    </Blogger>
    </asp:Content>


Oh my god! How much smaller is my template now? I don't have to port all that static markup in the template. If I ever need to change something, I can just change the Master Page and have it propogate all the way through every blog item page. Yay! How long did it take to implement? Well, let's put it this way, It took longer for me to write this post than it did to implement this entire solution.

Now of course I now have the problem of search engines having defunct links. Simple fix. I changed the behavior of my existing HttpModule to send 301 (Permanently Moved) HTTP statuses for any requests to the old .html pages to the new .aspx pages, rather than applying the HttpFilter to convert the static content to dynamic. Sweet!

Labels: , , , , , ,

 Tuesday, June 12, 2007

Posing a question

Non-Techies need not read further

Hmmm...

I've been building a VB.Net library for reading ID3 tags out of MP3 files. I'm wondering if I find a version 2 tag, should I completely discount the information found in the version 1 tag?

Should I treat it as "Highest Version Wins", or should I do a type of merge, where if artist is not found in version 2, use the one found in version 1?

Please comment if you have some input.
Thanks :)

Labels: , , ,

 Friday, May 04, 2007

Request for CoverFlow

I LOOOOOOOOOOOOOOOOVE the coverflow feature. It has made an iTunes convert out of me. My album artwork is very important to me. I absolutely love the ability to view my entire library by its artwork. It makes me spend HOURS making sure I have the best quality album artwork for my thousands of songs. (I haven't broken the 100,000 mark quite yet, but I'm close.)

I feel a great swell of disappointment when I connect my 80GB iPod to my machine, or any other, and I can't view it by its artwork, like I can my library. All that work manicuring my album artwork goes for nothing. Yes, I can see the artwork for individual songs when I play them, but that's it.

I do all that work, take my iPod on the road with me, then when I connect it to iTunes, the two CoverFlow buttons are disabled. It's such a drag, man.

Why would it be so hard to give that same feature that exists on the library, to the iPod?

God, that's a feature I really really want and I'm patiently waiting for Apple to implement it.

Does anyone else feel the same way?

Labels: , , ,

 Friday, February 23, 2007

Locked Assemblies in /bin

A few days ago I had a bizarre website administration issue. I had written an ASP.Net app that inadvertently locked my assemblies in the /bin directory. Granted the obvious, that assemblies in ASP.Net applications are shadow-copied to the Temporary ASP.Net files folder under the specific version of the framework, but my app was special in that it dynamically loaded and inspected the assemblies in the actual bin directory.

In designing the app, I had waited to put the inspection of these assemblies in a separate AppDomain, electing to do that when time permits. Because of this, When I loaded the assemblies in the /bin directory, the .Net Framework keeps a lock on those files for the lifetime of the current AppDomain (until it is unloaded). For working on my local machine, this is fine during development. If anything locks, I can simply run an IISRESET command, which will unload all AppDomains for ASP.Net web applications on my server. When migrating these assemblies to my hosted environment, it was a different story.

Using FTP, I pushed up all my new development work, did a small smoke test, tried my pages and voila! She worked! I went back into development and modified my pages so they load all of these assemblies on a separate AppDomain (which can be unloaded through code). I went to push up my new changes and then it hit me...The assemblies were now locked in the hosted environment!

Well, great! Now I can't push up my new changes, or any other changes for that matter, until the AppDomain which runs my app in the hosted environment is unloaded. This means either calling the hosts on the phone and asking them to do an IISRESET for me, which since this is a shared server, they probably won't do because it would knock off other customers for a few seconds, or asking them to reboot the server, which for the same reason, they also probably will not do. Oh, I'm so screwed.

So I got to thinking. I could either wait for one of these two things to happen naturally, which since one of the founding principles of shared/dedicated hosting is 100% uptime, could be never, or I could take matters into my own hands. I figured there had to be a way to release file locks through code. Seems easy enough, right?

My first challenge was to find a method to unlock these files which would only affect ME. I couldn't be responsible for interrupting someone else's site on that server. My solution had to be isolated to my own application. I started writing a little administrative ASPX-only (no codebehind) page which could perform my task.

I tried using System.IO.FileStream to unlock the individual files. Well, that didn't work because the Framework will sense that the files are already locked BEFORE you even try to unlock them, and throws an exception.

So I did a little research. I found a way to unload a web app and return it to a state just like it was the first time it was run. Call HttpRuntime.UnloadAppDomain(). What this does is clears out the Temporary ASP.Net Files folder for your application. The next time a request is made, it reinitializes the app, shadow copying all the assemblies in the /bin directory to the Temporary ASP.Net Files folder. Cool. You would think that would work. It did not! It shadow copied all of the assemblies, but naturally it doesn't touch the actual assemblies in the /bin directory, which means it didn't affect the locks. D'Oh!

I was growing frustrated. My next step was to do something a touch more drastic that wouldn't be isolated to just me. I was going to programmatically perform an IISRESET on the server. I wished there was a way to do an IISRESET just for a particular LM Instance, but alas, there is not. I would be taking down every internet service on that remote machine momentarily. Fuck it. Let's do it. So I wrote some VB code that would start a Process which would run IISRESET. I tried it, it worked on the hosted server. I was actually rather surprised that the user account which ASP.Net was running under on that server actually had permissions to start a process. Gift Horse -- Mouth -- whatever.

I could see IIS coming down and coming back up. Thankfully it only took a few seconds. Must be a powerful machine to perform an entire IISRESET in like 3 seconds. Alright! I reconnected to FTP and tried to upload my latest DLLs and DAMMIT! Still locked. Sumummabitch! I was really pissed now. I couldn't understand why an IISRESET wouldn't release those file locks.

I did a little more research. The basic principle of unlocking a file that your app did not lock is to get its file handle, get the process which has the file handle open, and use the Win32 API method CloseHandle to release the lock. Well since I did not and could not know what the file handle was on the hosted server, I tried a slightly different method that ultimately worked out for me.

I started thinking I would use the Win32 API to get a list of the processes with open file handles on my files and simply kill them. Then it hit me. You're overthinking, stupid! You know which processes are running ASP.Net. The only processes ASP.Net has ever run under are aspnet_wp.exe (ASP.Net 1.0) and w3wp.exe (ASP.Net 1.1 and 2.0). Fuck it! I'll just kill them. At this point after I had done a couple of IISRESETs on the hosted server, I didn't give a shit about interrupting anyone's services anymore. I was too pissed off.

THANK GOD! It worked. Killing those processes on the server released my file locks and I was able to make my updates. So now I kind of have an ultimate IIS administration tool now. I can provide any task I need from a web page, provided the ASP.Net process account is given enough permission. Here Is a sample of my work.

<%@ Page Language="vb" AutoEventWireup="false" Inherits="System.Web.UI.Page" %>
<%@ Import Namespace="System.Diagnostics" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
  <head>
    <title>IIS Override Tool</title>
    <meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
    <meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
    <meta name=vs_defaultClientScript content="JavaScript">
    <meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
  </head>
  <body MS_POSITIONING="FlowLayout">

    <form id="Form1" method="post"
runat="server">
<asp:Button ID="Button1" Runat="server" Text="Unload AppDomain" OnClick="Button1_Click" />
<asp:Button ID="Button2" Runat="server" Text="Reset IIS" OnClick="Button2_Click" />
<asp:Button ID="Button3" Runat="server" Text="Kill ASP Worker Process" OnClick="Button3_Click" />
<script language="vb" runat="server">

Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    ' Unload and reinitialize the application
    HttpRuntime.UnloadAppDomain()
End Sub

Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    ' Performs an IISRESET
    Dim si As New ProcessStartInfo
    si.FileName = "iisreset"
    si.Arguments = ""
    si.UseShellExecute = True
    Dim prc As Process = Process.Start(si)
End Sub

Private Sub Button3_Click(ByVal sender As Object, ByVal e As System.EventArgs)
    ' Kills all the ASP.Net processes on the local machine

    ' Collect all the applicable processes. Multiple side-by-side versions of the framework may mean
    ' multiple instances of either aspnet_wp.exe or w3wp.exe

    Dim killer As New ArrayList
    For Each p As Process In Diagnostics.Process.GetProcesses()
        Dim processName As String = String.Empty
        Try
            processName = p.ProcessName
        Catch ex As Exception
        End Try

        If (processName <> Nothing) Then
            If ((String.Compare(processName, "w3wp", True) = 0) OrElse (String.Compare(processName, "aspnet_wp", True) = 0)) Then
                killer.Add(p)
            End If
        End If
    Next
    For Each p As Process In killer
        p.Kill()
    Next
End Sub

</script>
</form>

</body>
</html>

Labels: , , , ,

 Monday, July 24, 2006

QuickTime & Windows Server 2003 - The Secret

I was just happy as a clam until a couple of weeks ago when my iTunes told me "There is a new version of iTunes. Would you like to download it?" Dunce that I am, I replied yes.

iTunes is bundled with QuickTime, and as you may or may not know, the latest version of QuickTime (version 7.0.3) from Apple is fairly incompatible with Windows 2003 Server. Ordinarily, I could give less than a fuck, but iTunes requires QuickTime to run. The only reason I EVER use iTunes is to put music onto my iPods, and since iTunes was to ONLY thing that I could use, you can imagine how pissed I was.

After doing a little research, I came across several threads like this one in the Apple support forums. It seems that one of the Security patches (KB908531) for Windows Server 2003 issued by Microsoft, creates a situation where parts of QuickTime's normal operation (including install) are now "privileged instructions".

You could uninstall this security patch and the latest versions of QuickTime and iTunes will work just fine. The problems with this are that 1) you leave your Windows 2003 Server vulnerable to attack, and 2) If you have your Windows Update set to automatically download, you will be consatntly downloading and re-installing this security patch.

The latest version of QuickTime claims to have corrected a vulnerability as well. Personally I would rather go with a secure Windows server and a vulnerable older version of QuickTime, so that's what I did.


So here's how to clean and revert QuickTime.

First, let's get down to the uninstall. Since the latest version of QuickTime fouls up the install, it fails to make the registry entries that would allow the uninstall to show up in Add/Remove Programs. OK, so then what? You could try using the Start Menu item to uninstall QuickTime (Start -> All Programs -> QuickTime -> Uninstall QuickTime). For the same reason (the catastrophic failure during install), it fails to make registry entries that would allow the InstallShield kernel to run the MSI package which would uninstall QuickTime.

Download the Windows Installer CleanUp Utility from Microsoft. This will find the MSI installer package and allow you to uninstall its contents fairly quietly.

It may still leave the files in place so be sure to delete those files manualy. Usually they are stored in C:\Program Files\QuickTime

Here is the step that is really important and must be done before proceeding any further. Open your system folder (usually C:\Windows\system32) and find 2 files, QuickTime.qts and QuickTimeVR.qtx. You must delete these files. They are Apple extensions for QuickTime that function like DLLs. Any QuickTime installer will search for the existence of these files and read the version information out of these files. Don't believe me? Run a file monitor during the install process.

OK, so now you have successfully cleaned off QuickTime. If you inadvertently uninstalled iTunes, you must install the latest version of iTunes (which will attempt to reinstall the latest version of QuickTime) and repeat the process.

QuickTime 7.0.1 Reinstaller (link no longer available)

So now you should have the latest version of iTunes and the not so latest version of QuickTime.

Labels: , ,