Monthly Archives: May 2005

Playlist copier

I have a pocket pc that I use to listen to music. I like to change up what i’m listening to while I’m using PocketMusic – which is excellent.
So I wrote a little app to take whatever playlists I’ve created on my computer and copy them over to my sd card for use on the go.
Things that I will do if I figure it out – try to go around having to take sd card out and use usb writer . see if there is someway to just go through active sync.

Since I didn’t see this trivial app out there – I created it.
Here you go.
Gpl License please. If you make something better from this, please let me know and please give it away.
Following is the contents of mainwindow.cs

using System;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;

namespace PlaylistCopier
{
 /// 
 /// Summary description for playlistcopier
 /// 
 public class MainWindow : Form
 {
  private TextBox txtPlaylistPath;
  private Button btnOpen;
  private GroupBox grpPlaylist;
  private GroupBox grpSaveTo;
  private TextBox txtSavePath;
  private Button btnSavePath;
  private Button btnCopy;
  private StatusBar sb;
  private OpenFileDialog ofd;
  private SaveFileDialog sfd;
  private ProgressBar progressBar;
  /// 
  /// Required designer variable.
  /// 
  private Container components = null;

  public MainWindow()
  {
   //
   // Required for Windows Form Designer support
   //
   InitializeComponent();

   //
   // TODO: Add any constructor code after InitializeComponent call
   //
  }

  /// 
  /// Clean up any resources being used.
  /// 
  protected override void Dispose( bool disposing )
  {
   if( disposing )
   {
    if (components != null) 
    {
     components.Dispose();
    }
   }
   base.Dispose( disposing );
  }

  #region Windows Form Designer generated code
  /// 
  /// Required method for Designer support - do not modify
  /// the contents of this method with the code editor.
  /// 
  private void InitializeComponent()
  {
   this.txtPlaylistPath = new System.Windows.Forms.TextBox();
   this.ofd = new System.Windows.Forms.OpenFileDialog();
   this.sfd = new System.Windows.Forms.SaveFileDialog();
   this.btnOpen = new System.Windows.Forms.Button();
   this.grpPlaylist = new System.Windows.Forms.GroupBox();
   this.grpSaveTo = new System.Windows.Forms.GroupBox();
   this.txtSavePath = new System.Windows.Forms.TextBox();
   this.btnSavePath = new System.Windows.Forms.Button();
   this.btnCopy = new System.Windows.Forms.Button();
   this.sb = new System.Windows.Forms.StatusBar();
   this.progressBar = new System.Windows.Forms.ProgressBar();
   this.grpPlaylist.SuspendLayout();
   this.grpSaveTo.SuspendLayout();
   this.SuspendLayout();
   // 
   // txtPlaylistPath
   // 
   this.txtPlaylistPath.Anchor = 1);
   this.txtPlaylistPath.Location = new System.Drawing.Point(8, 24);
   this.txtPlaylistPath.Name = "txtPlaylistPath";
   this.txtPlaylistPath.Size = new System.Drawing.Size(352, 20);
   this.txtPlaylistPath.TabIndex = 1;
   this.txtPlaylistPath.Text = "";
   // 
   // btnOpen
   // 
   this.btnOpen.Anchor = 2);
   this.btnOpen.Location = new System.Drawing.Point(368, 24);
   this.btnOpen.Name = "btnOpen";
   this.btnOpen.Size = new System.Drawing.Size(24, 24);
   this.btnOpen.TabIndex = 2;
   this.btnOpen.Text = "...";
   this.btnOpen.Click += new System.EventHandler(this.btnOpen_Click);
   // 
   // grpPlaylist
   // 
   this.grpPlaylist.Anchor = 3);
   this.grpPlaylist.Controls.Add(this.txtPlaylistPath);
   this.grpPlaylist.Controls.Add(this.btnOpen);
   this.grpPlaylist.Location = new System.Drawing.Point(16, 24);
   this.grpPlaylist.Name = "grpPlaylist";
   this.grpPlaylist.Size = new System.Drawing.Size(400, 56);
   this.grpPlaylist.TabIndex = 3;
   this.grpPlaylist.TabStop = false;
   this.grpPlaylist.Text = "Find Playlist";
   // 
   // grpSaveTo
   // 
   this.grpSaveTo.Anchor = 4);
   this.grpSaveTo.Controls.Add(this.txtSavePath);
   this.grpSaveTo.Controls.Add(this.btnSavePath);
   this.grpSaveTo.Location = new System.Drawing.Point(16, 88);
   this.grpSaveTo.Name = "grpSaveTo";
   this.grpSaveTo.Size = new System.Drawing.Size(400, 56);
   this.grpSaveTo.TabIndex = 4;
   this.grpSaveTo.TabStop = false;
   this.grpSaveTo.Text = "Copy To";
   // 
   // txtSavePath
   // 
   this.txtSavePath.Anchor = 5);
   this.txtSavePath.Location = new System.Drawing.Point(8, 24);
   this.txtSavePath.Name = "txtSavePath";
   this.txtSavePath.Size = new System.Drawing.Size(352, 20);
   this.txtSavePath.TabIndex = 1;
   this.txtSavePath.Text = "";
   // 
   // btnSavePath
   // 
   this.btnSavePath.Anchor = 6);
   this.btnSavePath.Location = new System.Drawing.Point(368, 24);
   this.btnSavePath.Name = "btnSavePath";
   this.btnSavePath.Size = new System.Drawing.Size(24, 24);
   this.btnSavePath.TabIndex = 2;
   this.btnSavePath.Text = "...";
   this.btnSavePath.Click += new System.EventHandler(this.btnSavePath_Click);
   // 
   // btnCopy
   // 
   this.btnCopy.Location = new System.Drawing.Point(16, 160);
   this.btnCopy.Name = "btnCopy";
   this.btnCopy.Size = new System.Drawing.Size(40, 23);
   this.btnCopy.TabIndex = 5;
   this.btnCopy.Text = "Copy";
   this.btnCopy.Click += new System.EventHandler(this.btnCopy_Click);
   // 
   // sb
   // 
   this.sb.Location = new System.Drawing.Point(0, 199);
   this.sb.Name = "sb";
   this.sb.Size = new System.Drawing.Size(424, 22);
   this.sb.TabIndex = 6;
   this.sb.Text = "Ready";
   // 
   // progressBar
   // 
   this.progressBar.Anchor = 7);
   this.progressBar.Location = new System.Drawing.Point(64, 160);
   this.progressBar.Name = "progressBar";
   this.progressBar.Size = new System.Drawing.Size(352, 23);
   this.progressBar.TabIndex = 7;
   // 
   // MainWindow
   // 
   this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
   this.ClientSize = new System.Drawing.Size(424, 221);
   this.Controls.Add(this.progressBar);
   this.Controls.Add(this.sb);
   this.Controls.Add(this.btnCopy);
   this.Controls.Add(this.grpSaveTo);
   this.Controls.Add(this.grpPlaylist);
   this.MaximumSize = new System.Drawing.Size(960, 264);
   this.MinimumSize = new System.Drawing.Size(168, 248);
   this.Name = "MainWindow";
   this.Text = "Playlist Copier";
   this.grpPlaylist.ResumeLayout(false);
   this.grpSaveTo.ResumeLayout(false);
   this.ResumeLayout(false);

  }
  #endregion

  /// 
  /// The main entry point for the application.
  /// 
  [STAThread]
  static void Main() 
  {
   Application.Run(new MainWindow());
  }

  private void btnOpen_Click(object sender, EventArgs e)
  {
   
   ofd.Multiselect = false;
   ofd.Filter = "M3U Files|*.m3u";
   if(ofd.ShowDialog() == DialogResult.OK)
   {
    this.txtPlaylistPath.Text = ofd.FileName;
   }
  }

  private void btnSavePath_Click(object sender, EventArgs e)
  {
  
   
   //sfd.Multiselect = false;
   //sfd.Filter = "*.m3u";
   sfd.DefaultExt = ".m3u";
   
   
   if(sfd.ShowDialog() == DialogResult.OK)
   {
    this.txtSavePath.Text = sfd.FileName;
   }
  }

  private void btnCopy_Click(object sender, EventArgs e)
  {
   
   FileInfo fi = new FileInfo(txtPlaylistPath.Text.Trim());
   FileInfo fo = new FileInfo(txtSavePath.Text);
   DirectoryInfo dirOut = fo.Directory;
   FileInfo fcur;
   TextReader tr;
   if8) == null)
   {
    MessageBox.Show("Problem Opening " + fi.Name + "for reading.");
    return;
   }
   //get linecount of the playlist
   int i = 0;
   while(tr.ReadLine() != null)
   {
    i++;
   }
   tr.Close();
   progressBar.Step = 1;
   progressBar.Maximum = i;
   progressBar.Minimum = 0;

   tr = new StreamReader(fi.OpenRead());

   
   TextWriter tw;
   if9) == null)
   {
    MessageBox.Show("Problem Opening " + fo.Name + "for writing.");
    return;
   }
  
   

   try
   {
    sb.Text = "Copying";
    string line;
    while( (line = tr.ReadLine()) != null)
    {
     //is this a comment line?
     if (line.StartsWith("#"))
     {
      //It's a comment line.
      
      //progressBar.
      //write it to the new file and then keep going
      tw.WriteLine(line);

      //increment progress
      progressBar.PerformStep();
     
     }
     else
     {
      //it's a file path
      //find the file
      fcur = new FileInfo(fi.Directory.FullName + @"\" + line);
      
      if(fcur.Exists) //only move good files
      {
       //only move files that don't already exist
       FileInfo ftest = new FileInfo(dirOut.FullName +  @"\" + line);
       if(!ftest.Exists)
       {
        //copy it to the new file directory 
        DirectoryInfo dirnew = new DirectoryInfo(dirOut.FullName + @"\" + Path.GetDirectoryName(line));
        if(!dirnew.Exists)
        {
         //Parent directory of new file doesn't exist yet

         
         // need to create the parent dir for the file.
         dirnew = dirOut.CreateSubdirectory(Path.GetDirectoryName(line));
         if(! dirnew.Exists)
         {
          MessageBox.Show(@"Can't create "+ dirnew.FullName);
          return;
         }
         
        
         fcur.CopyTo(dirOut.FullName +  @"\"+ line);
        }
       }
       //write the entry to the new playlist
       tw.WriteLine(line);
       //increment progress
       progressBar.PerformStep();
      }

     }
    }
   }
   catch(Exception ex)
   {
    MessageBox.Show(ex.Message + ex.StackTrace);
   }
   finally
   {
    
    tr.Close();
    tw.Close(); 
    progressBar.Value = 0;
    sb.Text = "Ready";
   }

   
   
  }


 }

 //TODO: separate out the concept of a playlist into an interface


}
  1. System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right  (back)
  2. System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right  (back)
  3. System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right  (back)
  4. System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right  (back)
  5. System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right  (back)
  6. System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right  (back)
  7. System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right  (back)
  8. tr = new StreamReader(fi.OpenRead(  (back)
  9. tw= new StreamWriter( fo.OpenWrite(  (back)

Responses to This Mobile Life greasemonkey script

I’m reading the comments and am trying to respond to them in an organized way.

* You are a jerk for revealing the cool secret I discovered! Now they will ruin it for EVERYBODY!
** Sorry. I think they give this stuff away. It’s their servers. If they want to, they have that right. Let’s give them a chance to be awesome instead of expecting them to be jerks. Take some comfort in the fact that if the links get obfuscated it will affect me (sob), just as it will when someone else beats the obfuscation (yay).
** Tell all your friends you were doing it way back when. Show them file creation dates to prove it. They’ll be totally wowed. Don’t mention how you didn’t share the idea with your community.

* You are a jerk for stealing from public radio.
** It’s public radio. They give this away over the airwaves. They give it away over the internet. They want you to listen to it. Feel free to donate directly to the station or to NPR in general. I hope more people listen to this stuff and give them money, but not so much that they can retire in luxury from their job of making cool stuff for me to listen to.

* You are a jerk for using up all the bandwidth of WBEZ.org
** Actually, I only created this script after reading Mark‘s review of the RadioShark in the last issue of Make. I told him about the trick and told him I’d try to whip up a greasemonkey for it. I then gave him a link to the script and he blogged it on boingboing. So he’s a awful nasty man for telling all of you about it. Pledge that you’ll never read his awful nasty blog again for what they did to wbez’s servers.
** I have also taken a suggestion from the comments and put in the coral cache address. That’s so hot, I love it. Wish I’d thought of it in the beginning.
** Turn: I’m saving them bandwidth. If you listen to the same stream twice you download it twice. If you download it once each subsequent listen is FREE to wbez.

* You are a jerk for your crappy blog design.
** I apologize. It’s definitely not ready for prime time – but I think it is just the pre tag blogger put in when I pasted the greasemonkey script in. In my defence I think any long line in this particular template with that tag will overlap the sidepanel. Can’t be helped unless I take down my flickr panel. That ain’t happening.

* Thanks!
** You’re welcome! It feels good to be able to give even something tiny back to the internerds who’ve given me tons of cool stuff. Gift economies rock. Now go do wonderful things.

BTW – this website is no longer active, so you can take the domain name!

This American Life downloads

I love greasemonkey. It’s sort of a uber extension for firefox that lets you have hacky control over how pages display and what they do. The scripts for it are amazing.

So I wrote one.
This American Life is a radio show about everything and it is really smart and awesome – if you haven’t listened to it you totally should.

Number 61 called “Fiasco” is my favorite.

They have a links to buy cd’s from audible.com and they have links to realaudio streams that are free.
Unforunately, I like to listen to them on my pocket pc.
Here’s a greasemonkey script that changes all the stream links to download links.
Install greasemonkey.
I don’t have separate hosting, so just copy and paste this into a file and open it in firefox.
Then go to tools, and install user script.
Open thislife.org – all ram links should point to the actual .rm files now for downloading.

Please feel free to improve on this. It might be nice if it offered you a separate link for downloading as opposed to streaming.

Why doesn’t it work?!
Thanks for your input! Please let me know how it isn’t working.

I am in the main page, none of the sub pages have the links converted.
You’ve got an old version! The new version works better better, sometimes. Thanks much to
Why is thislife.org CRAWLING right now?
I had no idea so many people would use the script and the first version hit their servers directly.
I’m putting up a new version that hits the coral cache of it. Thanks Jaime Alesso!

If you know how to fix this, let me know, I’m looking at it.
Please email me if you can host the script, thanks.
update: fixed to work with firefox 1.5/greasemonkey 0.64

from here

// This Mobile life
// version 0.4 BETA!
// 2005-05-19
// Copyright (c) 2005, Matt Katz
// Released under the GPL license
// http://www.gnu.org/copyleft/gpl.html
//
// --------------------------------------------------------------------
//
// This is a Greasemonkey user script.
//
// To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
// Then restart Firefox and revisit this script.
// Under Tools, there will be a new menu item to "Install User Script".
// Accept the default configuration and install.
//
// To uninstall, go to Tools/Manage User Scripts,
// select "This Mobile Life", and click Uninstall.
//
// --------------------------------------------------------------------
//
// ==UserScript==
// @name          This Mobile Life
// @namespace     http://snarkhunt.blogspot.com
// @description   Changes all This American Life ra stream links to link to the .rm file to download
// @include   http://thislife.org/*
// @include       http://*.thislife.org/*
// ==/UserScript==




var allLinks = unsafeWindow.document.getElementsByTagName("a");

for (i = 0; i < allLinks.length; i++)
{ 
 
  var href = allLinks[i].href;
  if (href.match(/ra\/([0-9]+).ram$/i) )
  {
   
//   alert('Hello world!');
   var episode = href.match(/([0-9]+)/i);
   
   //get the number to get the episode number
  if(episode){
    allLinks[i].setAttribute("href", "http://wbez.org.nyud.net:8090/ta/" + episode[1] + ".rm");
   }
   
   
  }
}