Channels ▼


Your Own MP3 Duration Calculator: Part 2

Copy selected songs to a new folder

Okay, so you play with MDC you select a bunch of songs out of your source directory and now you want to burn them. Liat preferred to have all the selected songs in a dedicated folder so she can rename songs, rearrange them and examine previous CDs.

With MDC 1.0 it was a grueling manual process. Liat fired up an explorer window next to MDC, selected all the files she selected previously in MDC, create a new folder and copy the files there. In MDC 2.0 this task can be done directly. I added a "Make CD..." button (see Figure 4) that opens a folder selection dialog that allows you to browse to an existing folder or create a new one. Once you select a folder, the selected items are copied to the target folder.

[Click image to view at full size]
Figure 4

As usual XAML makes it easy to add a button. The button is docked to the right side of the bottom panel, it has a tooltip and it is disabled initially (can't make a CD before some songs are selected). The Click event is hooked up to the MakeCD_Click() event handler:

    Name="makeCD" DockPanel.Dock="Right" Margin="3" 
    ToolTip="Copy selected songs to a new folder" 
    Click="MakeCD_Click" IsEnabled="False"

 Make CD...


There button is enabled/disabled based on the selection state of the files list. This can be done with data binding, but I opted in this case to use imperative code in the files_SelectionChanged() event handler that's being called whenever the selection changes. It is just one line and I handle in the same place enabling/disabling also the 'Select All' and 'Unselect All' buttons. The 'Select All' button is enabled if not all the items are selected. The 'Unselect All' and 'Make CD...' buttons are enabled if at least one item is selected.

  selectAll.IsEnabled = files.SelectedItems.Count < files.Items.Count;

 unselectAll.IsEnabled = files.SelectedItems.Count > 0;
  makeCD.IsEnabled = files.SelectedItems.Count > 0;

The MakeCD_Click() event handler implements two requested features: copying selected files to a folder and also exporting the song list to a CSV file.

The first step is to select the target folder. I reuse here there _folderBrowserDialog I use for selecting the source folder. In order to remember the source folder I save it in a temporary variable and restore it after the user selected a target folder. If the user selects the the same folder as the source folder MDC displays a message box and takes no action (no point in copying the files to the same folder, there are already there.

    private void MakeCD_Click(object sender, RoutedEventArgs e)
      string savedPath = _folderBrowserDialog.SelectedPath;
      _folderBrowserDialog.ShowNewFolderButton = true;
      DialogResult r = _folderBrowserDialog.ShowDialog();
      if (r == System.Windows.Forms.DialogResult.OK)
        string path = _folderBrowserDialog.SelectedPath;
        // check that the target folder is different than the source folder
        if (path == savedPath)
              "Target folder is the same as source folder. no action taken");
        // restore selected path
        _folderBrowserDialog.SelectedPath = savedPath;

Now, it's time to actually copy all the selected files to the target folder. The .NET Framework provides in the System.IO namespace several classes to help with path manipulation and file operations. Many of these operations are implemented as static methods, which makes a lot of sense for operations like Path.Combine or File.Copy that don't have any state worth remembering for future operations:

  // copy selected songs to target folder

 foreach (TrackInfo t in files.SelectedItems)
   var src = System.IO.Path.Combine(savedPath, t.Name);
   var dst = System.IO.Path.Combine(path, t.Name);
   System.IO.File.Copy(src, dst);

Exporting the song list to a CSV file

This is another feature Liat requested and it is also implemented in the MakeCD_Click() event handler immediately after copying the selected songs. The format is very simple. It is just a two-column list of Name, Duration for each selected item (see Figure 5). Liat can edit it later in Excel and add her class program next to the songs. It goes something like: go fast for 5 minutes, then accelerate for 8 more minutes and when you can't go any faster increase the resistance until you start crying.

[Click image to view at full size]
Figure 5

The Excel native file format is very complicated because it supports a lot of functionality. But, just for importing tabular data into Excel you can use a CSV (Comma-separated values) file. It is very simple to create such a file. You have to be careful to make sure your values don't contain a comma (I don't do it here).

The filename is track_list.csv and it is stored in the target folder together with all the songs. I utilize the 'using' statement that ensures correct use of IDisposable objects. These object have a Dispose() method that should be called to ensure proper cleanup and the using statement does it at the end of the block even if an exception is thrown. I like to think of it as the C# equivalent of the C++ RAII design pattern (

The using statement creates the track_list.csv text file, which is guarantied to be closed properly at the end of the block. Inside the using block the code writes a header "Name", "Duration" to the sw StreamWriter object and then iterates over the selected TrackInfo items and writes each item's name and duration with some formatting to make it look nicer.

  // Create CSV file with track list
  var filename = System.IO.Path.Combine(path, "track_list.csv"); 
 using (var sw = File.CreateText(filename))
   foreach (TrackInfo t in files.SelectedItems)
     var d = new DateTime(t.Duration.Ticks);
     var name = System.IO.Path.GetFileNameWithoutExtension(t.Name);
     sw.WriteLine(name + "," + d.ToString("mm:ss"));

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.