Ribbon Interface

Posted on 3 January 2010 | 5 Comments

I’m a bit late to the game here, but after reformatting my computer to officially upgrade to Windows 7, and installing OpenOffice because I don’t want to deal with Office 2007 licensing, I realized how much I prefer the ribbon interface.

I looked around briefly to see if there was a “skin” or something similar for OO since it’s open source nature lends itself to that sort of thing. Alas, nothing to be found but rumors of Sun Microsystems working on a ribbon interface of their own.

Which was an enlightening discovery since reading the comments and reviews revealed almost universal rancor towards the ribbon interface – an attitude I fail to understand or agree with.

To me, the ribbon interface represents a logical solution to a big problem (especially with word-processors), namely feature-creep. There does not need to be a button for every function since there are so many. I don’t need four different visible buttons for left, center, right and justify. Of course I don’t believe the ribbon interface is necessarily appropriate for every suite and program available to the PC, but there is something to be said for a design standard.

So I guess for anyone reading this I’d like to hear your thoughts.

Bookmark and Share
By amclean | Posted in Software

Spoons Are Weird

Posted on 2 January 2010 | No Comments

Today I remembered an old conversation I had years ago which involved looking for common but weird words. Some of these words weren’t weird until you thought about it. Like ‘spoon’. Then while remembering this, my brain turned it into a bizarre English lesson. Keep in mind all of this came to mind while driving home from work, and for some reason I was overwhelmed by the compulsion to document it for posterity.

Observe and despair at my brain in action.

Spoons is a weird word. This sentence is wrong because you can’t refer to a plural noun in the singular, and so it could technically read “Spoons are a weird word” but of course that doesn’t make sense either because we are not talking about a plural noun, but rather the word referencing the object – ‘spoon’. The exception to this rule is when abstracting a plural into a singular collective noun, such as “group” or “bunch”. However in this case you could not say “Spoons are a weird bunch” and get the same meaning as was intended in the sentence starting the paragraph.

Of course you might also say “Spoon is a weird word”, which removes the confusion resulting from the plural noun, but even this is incorrect because neglecting to quote a word makes it the refer to the object instead of the word itself. I found the plural form of the word ‘spoon’ especially highlighted the issue when read or spoken aloud. So to say “Spoon is a weird word” would also be incorrect because it would be stating that a spoon is a word, which it is not – it is rather a utensil used to assist in the act of eating.

The only valid form I can imagine is “’Spoons’ is a weird word”. Notice the single quotes around ‘spoons’ which excludes it from the rules associated with proper noun use, and abstracts the “spoons” into a singular quoted subject.

Bookmark and Share
By amclean | Posted in Other

CFMAP Issue Solved By The ColdFusion Jedi

Posted on 18 December 2009 | No Comments

I started creating a program for a good friend of mine about a month ago in my spare time. Essentially it’s a territory assignment program that assigns specific addresses in a territory to be called on by a field service agent. This territory would be then un-assigned when completed and the agent would move on to the next territory. As an added bonus and an experiment, I thought it would be nifty to actually SEE where the addresses were, instead of simply cranking out the addresses in an ugly list. The results were… inconsistent. Any more than a few addresses and I’d get a popup saying the address couldn’t be found. Normally I wouldn’t think anything of it, but the addresses were different every time the page generated. And ultimately I discovered that all of the addresses could be found.

After a bit of struggling, the first person I thought of who not only had the know-how to solve the problem, but also the inclination to do so, was Ray Camden whose articles I read often and I knew took on questions from readers.

I hadn’t realized that the first step in geocoding was translating addresses to latitudinal and longitudinal coordinates. Apparently if you send too many addresses to geolocate too close together, you get a 620 error from google maps and throws an error (or many errors).

Thanks again to Raymond Camden for his help, and here’s the article he wrote about it: http://www.coldfusionjedi.com/index.cfm/2009/12/15/Having-trouble-with-too-many-map-markers-and-CFMAP

Bookmark and Share
By amclean | Posted in ColdFusion

Coldfusion->IT Analyst

Posted on 18 December 2009 | No Comments

I recently came across a job posting that immediately caught my attention. Not because it was a ColdFusion posting – quite the opposite in fact – but because it appeared at first to be my resume read back to me. The job was so finely tuned to my experience, I looked closer just to verify it wasn’t any of my previous employers filling a hole I had previously left void.

It is here in my hometown which is already a big plus, the position deals mostly with big-picture stuff (without the distraction of handling every little workstation hiccup) and features a team that seems to hold the same values as myself. There’s even a foosball table and a theatre room.

The first interview went long, which was great. It flowed more like a conversation than an interview. In fact it was the first non-tribunal interview I’ve had in ages. I’d almost forgotten how much I preferred one-on-one. Three days later and I’ve already been called for the second interview. I’m very optimistic about my chances.

Of course I will not neglect any chance I get to do programming or learning on my own time, but the focus may veer slightly to more server technology related issues and solutions.

…Assuming I get the job. I suppose I tend to get ahead of myself.

Bookmark and Share
By amclean | Posted in News

The Search For Work Continues

Posted on 7 December 2009 | 3 Comments

I’m still looking for any ColdFusion work at all. I had some back-and-forth with a company in the Netherlands but that fell through. And that pretty much sums up my entire list of opportunities since September. Right now I’m beginning a career in pizza delivery – a job that pays the bills for now but is ultimately unsatisfying.

This is new territory for me since I’ve never experienced an almost universally complete lack of response from any employers. Things must be really bad. Like… really really bad.

My writing on ColdFusion will probably slow now until I have professional cause to work with it again. Perhaps I should start another site where I discuss pizza at length. Perhaps not.

Bookmark and Share
By amclean | Posted in News

Job Searching

Posted on 6 November 2009 | 3 Comments

I hate looking for work. I know everyone does, even at the best of times.

But times like these, when local jobs have polarized into high paying jobs or low paying jobs and nothing in between, and the local government (who counts for a large percentage of local jobs) has cut down its budget for external contracts to almost nothing, looking for work now feels less like looking for a good fit and more like I’m the victim of a mean-spirited game of “Pig In The Middle”. I’m sure I’m not the only one, either.

I’m starting to feel like I specialized in all the wrong things. Windows instead of linux or Mac.  ColdFusion instead of PHP or Java. Network administration instead of database administration. Technical college instead of a computer sciences degree. Programming instead of design. That, and I was born in the wrong country.

Frustration abounds, and I’ve been essentially out of paid work since July, which kills any relocation budget I might have had.

If anyone reading this has any overflow work or say a lead on a ColdFusion telecommute job or contract position, I’m all over it. Otherwise, thanks for reading anyway and I’ll post my progress.

Bookmark and Share
By amclean | Posted in News

New Host!

Posted on 2 November 2009 | No Comments

Media Temple

I recently switched hosts to Media Temple, partly because of some service interruptions on our last host and also as a strategic manoeuvre. I can say without hesitation that this site is much zippier than before – I hope you notice as well. I mean obviously the site doesn’t do anything, but even so I think it’s noticeable. The added benefit to this new host is we now have ultimate power over it, even to the extend of being able to install our ColdFusion license on it.

Bookmark and Share
By amclean | Posted in News

SQL UNION

Posted on 26 October 2009 | 4 Comments

I was recently working on a social network back-end when I came across a problem. There was a users table, and these users had to have the option of “friending” each other. And so I created a “connections” table, which associated user to user. There were a few extra pieces but essentially what I ended up with was a table that stated the ID, friendA and friendB. I did not want multiple records for each connection so for each “friend” link there would be only one connection record.

The problem here is when it came time to use code to display the list of a given user’s friends, I hit a bit of a wall. I didn’t think I could arrange the users in any sort of order because I would need to use two queries like this (assuming 1 is your ID as the user trying to query the database for a list of your friends):

		SELECT
		user_to_user.id,
		user_to_user.userA
		FROM
		user_to_user
		WHERE
		user_to_user.userB = '1'

		SELECT
		user_to_user.id,
		user_to_user.userB
		FROM
		user_to_user
		WHERE
		user_to_user.userA = '1'

The first query checks all results where you are the user initiating the “friend” connection, and the second checks results where others initiated the connection with you. I thought I would have to loop through the results with userA and then userB separately.

As it turns out, I was wrong. The UNION operator is used to combine the result-set of two or more SELECT statements. So all I had to do is put UNION between the two queries and finish up with an ORDER BY clause and I was in business. Incidentally, I’ll note that the results of this would have columns id and userA – but what about userB? W3Schools says it best: The column names in the result-set of a UNION are always equal to the column names in the first SELECT statement in the UNION. So all of the results – both userA and userB – will return under the userA column. If I were to swap the queries so I ask for the userB results first, then all results would be as userB.

Bookmark and Share
By amclean | Posted in MySQL

Reading ID3 and MetaData From MP3s Using ColdFusion 8/9

Posted on 9 October 2009 | No Comments

Ok this has been done before, but everything I’ve read up until now seemed incomplete to me, although what is available was very instructive. For example, Ben Forta’s blog covers Reading MP3 ID3 tags with ColdFusion, while Rupesh Kumar covered Reading MP3 Meta-data from ColdFusion. At first glance the titles almost look like they’re talking about the same thing, but they’re not. The java library “jid3lib” that Ben spoke of could not easily be harnessed to give information such as track length, frequency or bitrate while Rupesh’s code didn’t handle any of the ID3 tag info.

So I decided to combine them.

Firstly you must download the jid3lib and place it in %CFHOME%\runtime\servers\lib and restart the application server.

Secondly, the file I used thanks to Ben Forta.
mp3.cfc:

<cfcomponent>
<!---<cfset mp3File = createObject("java", "coldfusion.util.MP3File").init(".\MP3")>
<cfoutput>mp3File.getBitRate() : #mp3File.getBitRate()# kbps</cfoutput><br>
<cfoutput>mp3File.getFrequency() : #mp3File.getFrequency()# Hz</cfoutput><br>
<cfoutput>mp3File.getVersion() : #mp3File.getVersion()#</cfoutput><br>
<cfoutput>mp3File.getDuration() : #mp3File.getDuration()# Sec</cfoutput><br>
<cfoutput>mp3File.isCopyRighted() : #mp3File.isCopyRighted()#</cfoutput><br>
<cfoutput>mp3File.getChannelMode() : #mp3File.getChannelMode()#</cfoutput><br>--->
    <cfset variables.filename = "">
    <cfset variables.loaded = false>
    <cfset variables.id3tag = "">

    <cffunction name="init" access="public" returnType="mp3" output="false">
        <cfargument name="filename" type="string" required="false">

        <!--- create an instance of the java code --->
        <cfset variables.mp3 = createObject("java", "org.farng.mp3.MP3File")>

        <cfif structKeyExists(arguments, "filename")>
            <!--- read it in --->
            <cfset variables.filename = arguments.filename>
            <cfset read(variables.filename)>
        </cfif>

        <cfreturn this>
    </cffunction>

    <cffunction name="checkLoaded" access="private" returnType="void" output="false"
                hint="Helper function to throw error if no mp3 loaded.">
        <cfif not variables.loaded>
            <cfthrow message="You must first read in an MP3!">
        </cfif>
    </cffunction>

	<cffunction name="getArtist" access="public" returntype="string" output="false" hint="Returns the Artist.">
		<cfreturn variables.id3tag.getLeadArtist()>
	</cffunction>

    <cffunction name="getAlbumTitle" access="public" returnType="string" output="false"
                hint="Returns the album title.">
        <cfreturn variables.id3tag.getAlbumTitle()>
    </cffunction>

    <cffunction name="getSongGenre" access="public" returnType="string" output="false"
                hint="Returns the song genre.">
        <cfreturn variables.id3tag.getSongGenre()>
    </cffunction>

    <cffunction name="getSongTitle" access="public" returnType="string" output="false"
                hint="Returns the song title.">
        <cfreturn variables.id3tag.getSongTitle()>
    </cffunction>

    <cffunction name="getTrackNumber" access="public" returnType="string" output="false"
                hint="Returns the song title.">
        <cfreturn variables.id3tag.getTrackNumberOnAlbum()>
    </cffunction>

    <cffunction name="getYearReleased" access="public" returnType="string" output="false"
                hint="Returns the song's release date.">
        <cfreturn variables.id3tag.getYearReleased()>
    </cffunction>

    <cffunction name="hasID3V1" access="public" returnType="boolean" output="true"
                hint="Returns true if the mp3 has id3v1 information.">
        <cfset checkLoaded()>

        <cfreturn variables.mp3.hasID3v1Tag()>
    </cffunction>

    <cffunction name="hasID3V2" access="public" returnType="boolean" output="false"
                hint="Returns true if the mp3 has id3v2 information.">
        <cfset checkLoaded()>

        <cfreturn variables.mp3.hasID3v2Tag()>
    </cffunction>

    <cffunction name="read" access="public" returnType="void" output="false">
        <cfargument name="filename" type="string" required="true">

        <!--- does the file exist? --->
        <cfif not fileExists(arguments.fileName)>
            <cfthrow message="#arguments.fileName# does not exist.">
        </cfif>

        <!--- copy to global scope --->
        <cfset variables.filename = arguments.filename>

        <cftry>
            <cfset variables.mp3.init(variables.filename)>
            <cfset variables.loaded = true>

            <cfif hasID3V1()>
                <cfset variables.id3tag = variables.mp3.getID3v1Tag()>
            </cfif>
            <cfif hasID3V2()>
                <cfset variables.id3tag = variables.mp3.getID3v2Tag()>
            </cfif>

            <cfcatch>
                <cfthrow message="Invalid MP3 file: #arguments.filename# #cfcatch.message#">
            </cfcatch>
        </cftry>
    </cffunction>

</cfcomponent>

Next, I modified Rupesh’s code to include the coldfusion.util.mp3file class – which you’ll notice I put inside the file loop because the class will not read a directory but will only read an individual file. I just made this the index.cfm file but it can be anything.

<cfset mp3 = createObject("component", "mp3").init()>
<cfset dir = "C:\ColdFusion9\wwwroot\Media Library\MP3\">

<cfdirectory action="list" directory="#dir#" filter="*.mp3" name="music">

<cfloop query="music">
	<cfoutput>filename = #name#<br></cfoutput>
	<cftry>
		<cfset mp3.read(dir &amp; name)>
		<cfset mp3File = createObject("java", "coldfusion.util.MP3File").init(dir & name)>
		<cfset minutes = #mp3file.getDuration()#>
		<cfset minutes = #numberformat(int(minutes/60),"00")#>
		<cfset seconds = #mp3File.getDuration()# mod 60>
		<cfoutput>
			artist: #mp3.getArtist()#<br>
			title: #mp3.getSongTitle()#<br>
			album: #mp3.getAlbumTitle()#<br>
			runtime : #minutes#':#numberformat(seconds,'00')#"<br>
			bitrate: #mp3File.getBitRate()# kbps<br>
			genre: #mp3.getSongGenre()#<br>
			track: #mp3.getTrackNumber()#<br>
			year: #mp3.getYearReleased()#<br>
			frequency: #mp3File.getFrequency()# Hz
		</cfoutput>
	<cfcatch>
		bad file <cfoutput>#cfcatch.message#</cfoutput>
	</cfcatch>
	</cftry>
	<hr>
</cfloop>

At this point it only reads files in a single directory and will not recursively check any subfolders. The output is pictured below:

Pretty basic formatting so you get the idea

Pretty basic formatting so you get the idea

I’m open to any suggestions on how to extend the class or code to include subfolders – obviously I derived most of the code based on the genius of others so I’m a bit hazy on how to take the ball and run with it. Another problem is the fact that the genre cranks out a genre code unless it’s a custom genre. You’ll notice Styx and Toto both have a genre code of 17 in the image above. This corresponds to “Rock”, but for some reason It won’t show a string.

Bookmark and Share
By amclean | Posted in ColdFusion

In San Diego

Posted on 28 September 2009 | No Comments

I arrived in San Diego safely this afternoon after a layover in Seattle.

It’s been a long day since my son decided he needed to wake up at 5:30 this morning and potty and wouldn’t return to sleep.

I’m staying in a Hilton and let me tell you, the thread-count on this bed is unbelievable.  So soft I can barely handle it. This room in general is pretty off-the-hook. I would post some pictures but I forgot my transfer cable back at home and the card is not compatible with my laptop.

I’ve forgotten about the size of American food portions. The layover in Seattle left us hungry so we made a quick stop at Burger King in the airport. The man asked me if I’d like a large drink, and my business partner quickly said to me “remember you’re in the states now”, which prompted me to ask for a medium. The man then presented a cup equivalent to the Super Big Gulp available at 7-11 (about a gallon). I then said I’d take a regular which is about the size of a Canadian large.

Not that I’m complaining. At least you get your money’s worth.

Bookmark and Share
By amclean | Posted in News

« newer postsolder posts »

Copyright © Drewcorp Coding and Technology.