Merge with bugfix-0.5

file:207f0b31533efdab9ae6bbbdb5504c0e0258925f(new)
--- /dev/null
+++ b/lib/mp3togo.glade
@@ -0,0 +1,1120 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
+
+<glade-interface>
+
+<widget class="GtkDialog" id="ImportDialog">
+ <property name="title" translatable="yes" context="yes">Import Playlist</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="default_width">320</property>
+ <property name="default_height">260</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+ <property name="has_separator">True</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog1-vbox">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog1-action_area">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="ImportGo">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Import</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">0</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="ImportCancel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Cancel</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">0</property>
+ <signal name="clicked" handler="on_ImportCancel" last_modification_time="Mon, 05 Jun 2006 01:35:33 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox3">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="ImportTitle">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Import Playlist from Application</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox7">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkRadioButton" id="ImportXMMS">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Import from XMMS session</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <signal name="toggled" handler="on_ImportXMMS_toggled" last_modification_time="Sun, 04 Jun 2006 21:34:25 GMT"/>
+ <signal name="clicked" handler="on_ImportXMMS_clicked" last_modification_time="Sun, 04 Jun 2006 21:46:21 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkSpinButton" id="XMMSSession">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="climb_rate">1</property>
+ <property name="digits">0</property>
+ <property name="numeric">True</property>
+ <property name="update_policy">GTK_UPDATE_ALWAYS</property>
+ <property name="snap_to_ticks">False</property>
+ <property name="wrap">False</property>
+ <property name="adjustment">0 0 100 1 10 10</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkRadioButton" id="ImportAmarok">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Import from amaroK</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="active">False</property>
+ <property name="inconsistent">False</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">ImportXMMS</property>
+ <signal name="toggled" handler="on_ImportAmarok_toggled" last_modification_time="Sun, 04 Jun 2006 21:36:56 GMT"/>
+ <signal name="clicked" handler="on_ImportAmarok_clicked" last_modification_time="Sun, 04 Jun 2006 21:46:12 GMT"/>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">12</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkWindow" id="MainWindow">
+ <property name="title" translatable="yes" context="yes">mp3togo</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="default_width">620</property>
+ <property name="default_height">400</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+ <signal name="destroy" handler="on_MainWindow_destroy" last_modification_time="Sun, 04 Jun 2006 19:28:09 GMT"/>
+
+ <child>
+ <widget class="GtkVBox" id="vboxWhole">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vboxTitle">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="Title">
+ <property name="height_request">15</property>
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">mp3togo</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">True</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="Configure">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Settings</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_Configure" last_modification_time="Sun, 04 Jun 2006 21:52:39 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="Exit">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Quit</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_Exit" last_modification_time="Sun, 04 Jun 2006 19:45:04 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">10</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHSeparator" id="hseparatorTop">
+ <property name="height_request">2</property>
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHPaned" id="hpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox5">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox6">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Playlist</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">5</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox8">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="border_width">2</property>
+ <property name="width_request">300</property>
+ <property name="height_request">300</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
+ <property name="shadow_type">GTK_SHADOW_NONE</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkTreeView" id="PlayListList">
+ <property name="border_width">2</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="headers_visible">False</property>
+ <property name="rules_hint">True</property>
+ <property name="reorderable">False</property>
+ <property name="enable_search">True</property>
+ <property name="fixed_height_mode">False</property>
+ <property name="hover_selection">False</property>
+ <property name="hover_expand">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonboxSelect">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_START</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="SelectAll">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_SelectAll" last_modification_time="Tue, 06 Jun 2006 07:49:11 GMT"/>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment1">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox10">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="stock">gtk-apply</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">All</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="SelectNone">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_SelectNone" last_modification_time="Tue, 06 Jun 2006 07:49:22 GMT"/>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment2">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox11">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="stock">gtk-apply</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">None</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="SelectInvert">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_SelectInvert" last_modification_time="Tue, 06 Jun 2006 07:49:32 GMT"/>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment3">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">0</property>
+ <property name="yscale">0</property>
+ <property name="top_padding">0</property>
+ <property name="bottom_padding">0</property>
+ <property name="left_padding">0</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkHBox" id="hbox12">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">2</property>
+
+ <child>
+ <widget class="GtkImage" id="image3">
+ <property name="visible">True</property>
+ <property name="stock">gtk-apply</property>
+ <property name="icon_size">4</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Invert</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVButtonBox" id="vbuttonbox1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_START</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="button7">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Remove Selected</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_PlaylistRemove" last_modification_time="Mon, 05 Jun 2006 02:45:55 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button8">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Add Files</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_PlaylistAddFiles" last_modification_time="Sun, 04 Jun 2006 20:45:36 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button9">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Import from App</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_PlaylistImport" last_modification_time="Sun, 04 Jun 2006 21:18:48 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox9">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vbox10">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Player</property>
+ <property name="use_underline">True</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">5</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hbox9">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="Placeholder">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Not implemented</property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_CENTER</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="shrink">True</property>
+ <property name="resize">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHSeparator" id="hseparator1">
+ <property name="height_request">2</property>
+ <property name="visible">True</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vboxStatus">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkScrolledWindow" id="scrolledwindow2">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="vscrollbar_policy">GTK_POLICY_NEVER</property>
+ <property name="shadow_type">GTK_SHADOW_IN</property>
+ <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+
+ <child>
+ <widget class="GtkLabel" id="CurrentFile">
+ <property name="width_request">420</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHBox" id="hboxBottom">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkVBox" id="vboxProgress">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkLabel" id="StatusText">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes"></property>
+ <property name="use_underline">False</property>
+ <property name="use_markup">False</property>
+ <property name="justify">GTK_JUSTIFY_LEFT</property>
+ <property name="wrap">False</property>
+ <property name="selectable">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xpad">0</property>
+ <property name="ypad">0</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ <property name="width_chars">-1</property>
+ <property name="single_line_mode">False</property>
+ <property name="angle">0</property>
+ </widget>
+ <packing>
+ <property name="padding">5</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkProgressBar" id="Progress">
+ <property name="height_request">20</property>
+ <property name="visible">True</property>
+ <property name="orientation">GTK_PROGRESS_LEFT_TO_RIGHT</property>
+ <property name="fraction">0</property>
+ <property name="pulse_step">0.10000000149</property>
+ <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="PauseStop">
+ <property name="height_request">30</property>
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_DEFAULT_STYLE</property>
+ <property name="spacing">5</property>
+
+ <child>
+ <widget class="GtkButton" id="Start">
+ <property name="visible">True</property>
+ <property name="label">gtk-convert</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked" handler="on_Start" last_modification_time="Tue, 06 Jun 2006 08:06:47 GMT"/>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="Pause">
+ <property name="visible">True</property>
+ <property name="label">gtk-media-pause</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="Abort">
+ <property name="visible">True</property>
+ <property name="label">gtk-media-stop</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">10</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkDialog" id="SettingsDialog">
+ <property name="title" translatable="yes" context="yes">mp3togo settings</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="default_width">320</property>
+ <property name="default_height">260</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+ <property name="has_separator">True</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog2-vbox">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog2-action_area">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="SettingsSave">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Save</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">0</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="SettingsCancel">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes" context="yes">Cancel</property>
+ <property name="use_underline">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">0</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkVBox" id="vboxSettings">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <placeholder/>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+
+ <child>
+ <placeholder/>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+<widget class="GtkFileChooserDialog" id="AddFilesSelector">
+ <property name="visible">True</property>
+ <property name="action">GTK_FILE_CHOOSER_ACTION_OPEN</property>
+ <property name="local_only">True</property>
+ <property name="select_multiple">True</property>
+ <property name="show_hidden">False</property>
+ <property name="do_overwrite_confirmation">False</property>
+ <property name="title" translatable="yes">Add Files or Playlists</property>
+ <property name="type">GTK_WINDOW_TOPLEVEL</property>
+ <property name="window_position">GTK_WIN_POS_NONE</property>
+ <property name="modal">False</property>
+ <property name="resizable">True</property>
+ <property name="destroy_with_parent">False</property>
+ <property name="decorated">True</property>
+ <property name="skip_taskbar_hint">False</property>
+ <property name="skip_pager_hint">False</property>
+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
+ <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
+ <property name="focus_on_map">True</property>
+ <property name="urgency_hint">False</property>
+
+ <child internal-child="vbox">
+ <widget class="GtkVBox" id="dialog-vbox1">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">24</property>
+
+ <child internal-child="action_area">
+ <widget class="GtkHButtonBox" id="dialog-action_area1">
+ <property name="visible">True</property>
+ <property name="layout_style">GTK_BUTTONBOX_END</property>
+
+ <child>
+ <widget class="GtkButton" id="button1">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-cancel</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-6</property>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkButton" id="button2">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-open</property>
+ <property name="use_stock">True</property>
+ <property name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <property name="response_id">-5</property>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">GTK_PACK_END</property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+</widget>
+
+</glade-interface>
file:f45a1278f195ce8154689f93971c6cebc2b595ac(new)
--- /dev/null
+++ b/lib/mp3togo.gladep
@@ -0,0 +1,8 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<!DOCTYPE glade-project SYSTEM "http://glade.gnome.org/glade-project-2.0.dtd">
+
+<glade-project>
+ <name>mp3togo</name>
+ <program_name>mp3togo</program_name>
+ <gnome_support>FALSE</gnome_support>
+</glade-project>
file:14620f89c3875896529bd8832da1abfac8e15ffb -> file:2ea2bd6a982556d60d2bce769bce6503184ccb67
--- a/mp3togo/__init__.py
+++ b/mp3togo/__init__.py
@@ -21,5 +21,5 @@
# __all__ = ('converter', 'main', 'options', 'setup')
-version = '0.5.11'
+version = '0.6.0'
file:88c098c7679465e5c7847caf35e865ea0ea9d594 -> file:14277acd53b89c4bc1bdd5a306b2a8fd29ddec69
--- a/mp3togo/cluster.py
+++ b/mp3togo/cluster.py
@@ -97,23 +97,13 @@ def slave(opts):
def initialize(ropts):
"""Integrate remote options into local opts"""
- # of = file('/home/sim/temp/2go/cluster/opts-slave', 'w')
-# for key in ropts.keys():
-# if opts.has_key(key):
-# opts[key] = ropts[key]
-# # of.write("%s: %s\n" % (key, opts[key]))
-# else:
-# return None
- # of.close()
- st = ropts['pickle']
- opts._d = cPickle.loads(st)
-
- opts['verbosity'] = 0
- of = file('/home/sim/temp/2go/cluster/opts-slave', 'w')
- for key in opts.keys():
- of.write("%s: %s\n" % (key, opts[key]))
- of.close()
- return "SLAVE: ready"
+ try:
+ st = ropts['pickle']
+ opts._d = cPickle.loads(st)
+ opts['verbosity'] = 0
+ return "SLAVE: ready"
+ except:
+ return None
def perform(rotps):
"""Run the work unit and watch progress"""
@@ -124,7 +114,7 @@ def slave(opts):
fc = cache.Cache(opts['usecache'], opts)
else:
fc = None
- trk = track.Track(rotps['file'], opts, fc)
+ trk = track.Track(rotps['file'], opts, cooked=fc)
pl = pool.Pool(opts)
if pl.add_track(trk):
tsk = trk.getfirst()
@@ -220,9 +210,14 @@ class Boss:
self.current = None
self.pid, self.fd1 = pty.fork()
if self.pid == 0:
+ args = ''
args = r_schema.replace('%h', host)
- args += " mp3togo --cluster-slave True"
- #args += " test-mp3togo --cluster-slave True"
+ if args:
+ args += ' '
+ if self.opts.argv:
+ args += self.opts.argv[0] + " --cluster-slave True"
+ else:
+ args += "mp3togo --cluster-slave True"
args = args.split()
os.execvp(args[0], args)
else:
@@ -267,6 +262,7 @@ class Boss:
self.files.push(self.current, front=True)
raise StopIteration
yield ('Not Ready', 'Not Ready', 0)
+ # Roll back and try to start again self = Boss(yada, ...)
continue
self.rf.flush()
for line in inp.split('\n'):
@@ -289,12 +285,12 @@ class Boss:
return
self.wf.write('file=%s\n' % self.current)
self.wf.write(EOT)
- start = time.time()
+ self.start = time.time()
percent = 0.0
if EOR.replace('\n', '') == line:
if self.current:
yield (self.current, 'Finished',
- float(time.time() - start))
+ float(time.time() - self.start))
next()
break
elif line.startswith('Progress:'):
file:bee7f320d82060a8aa6c09ff08e3fb57e30c0775 -> file:a9172f2a1028c58af20458eef79f9c84471be2bd
--- a/mp3togo/conf.py
+++ b/mp3togo/conf.py
@@ -75,11 +75,14 @@ class Options(options.Options):
"""Subclass options.Options and fill in application specific
information."""
def __init__(self, argv=None, conffile=None, readconf=True):
- options.Options.__init__(self, '~/.mp3togo')
+ self.argv = argv
+ options.Options.__init__(self, absfile('~/.mp3togo'))
# Options to add:
# ((name, short option, long option, default value, hook, help text), ...)
self._set += [
+ ('gui', 'X', 'gui-mode', False, None,
+ '''Start mp3togo GTK interface.'''),
('brwarning', 't', 'file-tag', '.2go', None,
'''A string appended to the name of the file to indicate it has been recoded.'''),
('tempdir', 'w', 'work-dir', '/tmp', self._absfile,
@@ -264,6 +267,8 @@ Description:
def checkfile(self, name):
"""Verify the existence of an audio file"""
name = name.replace('\n', '')
+ name = name.replace('\r', '')
+ name = name.replace('\f', '')
if not os.path.exists(name):
raise ErrorNoFile
name = absfile(name)
file:8e3b396fb24e674ccedc0761bfc22ea1ffd42f7f -> file:0c4aa85b716afdc199903e38cf5c15c255db6337
--- a/mp3togo/filelist.py
+++ b/mp3togo/filelist.py
@@ -24,13 +24,14 @@ import os
import tempfile
import threading
-import mp3togo.conf as setup
+import mp3togo.conf as conf
class FileList:
"""A list of verified music files."""
def __init__(self, opts):
+ """Setup"""
self._opts = opts
self._list = []
self._i = 0
@@ -51,28 +52,30 @@ class FileList:
return tuple(self._list)
def addfiles(self, names, block=True):
+ """Add a list of files or playlists to the list"""
if not self._lock.acquire(block) and not block:
return False
-
if type(names) not in (type([]), type(())):
names = (names,)
-
for name in names:
- try:
- if os.path.splitext(name)[1] in ('.m3u', '.pls'):
- self._addplaylist(name)
- continue
- else:
- name = self._opts.checkfile(name)
- except:
- continue
-
- if name not in self._list:
- self._list.append(name)
-
+ if os.path.splitext(name)[1] in ('.m3u', '.pls'):
+ self._addplaylist(name)
+ else:
+ self._addfile(name)
self._lock.release()
return True
+ def _addfile(self, name):
+ """Add one file"""
+ #All files must be added through this method for the subclass to work
+ try:
+ name = self._opts.checkfile(name)
+ if name not in self._list:
+ self._list.append(name)
+ return True
+ except:
+ return None
+
def addplaylist(self, lst, block=True):
"""Add a playlist."""
if not self._lock.acquire(block) and not block:
@@ -86,40 +89,35 @@ class FileList:
return ret
def _addplaylist(self, lst):
+ """Internal use"""
if not os.path.exists(lst):
- raise setup.ErrorNoFile
+ raise conf.ErrorNoFile
pl = file(lst)
for line in pl:
if line.startswith('/'):
- try:
- name = self._opts.checkfile(line)
- except:
- continue
- self._list.append(name)
+ self._addfile(line)
elif line.startswith("File") and line.find('=') > -1:
name = line.strip().split('=', 1)[1]
- try:
- name = self._opts.checkfile(name)
- except:
- continue
- self._list.append(name)
+ self._addfile(name)
return True
def addXMMS(self, session=0, block=True):
+ """Add playlist from running XMMS session"""
if self._opts.mod['xmms']:
import xmms
else:
- raise setup.ErrorNoXMMSControl
+ raise conf.ErrorNoXMMSControl
if not xmms.control.is_running:
- raise setup.ErrorXMMSNotRunning
+ raise conf.ErrorXMMSNotRunning
res = []
for i in range(xmms.control.get_playlist_length(session)):
- res.append(xmms.control.get_playlist_file(i))
+ res.append(xmms.control.get_playlist_file(i, session))
# locks self in addfiles
self.addfiles(res, block)
def addAmarok(self, session=0, block=True):
+ """Add playlist from running amaroK session"""
# Thanks Justus Pendleton
if self._opts.bin['dcop']:
m3u = tempfile.NamedTemporaryFile(suffix='.m3u',
@@ -129,20 +127,24 @@ class FileList:
'dcop', 'amarok', 'playlist',
'saveM3u', m3u.name, '0')
if exit_code != 0:
- raise setup.ErrorAmarokNotRunning
+ raise conf.ErrorAmarokNotRunning
self.addplaylist(m3u.name)
#os.unlink(m3u.name) <- cleaned up automaticaly by tempfile
def removefile(self, name, block=True):
+ """remove a file from the list"""
if not self._lock.acquire(block) and not block:
return False
+ self._removefile(name)
+ self._lock.release()
+ return True
+ def _removefile(self, name):
+ """Internal use"""
+ # All removals should use this
while name in self._list:
del self._list[self._list.index(name)]
- self._lock.release()
- return True
-
def pop(self, index=-1):
"""Pop off a value atomicly
Use either this or the iterator access, not both."""
@@ -157,7 +159,7 @@ class FileList:
"""Put a file back in the list
for another cluster node to try maybe."""
self._poplock.acquire()
- if front:
+ if front:
self._list.insert(0, value)
else:
self._list.append(value)
@@ -167,18 +169,21 @@ class FileList:
"""To use the iterator access, you must promise
to not modify the list."""
if not self._lock.locked():
- raise setup.ErrorUnlocked
+ raise conf.ErrorUnlocked
for self._i in range(len(self._list)):
yield self._list[self._i]
def cur_file(self):
+ """Returns the index of the iterator"""
return self._i
def __len__(self):
+ """returns the length of the list"""
return len(self._list)
def __contains__(self, name):
+ """Membership test"""
return name in self._list
file:6ce54fdef9dc83cac3cd3e96df0ae5626614cae7(new)
--- /dev/null
+++ b/mp3togo/gui/__init__.py
@@ -0,0 +1,23 @@
+#
+# mp3togo Portable Music Manager
+#
+# PyGTK interface sub package
+#
+# Copyright 2006: Simeon Veldstra <reallifesim@gmail.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc.
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
file:559f5ef47c2fda934305c1b82d7db811774f6d22(new)
--- /dev/null
+++ b/mp3togo/gui/filewindow.py
@@ -0,0 +1,53 @@
+# - gui/filewindow.py --
+# GTK user interface - File selection window
+#
+# This file is part of mp3togo
+#
+# (c) Simeon Veldstra 2006 <reallifesim@gmail.com>
+#
+# This software is free.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You may redistribute this program under the terms of the
+# GNU General Public Licence version 2
+# Available in this package or at http://www.fsf.org
+
+
+try:
+ import pygtk
+ pygtk.require("2.0")
+ import gtk
+ import gtk.glade
+ import gobject
+except:
+ print "GTK not present! mp3togo GTK GUI requires python-gtk2 and python-glade2"
+ sys.exit(1)
+
+import sys
+import os
+
+import mp3togo.gui.gutil as gutil
+
+class AddFilesSelector:
+ """File and playlist selector"""
+
+ def __init__(self, opts):
+ self.opts = opts
+
+ def run(self):
+ gladefile = gutil.find_glade_xml(self.opts)
+ self.wTree = gtk.glade.XML(gladefile, "AddFilesSelector")
+ self.dlg = self.wTree.get_widget("AddFilesSelector")
+
+ result = self.dlg.run()
+ names = self.dlg.get_filenames()
+ self.dlg.destroy()
+ if result == gtk.RESPONSE_OK:
+ return names
+ else:
+ return None
+
file:074d6049bfb0d9bb4b7b7d3541fdd0e876dd9d58(new)
--- /dev/null
+++ b/mp3togo/gui/gutil.py
@@ -0,0 +1,35 @@
+# - gutil.py --
+# GTK user interface utility functions
+
+# This file is part of mp3togo
+
+# Convert audio files to play on a mp3 player
+#
+# (c) Simeon Veldstra 2006 <reallifesim@gmail.com>
+#
+# This software is free.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You may redistribute this program under the terms of the
+# GNU General Public Licence version 2
+# Available in this package or at http://www.fsf.org
+
+import os
+import sys
+
+import mp3togo.conf as conf
+
+def find_glade_xml(opts):
+ """Return a path to the glade xml file."""
+ if opts.argv and opts.argv[0] != "mp3togo":
+ xml = os.path.split(conf.__file__)[0]
+ xml = os.path.split(xml)[0]
+ xml = os.path.join(xml, 'lib/mp3togo.glade')
+ else:
+ xml = os.path.join(sys.prefix, 'lib/mp3togo/mp3togo.glade')
+ return xml
+
file:489d32894147cbdc1a6f04fa98a0fbf24e89ebfc(new)
--- /dev/null
+++ b/mp3togo/gui/importwindow.py
@@ -0,0 +1,77 @@
+# - gui/importwindow.py --
+# GTK user interface - Import from jukebox application window
+#
+# This file is part of mp3togo
+#
+# (c) Simeon Veldstra 2006 <reallifesim@gmail.com>
+#
+# This software is free.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You may redistribute this program under the terms of the
+# GNU General Public Licence version 2
+# Available in this package or at http://www.fsf.org
+
+
+try:
+ import pygtk
+ pygtk.require("2.0")
+ import gtk
+ import gtk.glade
+ import gobject
+except:
+ print "GTK not present! mp3togo GTK GUI requires python-gtk2 and python-glade2"
+ sys.exit(1)
+
+import mp3togo.gui.gutil as gutil
+
+
+class ImportDialog:
+ """Import playlists from jukebox apps."""
+
+ def __init__(self, opts):
+ self.current = "XMMS"
+
+ gladefile = gutil.find_glade_xml(opts)
+ self.wTree = gtk.glade.XML(gladefile, "ImportDialog")
+ self.dlg = self.wTree.get_widget("ImportDialog")
+
+ callbacks = {
+ "on_ImportXMMS_toggled": (self.change, "XMMS"),
+ "on_ImportAmarok_toggled": (self.change, "amaroK"),
+ "on_ImportCancel": (self.change, ""),
+ }
+ self.wTree.signal_autoconnect(callbacks)
+
+ # Shade out jukeboxes that are not supported on this machine
+ if not opts.mod['xmms']:
+ if self.current.startswith('XMMS'):
+ self.current = ''
+ rbut = self.wTree.get_widget('ImportXMMS')
+ spinner = self.wTree.get_widget('XMMSSession')
+ rbut.set_active(False)
+ spinner.set_editable(False)
+
+ if not opts.bin['dcop']:
+ rbut = self.wTree.get_widget('ImportAmarok')
+ rbut.set_active(False)
+
+ def change(self, obj, arg):
+ self.current = arg
+
+ def run(self):
+ """Show the Import from Jukebox dialog."""
+ self.dlg.run()
+ name = self.current
+ if name == 'XMMS':
+ spinner = self.wTree.get_widget('XMMSSession')
+ name += ':' + str(int(spinner.get_value()))
+ self.dlg.destroy()
+ return name
+
+
+
file:a66f241dcb40389168fbaceaf859288713a797f5(new)
--- /dev/null
+++ b/mp3togo/gui/mainwindow.py
@@ -0,0 +1,266 @@
+# - gui/mainwindow.py --
+# GTK user interface - Main application window
+#
+# This file is part of mp3togo
+#
+# (c) Simeon Veldstra 2006 <reallifesim@gmail.com>
+#
+# This software is free.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You may redistribute this program under the terms of the
+# GNU General Public Licence version 2
+# Available in this package or at http://www.fsf.org
+
+
+try:
+ import pygtk
+ pygtk.require("2.0")
+ import gtk
+ import gtk.glade
+ import gobject
+except:
+ print "GTK not present! mp3togo GTK GUI requires python-gtk2 and python-glade2"
+ sys.exit(1)
+
+import sys
+import os
+import time
+import threading
+
+import mp3togo.util as util
+import mp3togo.conf as conf
+import mp3togo.filelist as filelist
+import mp3togo.pool as pool
+import mp3togo.track as track
+import mp3togo.task as task
+import mp3togo.cache as cache
+import mp3togo.cluster as cluster
+
+import mp3togo.gui.gutil as gutil
+import mp3togo.gui.filewindow as filewindow
+import mp3togo.gui.importwindow as importwindow
+import mp3togo.gui.playlist as playlist
+
+### Playlist Model: ['status', True, False, '/foo/bar/one.mp3'] ###
+STATUS = 0
+ABLE = 1
+SELECTED = 2
+FILE = 3
+NAME = 4
+
+
+class MainWind:
+ """The GUI Front end"""
+
+ def __init__(self, opts):
+ self.opts = opts
+ self.pool = pool.Pool(opts)
+ self.fails = {}
+ self.gang = []
+ self.gladexml = gutil.find_glade_xml(opts)
+
+ self.wTree = gtk.glade.XML(self.gladexml, "MainWindow")
+
+ view = self.wTree.get_widget("PlayListList")
+ self.list = playlist.PlayList(opts, view)
+
+ self.tips = gtk.Tooltips()
+
+ callbacks = {
+ "on_Exit": self.exit,
+ "on_MainWindow_destroy": self.exit,
+ "on_PlaylistAddFiles": self.add_files,
+ "on_PlaylistImport": self.import_files,
+ "on_PlaylistRemove": self.list.remove_selected,
+ "on_SelectAll": (self.list.select_all, True),
+ "on_SelectNone": (self.list.select_all, False),
+ "on_Configure": self.configure,
+ "on_Start": self.convert,
+ }
+ self.wTree.signal_autoconnect(callbacks)
+
+ # Set up worker processes:
+ self.workers = [('mp3togoGTK', '')]
+
+ self.window = self.wTree.get_widget("MainWindow")
+ if self.window:
+ self.window.show()
+
+ def select_all_playlist(self, obj=None):
+ """Select all"""
+ self.list.select_all(True)
+
+ def select_none_playlist(self, obj=None):
+ """Select None"""
+ self.list.select_all(False)
+
+ def add_files(self, obj):
+ """Callback to spawn fileselector"""
+ child = filewindow.AddFilesSelector(self.opts)
+ result = child.run()
+ if result:
+ self.list.addfiles(result)
+
+ def import_files(self, obj):
+ """callback to spawn file importer"""
+ child = importwindow.ImportDialog(self.opts)
+ result = child.run()
+ try:
+ # Move this into the list class
+ if result.startswith('XMMS'):
+ self.list.addXMMS(session=int(result.split(':')[1]))
+ elif result.startswith('amaroK'):
+ self.list.addAmarok()
+ except:
+ print "exception"
+
+ def convert(self, obj=None):
+ """Start the conversion"""
+ if not self.list._list:
+ return
+ # Set up cache
+ cooked = None
+
+ # Check for sanity
+ pass
+
+ for host in self.workers:
+ master = cluster.Boss(host[0],
+ self.list,
+ self.fails,
+ self.opts,
+ host[1])
+ self.gang.append({'boss': master,
+ 'poll': master.poll(),
+ 'file': ''})
+
+ def refresh_callback(self):
+ """Monitor the workers"""
+ if self.gang:
+ for slave in self.gang[:]:
+ try:
+ status = slave['poll'].next()
+ print status
+ except StopIteration:
+ self.set_progress(0.0)
+ if slave['file']:
+ self.list.finish(slave['file'])
+ del self.gang[self.gang.index(slave)]
+ break
+ if status[1] == 'Subtask Failed':
+ if slave['file']:
+ self.list.push(slave['file'])
+ self.set_status('Task failed')
+ break
+ if status[1] == 'Not Ready':
+ # Boss.kill() and restart?
+ break
+ if status[1] == 'Finished':
+ self.set_progress(0.0)
+ if slave['file']:
+ ts = util.format_time(status[2])
+ self.list.finish(slave['file'], ts)
+ self.set_status('Finished')
+ slave['file'] = ''
+ else:
+ if status[0] in self.list:
+ self.list.finish(status[0])
+ break
+ if status[0] != slave['file']:
+ if slave['file']:
+ self.list.finish(slave['file'])
+ slave['file'] = status[0]
+ #self.start_file(slave['file']) Boss calls pop()
+ self.set_fname(slave['file'])
+ break
+ # Just working
+ self.set_status(status[1]) # Current action
+ self.set_progress(status[2] / 100.0)
+ self.window.show_all()
+ return True
+ else:
+ return True
+
+
+ #wrap up
+ # def exec_thread():
+ # print "Bar"
+ # bar = self.wTree.get_widget("Progress")
+ # flabel = self.wTree.get_widget("CurrentFilename")
+ # while self.list:
+ # et = 0
+ # active = self.list.pop(0)
+ # print active
+ # self.start_file(active)
+ # flabel.set_label(active)
+ # trk = track.Track(active, self.opts, cooked)
+ # if self.pool.add_track(trk):
+ # tsk = trk.getfirst()
+ # while tsk:
+ # self.set_status(tsk.name)
+ # tsk.run()
+ # while tsk.status() == task.RUNNING:
+ # pcent = tsk.output()
+ # try:
+ # pcent = float(pcent) / 100.0
+ # except:
+ # pcent = 0.0
+ # bar.set_fraction(pcent)
+ # et += tsk.elapsed_time()
+ # tsk.wait()
+ # tsk = tsk.next()
+ # self.finish_file(active, format_time(et))
+ # else:
+ # self.set_status("Out of space")
+ # return
+ # self.set_status("Done")
+ # flabel.set_label("")
+
+ # self.machine = threading.Thread(None, exec_thread)
+ # self.machine.start()
+
+ def set_status(self, msg):
+ """Put text in the status label"""
+ self.status = msg
+ bar = self.wTree.get_widget("StatusText")
+ bar.set_label(msg)
+ bar.show()
+
+ def set_fname(self, name):
+ """Set the current filename label"""
+ flabel = self.wTree.get_widget("CurrentFile")
+ #if len(name) > 60:
+ # self.tips.set_tip(flabel, name)
+ # name = name[-60:]
+ flabel.set_label(name)
+ flabel.show()
+
+ def set_progress(self, percent):
+ """Update the progress bar"""
+ bar = self.wTree.get_widget("Progress")
+ bar.set_fraction(percent)
+ bar.show()
+
+ def configure(self):
+ """Callback to display configure window"""
+ child = Configure(self.opts)
+ result = child.run()
+ print result
+
+ def exit(self, obj):
+ """Exit, but don't leave a mess."""
+ gtk.main_quit()
+
+
+def start_gui(opts):
+ """Run the mp3togo PyGTK interface"""
+ gobject.threads_init()
+ gui = MainWind(opts)
+ gobject.idle_add(gui.refresh_callback)
+ gtk.main()
+
file:fdecc9728910716744e151cc921d746bde0390c3(new)
--- /dev/null
+++ b/mp3togo/gui/playlist.py
@@ -0,0 +1,233 @@
+# - gui/playlist.py --
+# GTK user interface - playlist widget
+#
+# This file is part of mp3togo
+#
+# (c) Simeon Veldstra 2006 <reallifesim@gmail.com>
+#
+# This software is free.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You may redistribute this program under the terms of the
+# GNU General Public Licence version 2
+# Available in this package or at http://www.fsf.org
+
+"""Manage the playlist widget"""
+
+try:
+ import pygtk
+ pygtk.require("2.0")
+ import gtk
+ import gtk.glade
+ import gobject
+except:
+ print "GTK not present! mp3togo GTK GUI requires python-gtk2 and python-glade2"
+ sys.exit(1)
+
+import sys
+import os
+
+import mp3togo.filelist as filelist
+import mp3togo.tags as tags
+
+import mp3togo.gui.gutil as gutil
+
+
+STATUS = 0
+ABLE = 1
+SELECT = 2
+NAME = 3
+FILE = 4
+
+
+class PlayList(filelist.FileList):
+ """manage a list of tracks"""
+
+ def __init__(self, opts, view):
+ """Create a playlist
+
+ opts is a conf.Options() instance
+ view is a gtk ListView widget"""
+
+ filelist.FileList.__init__(self, opts)
+ self.view = view
+ # add option to conf for this:
+ self.format = "[%x] %a - %t"
+ # STATUS, ABLE, SELECT, NAME, FILE
+ self.model = gtk.ListStore(str, bool, bool, str, str)
+
+ # Populate the ListStore widget
+ def cell_toggle(renderer, path, data):
+ new = self.model[path]
+ new[SELECT] = not new[SELECT]
+ self.model[path] = new
+ self._list[self.index(new[FILE])].selected = new[SELECT]
+ # Status Column
+ column = gtk.TreeViewColumn('Status',
+ gtk.CellRendererText(),
+ text=STATUS)
+ self.view.append_column(column)
+ # Select Column
+ toggle = gtk.CellRendererToggle()
+ toggle.set_property('activatable', True)
+ toggle.connect("toggled", cell_toggle, None)
+ column = gtk.TreeViewColumn('',
+ toggle,
+ activatable=ABLE,
+ active=SELECT)
+ self.view.append_column(column)
+ # Name Column
+ column = gtk.TreeViewColumn('Track',
+ gtk.CellRendererText(),
+ text=NAME)
+ self.view.append_column(column)
+ # Link data to widget
+ self.view.set_model(self.model)
+
+ def run(self):
+ pass
+
+ def __iter__(self):
+ """Iterate over a static list of waiting files"""
+ sl = self.tuple()
+ self._i = 0
+ for i in range(len(sl)):
+ yield sl[i]
+
+ def __contains__(self, name):
+ return name in [x.name for x in self._list]
+
+ def index(self, name):
+ """Return the index of a file in the list
+ Throws IndexError if not present."""
+ return filter(lambda x: x[1].name == name,
+ zip(range(len(self._list)), self._list))[0][0]
+
+ def tuple(self):
+ """Returns a tuple containing all the unstarted files"""
+ return [x.name for x in self._list if x.state == 'ready']
+
+ def _addfile(self, name):
+ """Add a file to self"""
+ name = self._opts.checkfile(name)
+ if name not in self:
+ entry = ListEntry(name, self._opts)
+ self._list.append(entry)
+ self.model.append(entry.as_model(self.format))
+
+ def _removefile(self, name):
+ """Remove a file from the list"""
+ try:
+ i = self.index(name)
+ except IndexError:
+ return
+ del self._list[i]
+ del self.model[i]
+
+ def pop(self, index=0):
+ """Pop a file off of the ready list and set its status
+ Raises IndexError like list.pop()"""
+ self._lock.acquire()
+ name = None
+ try:
+ name = self.tuple()[index]
+ i = self.index(name)
+ self._list[i].state = 'running'
+ self.model[i][STATUS] = ' ->'
+ self._list[i].selected = False
+ self.model[i][SELECT] = False
+ self._list[i].selectable = False
+ self.model[i][ABLE] = False
+ return name
+ finally:
+ self._lock.release()
+
+ def finish(self, name, elapsed='done'):
+ """Wrap up a finished file"""
+ self._lock.acquire()
+ try:
+ i = self.index(name)
+ self._list[i].state = 'done'
+ self.model[i][STATUS] = elapsed
+ self._list[i].selectable = True
+ self.model[i][ABLE] = True
+ finally:
+ self._lock.release()
+
+ def push(self, name):
+ """Put a file back in the ready list"""
+ self._lock.acquire()
+ try:
+ if name in self:
+ i = self.index(name)
+ self._list[i].state = 'ready'
+ self.model[i][STATUS] = ' '
+ self._list[i].selectable = True
+ self.model[i][ABLE] = True
+ else:
+ self._addfile(name)
+ finally:
+ self._lock.release()
+
+ def regenerate(self):
+ """Regenerate the model from the data"""
+ self._lock.acquire()
+ try:
+ self.model.clear()
+ for entry in self._list:
+ self.model.append(entry.as_model(self.format))
+ finally:
+ self._lock.release()
+
+ def select_all(self, obj, all):
+ """Select all if all=True none if all=False"""
+ self._lock.acquire()
+ try:
+ all = bool(all)
+ for i in range(len(self._list)):
+ self.model[i][SELECT] = all
+ self._list[i].selected = all
+ finally:
+ self._lock.release()
+
+ def remove_selected(self, obj=None):
+ self._lock.acquire()
+ try:
+ names = [x.name for x in self._list if x.selected]
+ for name in names:
+ i = self.index(name)
+ del self._list[i]
+ del self.model[i]
+ finally:
+ self._lock.release()
+
+
+class ListEntry:
+ """An item in a PlayList"""
+
+ def __init__(self, name, opts):
+ """Create a list entry"""
+ self.name = name
+ self.tags = tags.Tags(name, opts)
+ self.tags.read()
+ self.state = 'ready'
+ self.flag = ' '
+ self.selectable = True
+ self.selected = False
+
+ def as_model(self, fmt):
+ """The list entry in a form suitable for the ListStore widget"""
+ return [self.flag,
+ self.selectable,
+ self.selected,
+ self.tags.format(fmt),
+ self.name]
+
+
+
+
+
file:37c60f80e56193ccfe2497131e31cc8aa6e9515c -> file:be4cc09c4de3aafa21e651d8d61c3680ffd5546b
--- a/mp3togo/main.py
+++ b/mp3togo/main.py
@@ -33,6 +33,7 @@ import termios
import fcntl
import mp3togo
+import mp3togo.util as util
import mp3togo.filelist as filelist
import mp3togo.conf as conf
import mp3togo.track as track
@@ -41,6 +42,8 @@ import mp3togo.pool as pool
import mp3togo.cache as cache
import mp3togo.cluster as cluster
+import mp3togo.gui.mainwindow as mainwindow
+
def fail(mesg='', code=1):
if mesg:
@@ -56,6 +59,11 @@ def main(argv):
print conf.Options().usage()
fail(str(msg))
+ # Hand off control for gui interface
+ if opts['gui']:
+ gui = mainwindow.start_gui(opts)
+ return 0
+
# Cluster mode is handled in the cluster module
if opts['clusterslave']:
cluster.slave(opts)
@@ -215,7 +223,7 @@ def execute_sequential(playlist, opts, c
break
except IOError: pass
tm = tsk.elapsed_time()
- ts = format_time(tm)
+ ts = util.format_time(tm)
tsk.wait()
tryp("\r ")
if tsk.status() == task.DONE:
@@ -251,14 +259,14 @@ def execute_sequential(playlist, opts, c
del trk
tt = time.time() - track_start
- ts = format_time(tt)
+ ts = util.format_time(tt)
if ts:
tryp("Total time this track: %s\n\n" % ts)
else:
tryp('\n')
tm = time.time() - start_time
- ts = format_time(tm)
+ ts = util.format_time(tm)
if bad_ones:
if bad_ones == 1:
bad_str = ", 1 track failed."
file:fb9a82b927146b769758894ad5fc4be2f3ffc41a -> file:41c38e52135dd61eb50fff6d27d716768b0df691
--- a/mp3togo/tags.py
+++ b/mp3togo/tags.py
@@ -267,7 +267,9 @@ class Tags(UserDict.DictMixin):
%t Track title
%l Album title
%y Album release year
- %g Album genre"""
+ %g Album genre
+ %f Track file name
+ %x File extension """
if not self._lock.acquire(block) and not block:
return False
@@ -277,6 +279,8 @@ class Tags(UserDict.DictMixin):
'l': 'ALBUM',
'y': 'YEAR',
'g': 'GENRE_NAME'}
+ #'x': file extension
+ #'f': filename
#'z': Used for literal '%'
out = ""
@@ -290,6 +294,10 @@ class Tags(UserDict.DictMixin):
code = fmt[0] and fmt[0][0]
if code == 'z':
fmt[0] = '%' + fmt[0][1:]
+ elif code == 'f':
+ fmt[0] = self._file + fmt[0][1:]
+ elif code == 'x':
+ fmt[0] = self._type + fmt[0][1:]
elif code in esc.keys():
fmt[0] = self._tags.get(esc[code], ('',))[0] + fmt[0][1:]
else:
file:a81043dc5a799d17e259c8176f2647a4cdea9b22 -> file:2fd35d38de998f19d34802bde260b839f975312c
--- a/mp3togo/track.py
+++ b/mp3togo/track.py
@@ -37,7 +37,7 @@ FAILED = None
class Track:
"""Encapsulate the transformation of a file."""
- def __init__(self, filename, opts, cooked=None):
+ def __init__(self, filename, opts, cooked=None, intags=None):
self.bytes = 0
self._filename = filename
@@ -75,8 +75,11 @@ class Track:
# Read the tags
# Do this early so that 'treestructure' can access them
- self.tags = tags.Tags(filename, opts)
- self.tags.read()
+ if intags:
+ self.tags = intags
+ else:
+ self.tags = tags.Tags(filename, opts)
+ self.tags.read()
# Names
filetype = opts.getfiletype(filename)
file:6eeab17861140080cfda745ce0d1f96619affb54(new)
--- /dev/null
+++ b/mp3togo/util.py
@@ -0,0 +1,56 @@
+# - util.py -
+# General utility functions
+# This file is part of mp3togo
+#
+# (c) Simeon Veldstra 2006 <reallifesim@gmail.com>
+#
+# This software is free.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You may redistribute this program under the terms of the
+# GNU General Public Licence version 2
+# Available in this package or at http://www.fsf.org
+
+"""Utility functions for mp3togo"""
+
+import sys, os
+
+
+
+
+def format_time(tm):
+ """Convert a time from floating point seconds to H:M:S"""
+ tm = int(tm)
+ if tm:
+ hr, min, sec = (tm/3600, (tm%3600)/60, (tm%3600)%60)
+ ts = "%ds " % sec
+ if min > 0:
+ ts = ("%dm " % min) + ts
+ if hr > 0:
+ if min == 0:
+ ts = "0m " + ts
+ ts = ("%dh " % hr) + ts
+ return ts[:-1]
+ else:
+ return ''
+
+def format_bytes(bytes):
+ """Express a size in human readable format"""
+ k = 1024.0
+ m = 1024 * k
+ g = 1024 * m
+ if 0 < bytes < k:
+ ret = str(int(bytes/k)) + " KB"
+ elif k <= bytes < m:
+ ret = str(int(bytes/m)) + " MB"
+ elif m <= bytes < g:
+ ret = str(int(bytes/g)) + " GB"
+ else:
+ ret = str(bytes) + " Bytes"
+ return ret
+
+
file:a1c8eb5aa84f4348ae1f06c6636146b22d59af77 -> file:bc728c5927c86dad2262644b3c288d65cd6e18af
--- a/setup.py
+++ b/setup.py
@@ -72,9 +72,10 @@ use its components in another program.
The package installs a command line executable named mp3togo
in /usr/bin, for command line options, run `mp3togo --help`.""",
- packages = ["mp3togo"],
+ packages = ["mp3togo", "mp3togo.gui"],
#data_files = [('/usr/bin', ['bin/mp3togo'])],
scripts = ['bin/mp3togo'],
+ data_files = [('lib/mp3togo', ['lib/mp3togo.glade'])],
classifiers = [
'Development Status :: 4 - Beta',
'Environment :: Console',