Archive for Scripts

Gettin’ Your Macro On

// July 29th, 2008 // 3 Comments » // Scripts, Software, Web

I think it’s time to rock out with another dotCMS blog, and dig into some basic stuff that can be very useful to people getting started in the content management system.  There was a topic recently on the mailing list that was asking about where to look to see some examples of macros, and where you can save your own.  This looked to be a good topic to cash in on (speaking of cash, wanna loan me some?).

Macro output on a page

Macro output on a page

In dotCMS, a macro is basically like it is in other applications: it’s a collection of code one calls to reproduce complex processes in a simple, and straightforward fashion.  You know, to help stupid people out.  To put it in other terms, it’s effectively what one might call a function in other languages.  You give it a name, set parameters it can take, and define some output.  dotCMS comes out of the box with a lot of macros you can readily use, sometimes without even realizing it.  These include things like the commonly used pullContent(), and fancier tools like videoPlayer().  Naturally, dotCMS has a list of these built in macros, and how to use them.  If you want to take a look at example code, the built in macros are stored in /[dotcmsroot]/dotCMS/WEB-INF/velocity/dotCMS_library.vm.  Don’t mess with those though, because odds are you’ll break stuff.  Just trust me on this.

There are a couple ways to approach writing your own macros.  The first is to write a second .vm file, and store it with the default one in the velocity folder.  It will be loaded when the server starts, but requires a server restart when you change or update them, because they are cached in the system when it starts.  Conventionally, the file name dotCMS_library_ext.vm is recommended.  By convention, I just mean that’s what the dotMarketing programmer folks have recommended to me.  The other way is to use a static container, which you include first thing in all the templates you want the macros to be available to.  Macros edited and saved this way do not require server restarts to use, but naturally you must make sure you’ve included the container in EVERY template where you suspect your macros might be used (and also ones where they might not. Trust me, never underestimate the stupidity of your users).  Neither method is right or wrong, and you should just choose the way that fits your development style best.  I’m still looking for a solution that would qualify as chaotic neutral, however.

Okay, so naturally you need to have something of a working knowledge of Velocity code to write a macro, so if you’ve never taken the time to learn some, I suggest you go do that.  Mr. Falzone has talked about this issue, so go get yourself some learnin’ and stop trying to run before you can walk.  Now, get off my lawn. If you already know Velocity stuff, go anyway, he’s a nice guy and worked hard, so you owe it to him to read it and pretend like you’re new to the subject.  Don’t worry, it’ll be our little secret.  But, assuming you understand the basics, this should be pretty straightforward.  So, starting up, we need to define the macro.  I’ll use as an example the macro I wrote that pulls in a list of events from the calendar by a tag:

  1. ## Create a list of events based on a specific tag
  2. ## Optional Parameters:
  3. ##    $eventNum   - Changes the number of results to return
  4. ##    $listTitle  – Changes the title of the event listing
  5. #macro(pullEventListByTag $eventTag)
  6.  
  7. #end

So, we start by calling the macro() function, naming it, and giving it a list of variables to expect.  You can have more than one variable, just list them one after the other (no commas or anything).  As you can see, before I open the macro, I list a couple variables in comments that aren’t required, but can be set before you use pullEventListByTag() and they’ll be pulled in later.  Next, I’m going to set three variables that I’ll use when querying for events, then I’ll build out the query and set it as a variable, and set how I want it ordered (date1 is the event start date).

  1. ## Create a list of events based on a specific tag
  2. ## Optional Parameters:
  3. ##    $eventNum   – Changes the number of results to return
  4. ##    $listTitle  - Changes the title of the event listing
  5. #macro(pullEventListByTag $eventTag)
  6.   #set($eventListPast= $date.format(’MM/dd/yyyy’, $UtilMethods.addDays($date.getDate(),0)))
  7.   #set($eventListToday= $date.format(’MM/dd/yyyy’, $date.getDate()))
  8.   #set($eventListFuture= $date.format(’MM/dd/yyyy’, $UtilMethods.addDays($date.getDate(),80)))
  9.  
  10.   #set($query = "+type:content +deleted:false +structureInode:492 +text4:${eventTag} + (+languageId:1* +( ((date1:[${eventListToday} 00:00:00 TO ${eventListFuture}]))) +live:true)")
  11.   #set($orderBy = ‘date1 asc’)
  12.  
  13. #end

Okay, next up I’m going to check for those optional variables, and if they aren’t set, it will give some default values.  After that, I’ll call the pullContent() macro (as you can see, you can call other macros within macros), and save the results in its own list variable.

  1. #macro(pullEventListByTag $eventTag)
  2.  
  3.   #set($query = "+type:content +deleted:false +structureInode:492 +text4:${eventTag} + (+languageId:1* +( ((date1:[${eventListToday} 00:00:00 TO ${eventListFuture}]))) +live:true)")
  4.   #set($orderBy = ‘date1 asc’)
  5.  
  6.   #if(!($UtilMethods.isSet($eventNum)))
  7.     #set($eventNum = 10)
  8.   #end
  9.   #if(!($UtilMethods.isSet($listTitle)))
  10.     #set($listTitle = ‘Related Events’)
  11.   #end
  12.  
  13.   #pullContent("$query" "$eventNum" "$orderBy")
  14.   #set($eventMacroList = $list)
  15.  
  16. #end

That takes care of the heavy lifting.  Next I’ll start the output.  In this case I’ll build out a <div> to hold the contents, pump out a header, and start a standard foreach() loop for the results in $eventMacroList just as we would when using the pullContent() macro like any other time.  I told you this wasn’t hard.

  1. #macro(pullEventListByTag $eventTag)
  2.  
  3.   #pullContent("$query" "$eventNum" "$orderBy")
  4.   #set($eventMacroList = $list)
  5. <div class="small">
  6.   #foreach($eventMacroEntry in $eventMacroList)
  7. <div style="margin:.5em 1em"><strong>$date.format(’MMM dd’, $eventMacroEntry.startDate) |</strong> #if($UtilMethods.isSet($eventMacroEntry.description)) <a href="/calendar/index.dot?id=$eventMacroEntry.identifier">$eventMacroEntry.title</a> #else $eventMacroEntry.title #end</div>
  8. #end</div>
  9. <div style="text-align:right"><a href="/calendar/?tag=$webapi.encodeURL($eventTag)"><small>More "$eventTag" Events $raquo;</small></a></div>
  10. <!— end eventsTagged —>
  11. #end

And believe it or not, that’s it. Once this is saved and initiated in the manner you choose, you can call your custom macro with the parameters you’ve set, and it will execute the code. In this case, you could call pullEventListByTag(”football”) to return all events tagged football. On another page you could call pullEventListByTag(”baseball”) and get a different set, but still get the same structured output.  Such is the nature of macros.  Any process you would need to do over and over again, or need to simplify for less savvy users are prime candidates for macroification.  In simple terms, this example is nothing more than a macro to automate a pullContent() call and foreach() loop.  If you look at the default macro file in dotCMS, you’ll see how much more complex you can get with them.

So, the complete macro for this example would be as follows.  Feel free to copy and modify it to fit your own needs, or to play around with to get used to the process.  I’d be happy to see how you improve or modify it.  You can also discuss it in the forums, or share your own creations.

  1. ## Create a list of events based on a specific tag
  2. ## Optional Parameters:
  3. ##    $eventNum   – Changes the number of results to return
  4. ##    $listTitle  - Changes the title of the event listing
  5. #macro(pullEventListByTag $eventTag)
  6.   #set($eventListPast= $date.format(’MM/dd/yyyy’, $UtilMethods.addDays($date.getDate(),0)))
  7.   #set($eventListToday= $date.format(’MM/dd/yyyy’, $date.getDate()))
  8.   #set($eventListFuture= $date.format(’MM/dd/yyyy’, $UtilMethods.addDays($date.getDate(),80)))
  9.  
  10.   #set($query = "+type:content +deleted:false +structureInode:492 +text4:${eventTag} + (+languageId:1* +( ((date1:[${eventListToday} 00:00:00 TO ${eventListFuture}]))) +live:true)")
  11.   #set($orderBy = ‘date1 asc’)
  12.  
  13.   #if(!($UtilMethods.isSet($eventNum)))
  14.     #set($eventNum = 10)
  15.   #end
  16.   #if(!($UtilMethods.isSet($listTitle)))
  17.     #set($listTitle = ‘Related Events’)
  18.   #end
  19.  
  20.   #pullContent("$query" "$eventNum" "$orderBy")
  21.   #set($eventMacroList = $list)
  22. <div class="small">
  23.   #foreach($eventMacroEntry in $eventMacroList)
  24. <div style="margin:.5em 1em"><strong>$date.format(’MMM dd’, $eventMacroEntry.startDate) |</strong> #if($UtilMethods.isSet($eventMacroEntry.description)) <a href="/calendar/index.dot?id=$eventMacroEntry.identifier">$eventMacroEntry.title</a> #else $eventMacroEntry.title #end</div>
  25. #end</div>
  26. <div style="text-align:right"><a href="/calendar/?tag=$webapi.encodeURL($eventTag)"><small>More "$eventTag" Events $raquo;</small></a></div>
  27. <!— end eventsTagged —>
  28. #end

Getting my Fixx

// July 10th, 2008 // 3 Comments » // Scripts, Software, Web

I have not, and will not claim to be the tidiest person on the planet.  What I am, however, is a very organized unorganized person.  That is to say, while my desk looks like a mess to you, I absolutely know where every little thing is on it (so don’t touch anything).  Where my failing is, is that I tend to be forgetful, especially through the course of a day where I tend to switch tracks several times going from task to task.  This is especially a problem at work, where I will tell someone I’ll get something done, get distracted by some other problem, then forget about it.  This set me on a mission to find some software to help me out.

Fixx DashboardWhen I’m doing stuff over in dotCMS land, I am usually working with JIRA issue tracking software.  That’s what they use for dotCMS development tracking, and we’re using it to manage tasks on our site redesign project with them.  So I used that as a baseline.  While it isn’t the most clean, modern looking interface, it is very functional.  Besides, it’s also what I’ve gotten very used to, it’s comfortable.  But, it’s also not free.  There are some other systems out there I looked at, like JTrac, Eventum, Bugzilla, and a few others, but for various reasons, I didn’t run with them.  For instance, Bugzilla was too involved to install, and wouldn’t be very portable, Eventum I gave a pretty fair shot, and it  was very nice and very flexible, but had a very dated interface.  Most of the others I came across you had to pay for, or they were just too watered down.  Naturally, I posted to Twitter about my hunt, and along came the name of a product my search hadn’t turned up: Fixx.  Immediately, their interface certainly jumped out as the cleanest of the bunch, and they made used of AJAX (Asynchronous Javascript And XML) to speed things along.  It supports multiple projects which can have parts/components, you can give client access to projects, create custom resolutions and priorities, manage version releases, and even tie it in to Twitter for notifications.  It even supports OpenID.

Editing a project\'s versionsLike JTrac, Fixx is a Java based system, and with my usage of dotCMS, I’m not uncomfortable working with that these days.  All that means is that you better make sure you have the Java JDK installed, and have your JAVA_HOME environmental variable set.  Fixx is not free for groups, but it is free for single user usage, which is exactly what I was going for (there is an educational license discount if you want to use it at a school or college).  When you download it, it comes prepackaged with Apache Tomcat, and running the startup file will set up a webserver on your machine on port 9000.  So, to access your new tracker, you just open http://localhost:9000/ in your browser.  In my case, I tossed it on my server at home, punched a hole in my firewall, and set up a subdomain on that port so that I can access it from any machine that I’m at.  All said, this was all surprisingly painless.  Before I put it on my server, I was even running it right off a thumb drive for a little while testing it out.

So, with it up and running, I jumped right in.  I’ll give them credit, they took their goal of a simple but flexible issue tracker to heart, and seem to have made a nice run of it.  While Eventum is pretty crazy powerful, the interface is dated and cludgy.  Fixx isn’t so flexible, but it’s just plain nice to use.  It makes me think of why Twitter remains so much more popular than Plurk.  Plurk is better, with more options and features, but there are times when simplicity really sells.  And Fixx still gives you enough options and controls to make it worthwhile.  You can do unlimited projects, set project leads, make your custom resolutions and priorities, set sub areas, move tasks to new projects, and plenty more. Basically, all the “important” functions are there.

Viewing a taskCreating a task is as simple as most others: click the link, fill in the fields, and save.  But the interface that displays the task is soft and easy to look at (compare that to Eventum some time).  Information is easy to find, and it’s laid out in a manner that makes sense.  All your controls open up right on the screen, so you can move the task, resolve it, log time, attach files, comment, etc all on the same page without jumping around.  And again, they have tried to keep the options trimmed down a little, and aim more to make it fast, easy, and straightforward.  To me, this is absolutely perfect for the worker or freelancer doing a lot of things on their own.  For a larger group, the Bugzilla or JIRA path makes a bit more sense probably, but even then, there’s not much that those do that Fixx can’t.  The one big exception being nested tasks, or making a task dependent on others.  You can’t designate a task as a parent to another one or such.  That’s one big area I’d like to see change (and I already put in a feature request on the matter).

Overall, I’m impressed.  I haven’t seen another free issue tracker that is nearly as polished as this one is.  It also is perfectly suited to my particular needs.  I think anyone who needs a hand getting some of their tasks organized could stand to benefit from an install of this.  Heck, I even created a project for development of my Grayplicity Wordpress theme, so now I can keep a nice bead on what I need to do to improve it, and store recommendations I want to follow up on as they come in.  What about you?  Is there a system that you are partial to, or maybe on online project tracker that you think is very good?  Share your thoughts.

RIP Drupal, you lose.

// May 21st, 2008 // 7 Comments » // Scripts, Web, Wordpress

After about a year, I am kicking Drupal to the curb.  I fully recognize it is a robust, capable CMS (Content Management System).  So are a lot of other systems.  But it’s just not fitting me well.  Sometimes I think CMS usage is as much about tastes as it is strict functionality (actually, I’m sure of it).  Sure, a sweater might be warm, but if it’s ugly (with a big clown on the front), you might wear something a little lighter for the sake of having something more appealing (and less clowny).  That’s where I am at.  I’m tired of clowns and sweaters.

Wil Wheaton and the Clown SweaterI originally adopted Drupal to run Penpedia when I launched the site for a few reasons.  One, about that time I had started getting into Drupal just through the course of investigating different CMS’s.  I did like that user accounts could have their fields customized.  And I found a module that allowed for hand in hand single sign on authentication with the other half of the site, which ran MediaWiki.  That also made it appealing.  The longer I used it though, the more the rough edges started showing.

First, I didn’t want to start writing templates for a new system.  This is in part because I already know how to template other systems like WordPress, e107, dotCMS, and a couple others.  As a result, I start losing patience for learning others.  Not a huge deal, because theming Drupal isn’t terribly hard, it was just that I didn’t want to.  The theme I ultimately grabbed was only marginal, but I just never got motivated to write a custom one.  And frankly, I’m a little ashamed of that, because the design of the site is not indicative of my abilities.  But what did drive me nuts was the lack of any WYSIWYG editor built in.  And the module that enabled the feature was disgustingly complicated, and caused a lot of clashing with the code stripper.  The added steps of permissions and profiles for it to work right was just way beyond necessary.  Which leads me to the next thing.  The permission system didn’t please me.  It didn’t work how I’d expect, and seemed far to complicated for what it was doing.  That’s what I love about dotCMS, you can’t beat their permissioning system.  Doing complex, and sometimes even more routine, tasks in the back end of Drupal generally felt like a power struggle between me and the code, and I loathed the idea of having to go in and tweak anything.  And just to round it out, I’ve never liked the “node” concept.

But, just to remain clear, if it works for you, then great.  It just hasn’t meshed well with me, and has actually discouraged me from developing the site better.  That’s why I plan on changing things over there to Wordpress later this week.  The MediaWiki portion will remain unchanged, though there might be some tweaks to login stuff, as I am investigating what needs to happen to maintain single sign on with the two.  Plus, between here and there, I’ll only have one software package that I’ll need to worry about now, as opposed to two, which should encourage more development and activity on my part on the Penpedia site.  I think this will be a move all for the better, and it should benefit the site well.

The moral of the story?  There is a lot of value to standardizing on a CMS, and sticking with what you know.  Even if a system isn’t perfect, if you are familiar with it and know its capabilities, I think that beats out picking a robust system that just doesn’t click for you.

Filling a Wordpress Sandbox

// April 2nd, 2008 // 18 Comments » // CSS, Scripts, Web, XHTML

With the debut of my new theme, I have decided that I will go ahead and make it available as a downloadable theme for Wordpress 2.5. This will take some time, as obviously I want to make sure everything works, and take out all the stuff that makes it specific to me. This also raised the question of what about people who do things that I don’t? Building a theme custom to one’s needs is one thing, but making something that is flexible to everyone’s is another.

WP Content FrameworkTo address this, the answer was simple. Development Sandbox. Easy enough. But the kicker was content. I needed a good base of different content, formatting elements, comments, categories, etc. On the Wordpress Theme Viewer, they have just such a site set up. When you test themes, a bunch of test data is displayed in the theme so that you can see how different elements interact with it. But, to my surprise, there was no where that you could download this data at to load into your own site. No demo site database, no Wordpress eXtended RSS (WXR) file floating around, and no one seemed to have an idea of where you could get it.

Some suggested copying my current site. Others just said to toss some junk in. Quasi-reasonable, both answers, but that’s not a good solution. I want something consistent that I can use over and over. Using my own site content isn’t a good idea, because I doubtlessly do things that others don’t, and don’t do things they do. Random content isn’t thought out enough, and might miss some elements that need to be tested. My solution was to create my own site, complete with seeded content to test formatting and display. It comes with pages and sub-pages, categories and sub-categories. There are comments, there are formatting elements. In short, most everything to make sure that you get all your formatting elements covered when designing a Wordpress theme.

I also want to make this available to everyone, and will endeavor to keep it up and make it better as needs grow. Please, feel free to make comments or suggestions, and I’ll incorporate new things into it as they are made. I will also entertain the idea of creating an entire SQL file of a site, for those wishing to go that route rather than importing WXR files. WXR files are limited in what they can contain, so it won’t bring in things like blog names, descriptions, links, link categories, and other such things.

This is version 1.0 of the SuperSatellite WordPress Content Framework (WPCF for short). It is being made available as a Wordpress eXtended RSS file, which you can import into your empty Wordpress install through the Import page under Manage in Wordpress 2.5. I created and tested this in 2.5, though it may work in other versions. If you try it with others, let me know if it does or does not work.

Download WPCF v1.0

Changelog

  • 1.0 (08.04.02)
    • Initial release

Advanced kPlaylist

// April 1st, 2008 // 4 Comments » // Music, Scripts, Web

The following information is accurate as of the latest development build of kPlaylist, which is v1.7 rev479 that was released on the 1st of April, 2008. Get the most current version from kPlaylist’s download page. Revisions are issued pretty regularly, while the 1.7 base came out in 2006. I’m really not sure why he uses that kind of setup for versioning.

UPDATE (08.04.02): I just got word that version 1.8 of kPlaylist will be coming out once the current development code is deemed stable. This will be sometime after revision 480. Following that release, they will probably begin making regular development revisions based on the 1.8 code base, similar to what they are doing now on 1.7.

kPlaylist logoThis was surprisingly well timed, given that a year ago I published my little review in which I endorsed a piece of media streaming software called kPlaylist that I selected over a couple others when I was looking for a way to listen to my music when I wasn’t at home. It is by sheer coincidence that I decided now to go back and touch more on that software, giving a slightly more in depth look, and sharing some tricks and one of my tweaks that aren’t so well documented. Feel free to comment below and add your own advice, or correct any mistakes I might make (not that I ever make mistakes, who are we kidding?).

For those that are unfamiliar, kPlaylist is a PHP based script that allows you to store audio and video files on a web server, and output playlists that allow you to stream said files to the computer you are at. This is very handy if you have encoded a lot of CDs, and prefer to listen to them at work or at a friends house, without lugging the discs all over. You could also use it to share podcasts, or to create a band site where people can listen to and download your garage recordings, and anything along those lines. This does require you have access to a web server with ample storage space of course. I prefer to run my own from home, using No-IP.com to attach a domain name to my box on my internet connection. Just be sure you run a firewall, and that you have permission to share what you are with who you are. I won’t discuss the setup side of this. I assume you can set up your own MySQL database and connect to it and upload files and all that jazz. If you can’t, there’s support forums to help you out with that.

kPlaylist runs off one single file in its simplest form. We can refer to the kPlaylist site for a few of the software’s features:

  • Supports multiple music sources (drives, directories, nmb, smbfs, nfs, etc)
  • Multiuser based, includes automatic sign-up tool and user editor
  • Secure and safe, used daily in hundreds of installations worldwide
  • Upload, multiple upload, download and multi download support.
  • Inbuilt bulletin board to communicate with users
  • Randomizer function to find new and popular music and common music between users
  • Balance network load with the inbuilt streaming engine during streams and download.
  • Supports LAME to re-encode streams on-the-fly (transcoding)
  • History of activity, including detailed track use.
  • Mail functionality for attaching and sending a music file instantly.
  • Easy to get started; automatic upgrade and install.
  • International; supports 29 languages
  • Runs on all operating systems that support PHP and MySQL.
  • Audio support including, but not limited to mp3, ogg, wma, rma, wav, etc.
  • Tested with RealPlayer, XMMS, Windows Media Player, iTunes and Winamp.
  • Plus much, much more.

kPlaylist Screenshot 1So, let’s assume that you get everything set up and running. If so, you probably see something like what we have at the left (granted, I’ve already dug down into an album). If you are running off of the default install you probably notice that my setup looks a little different from yours. I’ve taken advantage some of the features that allow custom theming of kPlaylist. It also supports custom icon packs, so you can really get into how things display. The theme capabilities aren’t necessarily as robust as other applications, but you can still get in enough to have fun with it. Look at the left bar, and click on the button for Admin Control > Settings. This will get you into the settings console where you can start tweaking some of this stuff. Specifically, we want to look at the Customize tab.

kPlaylist Screenshot 2That would be this baby right here. First, if you’d like to embed kPlaylist into another app, like a CMS (Content Management System), you can turn off the Include Headers feature. This is useful if you want to integrate it with a community running on something like Drupal, Joomla, e107, or others. Otherwise, leave it on (which you normally will). The External Images path allows you to tell kPlaylist where to find alternative icons that you want to use. This is relative to the install root of kPlaylist. So, if you installed kPlaylist in a folder called /media, then theme/images/ would translate to http://www.yoursite.com/media/themes/images/. The best thing to do is download the default icon pack, and just start changing the ones you want. I do this, and rename the originals with a .bak extension, just in case I ever need to revert. Likewise, the External CSS (Cascading Style Sheets) File path works the same, allowing you to override default colors and layout settings for kPlaylist. Download the original at the link I just mentioned for images, and start tweaking, then upload it (probably near your custom images), and tell it to find it. You can do the same with Javascript and AJAX (Asynchronous Javascript And XML) frameworks for other options.

kPlaylist Screenshot 3In this case, if you use something like Prototype for AJAX functionality, you can enable additional features like the live Last Streams feed in the system. This can keep you apprised, live, of what people are listening too without the need to refresh the page. Hopefully, we’ll see more AJAX functionality like live-edit playlists soon. My fingers are crossed, and tempted to start coding such functionality myself…we’ll see. There’s a lot of room for growth of AJAX functionality in kPlaylist.

If you are anything like me, you’ve noticed that there are some pitfalls to the fact that kPlaylist is just a single file script. This is handy for simple setups, but can make upgrading tedious if you are using a lot of custom settings. This is because most of the more advanced settings are hardcoded into the script, rather than stored in the database (I’d love to see this change soon…). Actually, there’s a clever tool for simplifying upgrades without a lot of work remembering which variables you changed. You can create your own file, call it kpconfig.php, put it in with you kplaylist install, and store all your custom settings there. Then, each time that you upgrade, all your settings are still right there. The standard kPlaylist install will load this file after all the default settings are loaded, overwriting anything that you want customized. Here’s a sample of my kpconfig.php file:

  1. <?php
  2. $cfg[‘frontbulletinchars’] = 120;
  3. $cfg[‘enablegetid3′] = 1;
  4. $cfg[‘uploadselections’] = 24;
  5. $cfg[‘numberlogins’] = 1;
  6. $cfg[‘livestreamajax’] = true;
  7. $cfg[‘window_x’] = 420;
  8. $cfg[‘window_y’] = 220;
  9. $cfg[‘xspf_x’] = $cfg[‘window_x’]20;
  10. $cfg[‘xspf_y’] = $cfg[‘window_y’]20;
  11. $cfg[‘xspf_url’] = ‘xspf_player.swf’;
  12. $cfg[‘xspf_opt’] = ;
  13. $cfg[‘xspf_enable’] = true;
  14.  
  15. $streamtypes_default = array(
  16. 0 => array   (‘mp3′,   ‘audio/mpeg’,               1, 1, 1, 1),
  17. 1 => array   (‘mp2′,   ‘audio/mpeg’,               1, 1, 1, 1),
  18. 2 => array   (‘ogg’,   ‘application/x-ogg’,        1, 2, 1, 1),
  19. 3 => array   (‘wav’,   ‘audio/wave’,               1, 0, 1, 1),
  20. 4 => array   (‘wma’,   ‘audio/x-ms-wma’,           1, 0, 1, 1),
  21. 5 => array   (‘mpg’,   ‘video/mpeg’,               0, 0, 1, 1),
  22. 6 => array   (‘mpeg’,  ‘video/mpeg’,               0, 0, 1, 1),
  23. 7 => array   (‘avi’,   ‘video/avi’,                0, 0, 1, 1),
  24. 8 => array   (‘wmv’,   ‘video/x-ms-wmv’,           0, 0, 1, 1),
  25. 9 => array   (‘asf’,   ‘application/vnd.ms-asf’,   0, 0, 1, 1),
  26. 10 => array  (‘m3u’,   ‘audio/x-mpegurl’,          0, 0, 0, 0),
  27. 11 => array  (‘flac’,  ‘audio/x-flac’,             1, 0, 1, 1),
  28. 12 => array  (‘jpg’,   ‘image/jpeg’,               0, 0, 0, 0),
  29. 13 => array  (‘gif’,   ‘image/gif’,                0, 0, 0, 0),
  30. 14 => array  (‘png’,   ‘image/png’,                0, 0, 0, 0)
  31. );
  32. ?>

You might notice two things there. One, I’ve opted to enable a Flash based media player (by turning on xspf_enable and setting xspf_url), so that I can play my music right through a web page (if you can’t figure out how to get it to work after setting it up, go into My > Options > Playlist, and set it as XSPF). You can upload any Flash media player that accepts XSPF playlists (Try out Lacy Morrow’s player, or the JW FLV Media Player for instance). kPlaylist recommends the XSPF Web Music Player, but it’s just awfully lightweight for my tastes. That leads me to the second thing you might notice about my config file. I have two variables that aren’t in the original product. This is for a mod that allows me to control the size of my Flash player in the popup window. The variable window_x and window_y let you control the window’s size, but the players themselves don’t always cooperate with that.

My solution takes two steps. First, create the two additional parameters:

  1. $cfg[‘xspf_x’] = $cfg[‘window_x’]20;
  2. $cfg[‘xspf_y’] = $cfg[‘window_y’]20;

Then, look around line 14,651 for the flashhtml() function. I comment it out, and right after it place this modified version:

  1. function flashhtml()
  2.   {
  3.     global $setctl, $phpenv, $u_cookieid, $u_id, $cfg;
  4.     kprintheader(, 0, 0);
  5.     $playlist = $setctl->get(’streamurl’).$phpenv[’streamlocation’];
  6.     $playlist .= ‘?templist=’.$u_id.‘&amp;c=’.$u_cookieid.‘&amp;file=’.lzero(getrand(1,999999),6).‘.xml’;
  7.     $link = $cfg[‘xspf_url’].‘?’.$cfg[‘xspf_opt’].‘autoplay=true&amp;autoload=true&amp;playlist_url=’.urlencode($playlist);
  8. ?>
  9.     <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" width="<?php echo $cfg['xspf_x']; ?>" height="<?php echo $cfg['xspf_y']; ?>" id="xspf_player" align="middle">
  10.       <param name="allowScriptAccess" value="always" />
  11.       <param name="movie" value="<?php echo $link; ?>" />
  12.       <param name="quality" value="high" />
  13.       <param name="bgcolor" value="#e6e6e6" />
  14.       <embed src="<?php echo $link; ?>" quality="high" bgcolor="#e6e6e6" width="<?php echo $cfg['xspf_x']; ?>" height="<?php echo $cfg['xspf_y']; ?>" name="xspf_player" align="middle" allowScriptAccess="always" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />
  15.     </object>
  16. <?php
  17.     kprintend();
  18.   }

That allows the player size to be the full size of the window, minus a few pixels padding. So you can have full flexibility with both the player and its skin size.

There’s this thread in the support forums that you can look at for additional modifications as well, such as DNS (Domain Name Service) lookup on user IP addresses, showing the main directory in a scroll box, and a few others. These require a bit more editing, and will make future upgrades more involved though. You’ll find quite a bit of useful information in the forums that isn’t always available in the normal documentation. If you want to get really crazy, the source code is available too at Get Source page.

kPlaylist is getting increasingly more powerful lately. The enabling of XSPF is older, but still newish in general terms. Video support is being improved, there’s now built in zipping of multiple files (with PHP 5.2), virtual directory support, a network server mode, and more on the way. Still, it’s all around the most lightweight and useful streaming media server software that I’ve used. I do, however, think that there’s room for improvement, and I’m playing with the idea of forking the code and starting a new project based off it. If you’re interested in building a team to do that, contact me and we’ll talk.