Changeset aa6b1ec944ac

Show
Ignore:
Timestamp:
03/30/08 20:06:57 (8 months ago)
Author:
milosz@…
Branch:
trunk
Message:

* Graphics updates
* Add core dbus interface (startup/shutdown control)
* Add remote binary
* Work on track info module

Files:
1 added
18 modified

Legend:

Unmodified
Added
Removed
  • Makefile.am

    r85 r117  
    55# Main Service 
    66servicedir = $(DBUS_SERVICES_DIR) 
    7 service_in_files = org.beepmediaplayer.mpx.service.in 
    8 service_DATA = org.beepmediaplayer.mpx.service 
     7service_in_files = info.backtrace.mpx.service.in 
     8service_DATA = info.backtrace.mpx.service 
    99$(service_DATA): $(service_in_files) Makefile 
    1010        @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ 
     
    1212# Sentinel 
    1313sentineldir = $(DBUS_SERVICES_DIR) 
    14 sentinel_in_files = org.beepmediaplayer.mpxsentinel.service.in 
    15 sentinel_DATA = org.beepmediaplayer.mpxsentinel.service 
     14sentinel_in_files = info.backtrace.sentinel.service.in 
     15sentinel_DATA = info.backtrace.sentinel.service 
    1616$(sentinel_DATA): $(sentinel_in_files) Makefile 
    1717        @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ 
     
    5151        autogen.sh                                                                      \ 
    5252                                                                                                \ 
    53         org.beepmediaplayer.mpx.service.in                      \ 
    54         org.beepmediaplayer.mpxsentinel.service.in      \ 
     53        info.backtrace.mpx.service.in                           \ 
     54        info.backtrace.sentinel.service.in                      \ 
    5555                                                                                                \ 
    5656        mpx.1.in                                                                        \ 
  • configure.ac

    r116 r117  
    710710    icons/hicolor/24x24/stock/Makefile 
    711711 
     712        desktop/Makefile 
     713        desktop/mpx.desktop 
    712714    glade/Makefile 
    713715    images/Makefile 
     
    716718    mcs/Makefile 
    717719    python/Makefile 
     720        remote/Makefile 
    718721    scripts/Makefile 
    719722    widgets/Makefile 
  • icons/Makefile.am

    r20 r117  
    11SUBDIRS = hicolor 
     2 
     3iconsdir = $(datadir)/icons/hicolor/128x128/apps 
     4icons_DATA = mpx.png 
     5EXTRA_DIST = $(icons_DATA) 
  • mpx/Makefile.am

    r115 r117  
    198198mpx_bin_SOURCES += hal.hh hal.cc 
    199199endif 
     200 
     201built_header_make = \ 
     202        dbus-obj-MPX-glue.h 
     203 
     204EXTRA_DIST = \ 
     205        dbus-obj-MPX.xml 
     206 
     207dbus-obj-MPX-glue.h: dbus-obj-MPX.xml 
     208        @echo "* Generating /MPX DBus Glue" 
     209        @dbus-binding-tool --mode=glib-server --prefix=Player::DBusMPX::mpx \ 
     210    $(abs_top_builddir)/mpx/dbus-obj-MPX.xml > \ 
     211    dbus-obj-MPX-glue.h.temp 
     212        @cat dbus-obj-MPX-glue.h.temp   | sed s:G_BEGIN_DECLS:: | sed s:G_END_DECLS:: > \ 
     213    dbus-obj-MPX-glue.h.temp.1 
     214        @cat dbus-obj-MPX-glue.h.temp.1 | sed s/dbus_glib_Player\:\:DBusMPX\:\:mpx/dbus_glib_mpx/g > \ 
     215    dbus-obj-MPX-glue.h.temp.2 
     216        @cat dbus-obj-MPX-glue.h.temp.2 | sed s/dbus_glib_marshal_Player\:\:DBusMPX\:\:mpx/dbus_glib_marshal_mpx/g > \ 
     217    dbus-obj-MPX-glue.h 
     218        @rm -f dbus-obj-MPX-glue.h.temp 
     219        @rm -f dbus-obj-MPX-glue.h.temp.1 
     220        @rm -f dbus-obj-MPX-glue.h.temp.2 
  • mpx/mpx.cc

    r116 r117  
    760760namespace MPX 
    761761{ 
    762         void 
    763         Player::get_object (PAccess<MPX::Library> & pa) 
    764         { 
    765                 pa = PAccess<MPX::Library>(m_Library); 
    766         } 
    767  
    768         void     
    769         Player::get_object (PAccess<MPX::Amazon::Covers> & pa) 
    770         { 
    771                 pa = PAccess<MPX::Amazon::Covers>(m_Covers); 
    772         } 
    773  
    774     bool 
    775     Player::load_source_plugin (std::string const& path) 
     762#define TYPE_DBUS_OBJ_MPX (DBusMPX::get_type ()) 
     763#define DBUS_OBJ_MPX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_DBUS_OBJ_MPX, DBusMPX)) 
     764 
     765  struct DBusMPXClass 
     766  { 
     767    GObjectClass parent; 
     768  }; 
     769 
     770  struct Player::DBusMPX 
     771  { 
     772    GObject parent; 
     773    Player * player; 
     774 
     775    enum 
    776776    { 
    777                 enum 
     777      SIGNAL_STARTUP_COMPLETE, 
     778      SIGNAL_SHUTDOWN_COMPLETE, 
     779      SIGNAL_QUIT, 
     780      N_SIGNALS, 
     781    }; 
     782 
     783    static guint signals[N_SIGNALS]; 
     784 
     785    static gpointer parent_class; 
     786 
     787    static GType 
     788    get_type (); 
     789 
     790    static DBusMPX * 
     791    create (Player &, DBusGConnection*); 
     792 
     793    static void 
     794    class_init (gpointer klass, 
     795                gpointer class_data); 
     796 
     797    static GObject * 
     798    constructor (GType                   type, 
     799                 guint                   n_construct_properties, 
     800                 GObjectConstructParam * construct_properties); 
     801 
     802    static gboolean 
     803    ui_raise (DBusMPX * self, 
     804              GError **      error); 
     805 
     806    static gboolean 
     807    startup (DBusMPX * self, 
     808             int            no_network, 
     809             GError **      error); 
     810 
     811    static void 
     812    startup_complete (DBusMPX * self); 
     813   
     814    static void 
     815    shutdown_complete (DBusMPX * self); 
     816 
     817    static void 
     818    quit (DBusMPX * self); 
     819  }; 
     820 
     821  gpointer Player::DBusMPX::parent_class       = 0; 
     822  guint    Player::DBusMPX::signals[N_SIGNALS] = { 0 }; 
     823 
     824// HACK: Hackery to rename functions in glue 
     825#define mpx_startup     startup 
     826#define mpx_ui_raise    ui_raise 
     827 
     828#include "dbus-obj-MPX-glue.h" 
     829 
     830        void 
     831        Player::DBusMPX::class_init (gpointer klass, gpointer class_data) 
     832        { 
     833          parent_class = g_type_class_peek_parent (klass); 
     834 
     835          GObjectClass *gobject_class = reinterpret_cast<GObjectClass*>(klass); 
     836          gobject_class->constructor  = &DBusMPX::constructor; 
     837 
     838          signals[SIGNAL_STARTUP_COMPLETE] = 
     839                g_signal_new ("startup-complete", 
     840                                          G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)), 
     841                                          GSignalFlags (G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED), 
     842                                          0, 
     843                                          NULL, NULL, 
     844                                          g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); 
     845 
     846          signals[SIGNAL_SHUTDOWN_COMPLETE] = 
     847                g_signal_new ("shutdown-complete", 
     848                                          G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)), 
     849                                          GSignalFlags (G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED), 
     850                                          0, 
     851                                          NULL, NULL, 
     852                                          g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); 
     853 
     854          signals[SIGNAL_QUIT] = 
     855                g_signal_new ("quit", 
     856                                          G_OBJECT_CLASS_TYPE (G_OBJECT_CLASS (klass)), 
     857                                          GSignalFlags (G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED), 
     858                                          0, 
     859                                          NULL, NULL, 
     860                                          g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); 
     861        } 
     862 
     863        GObject * 
     864        Player::DBusMPX::constructor (GType                   type, 
     865                                                        guint                   n_construct_properties, 
     866                                                        GObjectConstructParam*  construct_properties) 
     867        { 
     868          GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type, n_construct_properties, construct_properties); 
     869 
     870          return object; 
     871        } 
     872 
     873        Player::DBusMPX * 
     874        Player::DBusMPX::create (Player & player, DBusGConnection * session_bus) 
     875        { 
     876                dbus_g_object_type_install_info (TYPE_DBUS_OBJ_MPX, &dbus_glib_mpx_object_info); 
     877 
     878                DBusMPX * self = DBUS_OBJ_MPX (g_object_new (TYPE_DBUS_OBJ_MPX, NULL)); 
     879                self->player = &player; 
     880 
     881          if(session_bus) 
     882          { 
     883                dbus_g_connection_register_g_object (session_bus, "/MPX", G_OBJECT(self)); 
     884                g_message("%s: /MPX Object registered on session DBus", G_STRLOC); 
     885          } 
     886 
     887          return self; 
     888        } 
     889 
     890        GType 
     891        Player::DBusMPX::get_type () 
     892        { 
     893          static GType type = 0; 
     894 
     895          if (G_UNLIKELY (type == 0)) 
    778896                { 
    779                         LIB_BASENAME, 
    780                         LIB_PLUGNAME, 
    781                         LIB_SUFFIX 
    782                 }; 
    783  
    784                 const std::string type = "mpxsource"; 
    785  
    786                 std::string basename (path_get_basename (path)); 
    787                 std::string pathname (path_get_dirname  (path)); 
    788  
    789                 if (!is_module (basename)) 
    790                         return false; 
    791  
    792                 StrV subs;  
    793                 split (subs, basename, is_any_of ("-.")); 
    794                 std::string name  = type + std::string("-") + subs[LIB_PLUGNAME]; 
    795                 std::string mpath = Module::build_path (build_filename(PLUGIN_DIR, "sources"), name); 
    796  
    797                 Module module (mpath, ModuleFlags (0));  
    798                 if (!module) 
    799                 { 
    800                         g_message("Source plugin load FAILURE '%s': %s", mpath.c_str (), module.get_last_error().c_str()); 
    801                         return false; 
     897                  static GTypeInfo const type_info = 
     898                        { 
     899                          sizeof (DBusMPXClass), 
     900                          NULL, 
     901                          NULL, 
     902                          &class_init, 
     903                          NULL, 
     904                          NULL, 
     905                          sizeof (DBusMPX), 
     906                          0, 
     907                          NULL 
     908                        }; 
     909 
     910                  type = g_type_register_static (G_TYPE_OBJECT, "MPX", &type_info, GTypeFlags (0)); 
    802911                } 
    803912 
    804                 g_message("LOADING Source plugin: %s", mpath.c_str ()); 
    805  
    806                 module.make_resident(); 
    807  
    808                 SourcePluginPtr plugin = SourcePluginPtr (new SourcePlugin()); 
    809                 if (!g_module_symbol (module.gobj(), "get_instance", (gpointer*)(&plugin->get_instance))) 
    810                 { 
    811           g_message("Source plugin load FAILURE '%s': get_instance hook missing", mpath.c_str ()); 
    812                   return false; 
    813                 } 
    814  
    815         if (!g_module_symbol (module.gobj(), "del_instance", (gpointer*)(&plugin->del_instance))) 
    816                 { 
    817           g_message("Source plugin load FAILURE '%s': del_instance hook missing", mpath.c_str ()); 
    818                   return false; 
    819                 } 
    820  
    821                  
    822         PlaybackSource * p = plugin->get_instance(*this);  
    823         Gtk::Alignment * a = new Gtk::Alignment; 
    824         p->get_ui()->reparent(*a); 
    825         a->show(); 
    826         m_ref_xml->get_widget("sourcepages", m_MainNotebook); 
    827         m_MainNotebook->append_page(*a); 
    828         m_Sources->addSource( p->get_name(), p->get_icon() ); 
    829                 m_SourceV.push_back(p); 
    830                 install_source(m_SourceCtr++, /* tab # */ m_PageCtr++); 
    831  
    832                 return false; 
    833     } 
    834  
    835         void 
    836         Player::on_volume_value_changed (double volume) 
    837         { 
    838                 m_Play->property_volume() = volume*100;  
    839                 mcs->key_set("mpx","volume", int(volume*100)); 
    840         } 
    841  
    842         bool 
    843         Player::on_seek_event (GdkEvent *event) 
    844         { 
    845           if( event->type == GDK_KEY_PRESS ) 
    846           { 
    847                           GdkEventKey * ev = ((GdkEventKey*)(event)); 
    848                           gint64 status = m_Play->property_status().get_value(); 
    849                           if((status == PLAYSTATUS_PLAYING) || (status == PLAYSTATUS_PAUSED)) 
    850                           { 
    851                                           gint64 pos = m_Play->property_position().get_value(); 
    852  
    853                                           int delta = (ev->state & GDK_SHIFT_MASK) ? 1 : 15; 
    854  
    855                                           if(ev->keyval == GDK_Left) 
    856                                           { 
    857                                                   m_Play->seek( pos - delta ); 
    858                                                   return true; 
    859                                           } 
    860                                           else if(ev->keyval == GDK_Right) 
    861                                           { 
    862                                                   m_Play->seek( pos + delta ); 
    863                                                   return true; 
    864                                           } 
    865                           } 
    866                           return false; 
    867           } 
    868           else if( event->type == GDK_BUTTON_PRESS ) 
    869           { 
    870                 g_atomic_int_set(&m_Seeking,1); 
    871                 goto SET_SEEK_POSITION; 
    872           } 
    873           else if( event->type == GDK_BUTTON_RELEASE && g_atomic_int_get(&m_Seeking)) 
    874           { 
    875                 g_atomic_int_set(&m_Seeking,0); 
    876                 m_Play->seek (gint64(m_Seek->get_value())); 
    877           } 
    878           else if( event->type == GDK_MOTION_NOTIFY && g_atomic_int_get(&m_Seeking)) 
    879           { 
    880                 SET_SEEK_POSITION: 
    881  
    882                 guint64 duration = m_Play->property_duration().get_value(); 
    883                 guint64 position = m_Seek->get_value(); 
    884  
    885                 guint64 m_pos = position / 60; 
    886                 guint64 m_dur = duration / 60; 
    887                 guint64 s_pos = position % 60; 
    888                 guint64 s_dur = duration % 60; 
    889  
    890                 static boost::format time_f ("%02d:%02d 
 %02d:%02d"); 
    891  
    892                 m_TimeLabel->set_text ((time_f % m_pos % s_pos % m_dur % s_dur).str()); 
    893           } 
    894           return false; 
    895         } 
    896  
    897         void 
    898         Player::on_play_metadata (MPXGstMetadataField field) 
    899         { 
    900                 MPXGstMetadata const& m = m_Play->get_metadata(); 
    901  
    902                 switch (field) 
    903                 { 
    904                   case FIELD_IMAGE: 
    905                         m_Metadata.Image = m.m_image.get(); 
    906                         m_InfoArea->set_image (m.m_image.get()->scale_simple (72, 72, Gdk::INTERP_HYPER)); 
    907                         return; 
    908          
    909                   case FIELD_TITLE: 
    910                         return; 
    911  
    912                   case FIELD_ALBUM: 
    913                         break; 
    914  
    915                   case FIELD_AUDIO_BITRATE: 
    916                         break; 
    917  
    918                   case FIELD_AUDIO_CODEC: 
    919                         break; 
    920  
    921                   case FIELD_VIDEO_CODEC: 
    922                         break; 
    923                 } 
    924         } 
    925  
    926         void 
    927         Player::on_play_position (guint64 position) 
    928         { 
    929           if (g_atomic_int_get(&m_Seeking)) 
    930                 return; 
    931  
    932           guint64 duration = m_Play->property_duration().get_value(); 
    933  
    934           if( (duration > 0) && (position <= duration) && (position >= 0) ) 
    935           { 
    936                 if (duration <= 0) 
    937                   return; 
    938  
    939                 if (position < 0) 
    940                   return; 
    941  
    942                 guint64 m_pos = position / 60; 
    943                 guint64 s_pos = position % 60; 
    944                 guint64 m_dur = duration / 60; 
    945                 guint64 s_dur = duration % 60; 
    946  
    947                 static boost::format time_f ("%02d:%02d 
 %02d:%02d"); 
    948  
    949                 m_TimeLabel->set_text((time_f % m_pos % s_pos % m_dur % s_dur).str()); 
    950                 m_Seek->set_range(0., duration); 
    951                 m_Seek->set_value(double (position)); 
    952  
    953 #if 0 
    954                 if( m_popup ) 
    955                 { 
    956                   m_popup->set_position (position, duration); 
    957                 } 
    958 #endif 
    959  
    960           } 
    961         } 
     913          return type; 
     914        } 
     915 
     916        gboolean 
     917        Player::DBusMPX::ui_raise (DBusMPX* self, GError** error) 
     918        { 
     919          return TRUE; 
     920        } 
     921 
     922        gboolean 
     923        Player::DBusMPX::startup  (DBusMPX*   self, 
     924                                                 int      no_network,  
     925                                                 GError** error) 
     926        { 
     927          return TRUE; 
     928        } 
     929 
     930        void 
     931        Player::DBusMPX::startup_complete (DBusMPX* self) 
     932        { 
     933          g_signal_emit (self, signals[SIGNAL_STARTUP_COMPLETE], 0); 
     934        } 
     935 
     936        void 
     937        Player::DBusMPX::shutdown_complete (DBusMPX* self) 
     938        { 
     939          g_signal_emit (self, signals[SIGNAL_SHUTDOWN_COMPLETE], 0); 
     940        } 
     941 
     942        void 
     943        Player::DBusMPX::quit (DBusMPX *self) 
     944        { 
     945          g_signal_emit (self, signals[SIGNAL_QUIT], 0); 
     946        } 
     947 
    962948 
    963949    Player::Player(Glib::RefPtr<Gnome::Glade::Xml> const& xml, 
     
    971957        , m_PageCtr(1) 
    972958   { 
     959                m_DiscDefault = Gdk::Pixbuf::create_from_file(build_filename(DATA_DIR, build_filename("images","disc-default.png")))->scale_simple(64,64,Gdk::INTERP_BILINEAR); 
     960 
     961                init_dbus (); 
     962                DBusObjects.mpx = DBusMPX::create(*this, m_SessionBus); 
     963 
    973964                try { 
    974965                        Py_Initialize(); 
     
    11841175                dynamic_cast<Gtk::ToggleButton*>(m_ref_xml->get_widget("sources-toggle"))->signal_toggled().connect( sigc::mem_fun( *this, &Player::on_sources_toggled ) ); 
    11851176 
    1186                 m_DiscDefault = Gdk::Pixbuf::create_from_file(build_filename(DATA_DIR, build_filename("images","disc-default.png")))->scale_simple(64,64,Gdk::INTERP_BILINEAR); 
     1177 
     1178                DBusObjects.mpx->startup_complete(DBusObjects.mpx);  
    11871179    } 
     1180 
     1181        void 
     1182        Player::init_dbus () 
     1183        { 
     1184                DBusGProxy * m_SessionBus_proxy; 
     1185                guint dbus_request_name_result; 
     1186                GError * error = NULL; 
     1187 
     1188                m_SessionBus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); 
     1189                if (!m_SessionBus) 
     1190                { 
     1191                  g_error_free (error); 
     1192                  return; 
     1193                } 
     1194 
     1195                m_SessionBus_proxy = dbus_g_proxy_new_for_name (m_SessionBus, 
     1196                                                                                                           "org.freedesktop.DBus", 
     1197                                                                                                           "/org/freedesktop/DBus", 
     1198                                                                                                           "org.freedesktop.DBus"); 
     1199 
     1200                if (!dbus_g_proxy_call (m_SessionBus_proxy, "RequestName", &error, 
     1201                                                                G_TYPE_STRING, "info.backtrace.mpx", 
     1202                                                                G_TYPE_UINT, 0, 
     1203                                                                G_TYPE_INVALID, 
     1204                                                                G_TYPE_UINT, &dbus_request_name_result, 
     1205                                                                G_TYPE_INVALID)) 
     1206                { 
     1207                  g_critical ("%s: RequestName Request Failed: %s", G_STRFUNC, error->message); 
     1208                  g_error_free (error); 
     1209                  error = NULL; 
     1210                } 
     1211                else 
     1212                { 
     1213                  switch (dbus_request_name_result) 
     1214                  { 
     1215                        case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER: 
     1216                        { 
     1217                          break; 
     1218                        } 
     1219 
     1220                        case DBUS_REQUEST_NAME_REPLY_EXISTS: 
     1221                        { 
     1222                          g_object_unref(m_SessionBus); 
     1223                          m_SessionBus = NULL; 
     1224                          return; 
     1225                        } 
     1226                  } 
     1227                } 
     1228 
     1229                g_message("%s: info.backtrace.mpx service registered on session DBus", G_STRLOC); 
     1230        } 
     1231 
     1232        void 
     1233        Player::get_object (PAccess<MPX::Library> & pa) 
     1234        { 
     1235                pa = PAccess<MPX::Library>(m_Library); 
     1236        } 
     1237 
     1238        void     
     1239        Player::get_object (PAccess<MPX::Amazon::Covers> & pa) 
     1240        { 
     1241                pa = PAccess<MPX::Amazon::Covers>(m_Covers); 
     1242        } 
     1243 
     1244    bool 
     1245    Player::load_source_plugin (std::string const& path) 
     1246    { 
     1247                enum 
     1248                { 
     1249                        LIB_BASENAME, 
     1250                        LIB_PLUGNAME, 
     1251                        LIB_SUFFIX 
     1252                }; 
     1253 
     1254                const std::string type = "mpxsource"; 
     1255 
     1256                std::string basename (path_get_basename (path)); 
     1257                std::string pathname (path_get_dirname  (path)); 
     1258 
     1259                if (!is_module (basename)) 
     1260                        return false; 
     1261 
     1262                StrV subs;  
     1263                split (subs, basename, is_any_of ("-.")); 
     1264                std::string name  = type + std::string("-") + subs[LIB_PLUGNAME]; 
     1265                std::string mpath = Module::build_path (build_filename(PLUGIN_DIR, "sources"), name); 
     1266 
     1267                Module module (mpath, ModuleFlags (0));  
     1268                if (!module) 
     1269                { 
     1270                        g_message("Source plugin load FAILURE '%s': %s", mpath.c_str (), module.get_last_error().c_str()); 
     1271                        return false; 
     1272                } 
     1273 
     1274                g_message("LOADING Source plugin: %s", mpath.c_str ()); 
     1275 
     1276                module.make_resident(); 
     1277 
     1278                SourcePluginPtr plugin = SourcePluginPtr (new SourcePlugin()); 
     1279                if (!g_module_symbol (module.gobj(), "get_instance", (gpointer*)(&plugin->get_instance))) 
     1280                { 
     1281          g_message("Source plugin load FAILURE '%s': get_instance hook missing", mpath.c_str ()); 
     1282                  return false; 
     1283                } 
     1284 
     1285        if (!g_module_symbol (module.gobj(), "del_instance", (gpointer*)(&plugin->del_instance))) 
     1286                { 
     1287          g_message("Source plugin load FAILURE '%s': del_instance hook missing", mpath.c_str ()); 
     1288                  return false; 
     1289                } 
     1290 
     1291                 
     1292        PlaybackSource * p = plugin->get_instance(*this);  
     1293        Gtk::Alignment * a = new Gtk::Alignment; 
     1294        p->get_ui()->reparent(*a); 
     1295        a->show(); 
     1296        m_ref_xml->get_widget("sourcepages", m_MainNotebook); 
     1297        m_MainNotebook->append_page(*a); 
     1298        m_Sources->addSource( p->get_name(), p->get_icon() ); 
     1299                m_SourceV.push_back(p); 
     1300                install_source(m_SourceCtr++, /* tab # */ m_PageCtr++); 
     1301 
     1302                return false; 
     1303    } 
     1304 
     1305        void 
     1306        Player::on_volume_value_changed (double volume) 
     1307        { 
     1308                m_Play->property_volume() = volume*100;  
     1309                mcs->key_set("mpx","volume", int(volume*100)); 
     1310        } 
     1311 
     1312        bool 
     1313        Player::on_seek_event (GdkEvent *event)