banshee r3770 - in trunk/banshee: . libbanshee src/Backends/Banshee.GStreamer src/Backends/Banshee.GStreamer/Banshee.GStreamer src/Clients/Nereid/Nereid src/Core/Banshee.Services/Banshee.Sources src/Core/Banshee.ThickClient src/Core/Banshee.ThickClient/Banshee.Collection.Gui src/Core/Banshee.ThickClient/Banshee.Gui src/Core/Banshee.ThickClient/Banshee.Gui.Widgets src/Core/Banshee.ThickClient/Resources src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea src/Extensions/Banshee.NotificationArea/Resources src/Libraries/Hyena/Hyena



Author: abock
Date: Sat Apr 12 00:09:08 2008
New Revision: 3770
URL: http://svn.gnome.org/viewvc/banshee?rev=3770&view=rev

Log:
2008-04-11  Aaron Bockover  <abock gnome org>

    * libbanshee/banshee-gst.c:
    * libbanshee/banshee-gst.h: Implemented our own logging functions that
    can call a handler function which is defined in managed code; this allows
    libbanshee to use the same logging facilities that are available to managed
    code

    * src/Backends/Banshee.GStreamer/Banshee.GStreamer/Service.cs: Implement
    the native logging function and proxy calls to the Hyena logger

    * libbanshee/banshee-player-private.h: Made the bp_debug macro expand to
    the new native logging function

    * src/Libraries/Hyena/Hyena/Log.cs: Made Commit method public

    * src/Clients/Nereid/Nereid/PlayerInterface.cs: Pack the status label in
    an EventBox; when the event box is clicked, call CycleStatusFormat on
    the active source; use the new MainMenu widget instead of fetching it
    directly from the UI manager

    * src/Core/Banshee.Services/Banshee.Sources/Source.cs: Implemented
    CycleStatusFormat and some supporting properties; and two new status
    formatters for time; added a ConfigurationId property

    * src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs:
    Use the Source.ConfigurationId property

    * src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/MainMenu.cs: Load the
    main menu from the UI manager and connect the new repeat and shuffle menus

    * src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs:
    Split FindAction into a FindActionGroup method

    * src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackRepeatActions.cs:
    * src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackShuffleActions.cs:
    Implemented CreateSubmenu and AttachSubmenu methods

    * src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs: Add some
    NRE defenses

    * src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml:
    Removed the hardcoded menu entries for shuffle and repeat

    * src/Extensions/Banshee.NotificationArea/Resources/NotificationAreaMenu.xm:
    * src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea/NotificationAreaService.cs:
    Added shuffle and repeat menus back to the tray menu



Added:
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/MainMenu.cs
Modified:
   trunk/banshee/ChangeLog
   trunk/banshee/libbanshee/banshee-gst.c
   trunk/banshee/libbanshee/banshee-gst.h
   trunk/banshee/libbanshee/banshee-player-private.h
   trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer.mdp
   trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/Service.cs
   trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs
   trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackRepeatActions.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackShuffleActions.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
   trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
   trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
   trunk/banshee/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml
   trunk/banshee/src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea/NotificationAreaService.cs
   trunk/banshee/src/Extensions/Banshee.NotificationArea/Resources/NotificationAreaMenu.xml
   trunk/banshee/src/Libraries/Hyena/Hyena/Log.cs

Modified: trunk/banshee/libbanshee/banshee-gst.c
==============================================================================
--- trunk/banshee/libbanshee/banshee-gst.c	(original)
+++ trunk/banshee/libbanshee/banshee-gst.c	Sat Apr 12 00:09:08 2008
@@ -34,6 +34,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
+#include <stdarg.h>
 
 #include <gst/gst.h>
 
@@ -43,17 +44,29 @@
 #  include <gst/pbutils/pbutils.h>
 #endif
 
+typedef enum {
+    BANSHEE_LOG_TYPE_DEBUG,
+    BANSHEE_LOG_TYPE_WARNING,
+    BANSHEE_LOG_TYPE_INFORMATION,
+    BANSHEE_LOG_TYPE_ERROR
+} BansheeLogType;
+
+typedef void (* BansheeLogHandler) (BansheeLogType type, const gchar *component, const gchar *message);
+
 static gboolean gstreamer_initialized = FALSE;
 static gboolean banshee_debugging;
+static BansheeLogHandler banshee_log_handler = NULL;
 static gint banshee_version = -1;
 
-void gstreamer_initialize (gboolean debugging)
+void 
+gstreamer_initialize (gboolean debugging, BansheeLogHandler log_handler)
 {
     if (gstreamer_initialized) {
         return;
     }
     
     banshee_debugging = debugging;
+    banshee_log_handler = log_handler;
 
     gst_init (NULL, NULL);
     
@@ -106,3 +119,37 @@
     
     return (guint)banshee_version;
 }
+
+static void
+banshee_log (BansheeLogType type, const gchar *component, const gchar *message)
+{
+    if (banshee_log_handler == NULL) {
+        switch (type) {
+            case BANSHEE_LOG_TYPE_WARNING: g_warning ("%s: %s", component, message); break;
+            case BANSHEE_LOG_TYPE_ERROR:   g_error ("%s: %s", component, message); break;
+            default:                       g_debug ("%s: %s", component, message); break;
+        }
+        return;
+    }
+    
+    (banshee_log_handler) (type, component, message);
+}
+
+void
+banshee_log_debug (const gchar *component, const gchar *format, ...)
+{
+    va_list args;
+    gchar *message;
+    
+    if (!banshee_debugging) {
+        return;
+    }
+    
+    va_start (args, format);
+    message = g_strdup_vprintf (format, args);
+    va_end (args);
+    
+    banshee_log (BANSHEE_LOG_TYPE_DEBUG, component, message);
+    
+    g_free (message);
+}

Modified: trunk/banshee/libbanshee/banshee-gst.h
==============================================================================
--- trunk/banshee/libbanshee/banshee-gst.h	(original)
+++ trunk/banshee/libbanshee/banshee-gst.h	Sat Apr 12 00:09:08 2008
@@ -34,4 +34,6 @@
 gboolean  banshee_is_debugging ();
 guint     banshee_get_version_number ();
 
+void      banshee_log_debug (const gchar *component, const gchar *format, ...);
+
 #endif /* _BANSHEE_GST_H */

Modified: trunk/banshee/libbanshee/banshee-player-private.h
==============================================================================
--- trunk/banshee/libbanshee/banshee-player-private.h	(original)
+++ trunk/banshee/libbanshee/banshee-player-private.h	Sat Apr 12 00:09:08 2008
@@ -46,11 +46,13 @@
 #  include <gst/interfaces/xoverlay.h>
 #endif
 
+#include "banshee-gst.h"
+
 #define P_INVOKE
 #define IS_BANSHEE_PLAYER(e) (e != NULL)
 #define SET_CALLBACK(cb_name) { if(player != NULL) { player->cb_name = cb; } }
 
-#define bp_debug g_debug
+#define bp_debug(x...) banshee_log_debug ("player", x)
 
 typedef struct BansheePlayer BansheePlayer;
 

Modified: trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer.mdp
==============================================================================
--- trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer.mdp	(original)
+++ trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer.mdp	Sat Apr 12 00:09:08 2008
@@ -23,6 +23,7 @@
     <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.8.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
     <ProjectReference type="Project" localcopy="False" refto="Banshee.Services" />
     <ProjectReference type="Project" localcopy="False" refto="Banshee.Core" />
+    <ProjectReference type="Project" localcopy="True" refto="Hyena" />
   </References>
   <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="True" RelativeMakefileName="Makefile.am">
     <BuildFilesVar Sync="True" Name="SOURCES" />

Modified: trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/Service.cs
==============================================================================
--- trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/Service.cs	(original)
+++ trunk/banshee/src/Backends/Banshee.GStreamer/Banshee.GStreamer/Service.cs	Sat Apr 12 00:09:08 2008
@@ -31,6 +31,7 @@
 using System.Collections.Generic;
 using System.Runtime.InteropServices;
 
+using Hyena;
 using Hyena.SExpEngine;
 using Banshee.ServiceStack;
 using Banshee.MediaProfiles;
@@ -39,16 +40,25 @@
 {
     public class Service : IExtensionService
     {
+        private delegate void BansheeLogHandler (LogEntryType type, IntPtr component, IntPtr message);
+        
+        private BansheeLogHandler native_log_handler = null;
+        
         public Service ()
         {
         }
         
         [DllImport ("libbanshee")]
-        private static extern void gstreamer_initialize (bool debugging);
+        private static extern void gstreamer_initialize (bool debugging, BansheeLogHandler log_handler);
         
         void IExtensionService.Initialize ()
         {
-            gstreamer_initialize (Banshee.Base.ApplicationContext.Debugging);
+            bool debugging = Banshee.Base.ApplicationContext.Debugging;
+            if (debugging) {
+                native_log_handler = new BansheeLogHandler (NativeLogHandler);
+            }
+            
+            gstreamer_initialize (debugging, native_log_handler);
             
             MediaProfileManager profile_manager = ServiceManager.MediaProfileManager;
             if (profile_manager != null) {
@@ -62,6 +72,20 @@
             }
         }
         
+        private void NativeLogHandler (LogEntryType type, IntPtr componentPtr, IntPtr messagePtr)
+        {
+            string component = componentPtr == IntPtr.Zero ? null : GLib.Marshaller.Utf8PtrToString (componentPtr);
+            string message = componentPtr == IntPtr.Zero ? null : GLib.Marshaller.Utf8PtrToString (messagePtr);
+            
+            if (message == null) {
+                return;
+            } else if (component != null) {
+                message = String.Format ("(libbanshee:{0}) {1}", component, message);
+            }
+            
+            Log.Commit (type, message, null, false);
+        }
+        
         private static void OnTestMediaProfile (object o, TestProfileArgs args)
         {
             bool no_test = Banshee.Base.ApplicationContext.EnvironmentIsSet ("BANSHEE_PROFILES_NO_TEST");

Modified: trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs
==============================================================================
--- trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs	(original)
+++ trunk/banshee/src/Clients/Nereid/Nereid/PlayerInterface.cs	Sat Apr 12 00:09:08 2008
@@ -120,7 +120,7 @@
         {
             primary_vbox = new VBox ();
             
-            Widget menu = ActionService.UIManager.GetWidget ("/MainMenu");
+            Widget menu = new MainMenu ();
             menu.Show ();
             primary_vbox.PackStart (menu, false, false, 0);
            
@@ -205,10 +205,19 @@
             footer_toolbar.ShowArrow = false;
             footer_toolbar.ToolbarStyle = ToolbarStyle.BothHoriz;
 
+            EventBox status_event_box = new EventBox ();
+            status_event_box.ButtonPressEvent += delegate (object o, ButtonPressEventArgs args) {
+                Source source = ServiceManager.SourceManager.ActiveSource;
+                if (source != null) {
+                    source.CycleStatusFormat ();
+                    UpdateStatusBar ();
+                }
+            };
             status_label = new Label ();
+            status_event_box.Add (status_label);
             
             Alignment status_align = new Alignment (0.5f, 0.5f, 1.0f, 1.0f);
-            status_align.Add (status_label);
+            status_align.Add (status_event_box);
 
             RepeatActionButton repeat_button = new RepeatActionButton ();
             repeat_button.SizeAllocated += delegate (object o, Gtk.SizeAllocatedArgs args) {

Modified: trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	(original)
+++ trunk/banshee/src/Core/Banshee.Services/Banshee.Sources/Source.cs	Sat Apr 12 00:09:08 2008
@@ -40,6 +40,7 @@
 
 using Banshee.Base;
 using Banshee.Collection;
+using Banshee.Configuration;
 using Banshee.ServiceStack;
 
 namespace Banshee.Sources
@@ -494,8 +495,31 @@
         public virtual int Count {
             get { return 0; }
         }
+        
+        public string ConfigurationId {
+            get { return (Parent == null ? UniqueId : Parent.UniqueId).Replace ('.', '_'); }
+        }
 
         public virtual int FilteredCount { get { return Count; } }
+        
+        protected virtual int StatusFormatsCount {
+            get { return 3; }
+        }
+        
+        protected virtual int CurrentStatusFormat {
+            get { return ConfigurationClient.Get<int> (String.Format ("sources.{0}", ConfigurationId), "status_format", 0); }
+            set { ConfigurationClient.Set<int> (String.Format ("sources.{0}", ConfigurationId), "status_format", value); }
+        }
+        
+        public void CycleStatusFormat ()
+        {
+            int new_status_format = CurrentStatusFormat + 1;
+            if (new_status_format >= StatusFormatsCount) {
+                new_status_format = 0;
+            }
+            
+            CurrentStatusFormat = new_status_format;
+        }
 
         public virtual string GetStatusText ()
         {
@@ -512,16 +536,45 @@
             if (this is IDurationAggregator) {
                 builder.Append (", ");
 
-                TimeSpan span = (this as IDurationAggregator).Duration; 
-                if (span.Days > 0) {
-                    double days = span.Days + (span.Hours / 24.0);
-                    builder.AppendFormat (Catalog.GetPluralString ("{0} day", "{0} days", DoubleToPluralInt (days)), FormatDouble (days));
-                } else if (span.Hours > 0) {
-                    double hours = span.Hours + (span.Minutes / 60.0);
-                    builder.AppendFormat (Catalog.GetPluralString ("{0} hour", "{0} hours", DoubleToPluralInt (hours)), FormatDouble (hours));
-                } else {
-                    double minutes = span.Minutes + (span.Seconds / 60.0);
-                    builder.AppendFormat (Catalog.GetPluralString ("{0} minute", "{0} minutes", DoubleToPluralInt (minutes)), FormatDouble (minutes));
+                TimeSpan span = (this as IDurationAggregator).Duration;
+                int format = CurrentStatusFormat;
+                
+                if (format == 0) {
+                    if (span.Days > 0) {
+                        double days = span.Days + (span.Hours / 24.0);
+                        builder.AppendFormat (Catalog.GetPluralString ("{0} day", "{0} days", 
+                            DoubleToPluralInt (days)), FormatDouble (days));
+                    } else if (span.Hours > 0) {
+                        double hours = span.Hours + (span.Minutes / 60.0);
+                        builder.AppendFormat (Catalog.GetPluralString ("{0} hour", "{0} hours", 
+                            DoubleToPluralInt (hours)), FormatDouble (hours));
+                    } else {
+                        double minutes = span.Minutes + (span.Seconds / 60.0);
+                        builder.AppendFormat (Catalog.GetPluralString ("{0} minute", "{0} minutes", 
+                            DoubleToPluralInt (minutes)), FormatDouble (minutes));
+                    }
+                } else if (format == 1) {
+                    if (span.Days > 0) {
+                        builder.AppendFormat (Catalog.GetPluralString ("{0} day", "{0} days", span.Days), span.Days);
+                        builder.Append (", ");
+                    }
+                    
+                    if (span.Hours > 0) {
+                        builder.AppendFormat(Catalog.GetPluralString ("{0} hour", "{0} hours", span.Hours), span.Hours);
+                        builder.Append (", ");
+                    }
+
+                    builder.AppendFormat (Catalog.GetPluralString ("{0} minute", "{0} minutes", span.Minutes), span.Minutes);
+                    builder.Append (", ");
+                    builder.AppendFormat (Catalog.GetPluralString ("{0} second", "{0} seconds", span.Seconds), span.Seconds);
+                } else if (format == 2) {
+                    if (span.Days > 0) {
+                        builder.AppendFormat ("{0}:{1:00}:", span.Days, span.Hours);
+                    } else if (span.Hours > 0) {
+                        builder.AppendFormat ("{0}:", span.Hours);
+                    }
+                    
+                    builder.AppendFormat ("{0:00}:{1:00}", span.Minutes, span.Seconds);
                 }
             }
 

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Collection.Gui/PersistentColumnController.cs	Sat Apr 12 00:09:08 2008
@@ -60,7 +60,7 @@
                 
                 if (source != null) {
                     // If we have a parent, use their UniqueId so all children of a parent persist the same columns
-                    source_id = (source.Parent == null ? source.UniqueId : source.Parent.UniqueId).Replace ('.', '_');
+                    source_id = source.ConfigurationId;
                     Load ();
                 }
             }

Added: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/MainMenu.cs
==============================================================================
--- (empty file)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui.Widgets/MainMenu.cs	Sat Apr 12 00:09:08 2008
@@ -0,0 +1,55 @@
+//
+// MainMenu.cs
+//
+// Author:
+//   Aaron Bockover <abockover novell com>
+//
+// Copyright (C) 2008 Novell, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using Gtk;
+
+using Banshee.ServiceStack;
+using Banshee.Gui;
+
+namespace Banshee.Gui.Widgets
+{
+    public class MainMenu : VBox
+    {
+        public MainMenu ()
+        {
+            InterfaceActionService interface_service = ServiceManager.Get<InterfaceActionService> ();
+            
+            MenuShell menu = (MenuShell)interface_service.UIManager.GetWidget ("/MainMenu");
+            
+            ((PlaybackRepeatActions)interface_service.FindActionGroup ("PlaybackRepeat")).AttachSubmenu (
+                "/MainMenu/PlaybackMenu/RepeatMenu");
+                
+            ((PlaybackShuffleActions)interface_service.FindActionGroup ("PlaybackShuffle")).AttachSubmenu (
+                "/MainMenu/PlaybackMenu/ShuffleMenu");
+            
+            menu.Show ();
+            PackStart (menu, true, true, 0);
+        }
+    }
+}

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/InterfaceActionService.cs	Sat Apr 12 00:09:08 2008
@@ -111,6 +111,17 @@
             }
         }
         
+        public ActionGroup FindActionGroup (string actionGroupId)
+        {
+            foreach (ActionGroup group in action_groups.Values) {
+                if (group.Name == actionGroupId) {
+                    return group;
+                }
+            }
+            
+            return null;
+        }
+        
         public Action FindAction (string actionId)
         {
             string [] parts = actionId.Split ('.');
@@ -122,15 +133,8 @@
             string group_name = parts[0];
             string action_name = parts[1];
             
-            foreach (ActionGroup group in action_groups.Values) {
-                if (group.Name != group_name) {
-                    continue;
-                }
-                
-                return group.GetAction (action_name);
-            }
-            
-            return null;
+            ActionGroup group = FindActionGroup (group_name);
+            return group == null ? null : group.GetAction (action_name);
         }
         
         public void PopulateToolbarPlaceholder (Toolbar toolbar, string path, Widget item)

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackRepeatActions.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackRepeatActions.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackRepeatActions.cs	Sat Apr 12 00:09:08 2008
@@ -42,8 +42,9 @@
 {
     public class PlaybackRepeatActions : BansheeActionGroup, IEnumerable<RadioAction>
     {
+        private InterfaceActionService action_service;
         private RadioAction active_action;
-
+        
         public RadioAction Active {
             get { return active_action; }
             set {
@@ -57,11 +58,18 @@
         
         public PlaybackRepeatActions (InterfaceActionService actionService) : base ("PlaybackRepeat")
         {
+            action_service = actionService;
             actionService.AddActionGroup (this);
+            
+            Add (new ActionEntry [] {
+                new ActionEntry ("RepeatMenuAction", null,
+                    Catalog.GetString ("Repeat"), null,
+                    Catalog.GetString ("Repeat"), null)
+            });
 
             Add (new RadioActionEntry [] {
                 new RadioActionEntry ("RepeatNoneAction", null, 
-                    Catalog.GetString ("Repeat N_one"), null,
+                    Catalog.GetString ("Repeat _Off"), null,
                     Catalog.GetString ("Do not repeat playlist"),
                     (int)PlaybackRepeatMode.None),
                     
@@ -99,12 +107,30 @@
                 handler (o, args);
             }
         }
+        
+        public void AttachSubmenu (string menuItemPath)
+        {
+            MenuItem parent = action_service.UIManager.GetWidget (menuItemPath) as MenuItem;
+            parent.Submenu = CreateMenu ();
+        }
+        
+        public MenuItem CreateSubmenu ()
+        {
+            MenuItem parent = (MenuItem)this["RepeatMenuAction"].CreateMenuItem ();
+            parent.Submenu = CreateMenu ();
+            return parent;
+        }
             
         public Menu CreateMenu ()
         {
             Menu menu = new Gtk.Menu ();
+            bool separator = false;
             foreach (RadioAction action in this) {
                 menu.Append (action.CreateMenuItem ());
+                if (!separator) {
+                    separator = true;
+                    menu.Append (new SeparatorMenuItem ());
+                }
             }
             menu.ShowAll ();
             return menu;

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackShuffleActions.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackShuffleActions.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/PlaybackShuffleActions.cs	Sat Apr 12 00:09:08 2008
@@ -44,6 +44,7 @@
     {
         private RadioAction active_action;
         private PlaybackActions playback_actions;
+        private InterfaceActionService action_service;
 
         public RadioAction Active {
             get { return active_action; }
@@ -60,7 +61,14 @@
             : base ("PlaybackShuffle")
         {
             playback_actions = playbackActions;
+            action_service = actionService;
             actionService.AddActionGroup (this);
+            
+            Add (new ActionEntry [] {
+                new ActionEntry ("ShuffleMenuAction", null,
+                    Catalog.GetString ("Shuffle"), null,
+                    Catalog.GetString ("Shuffle"), null)
+            });
 
             Add (new RadioActionEntry [] {
                 new RadioActionEntry ("ShuffleOffAction", null, 
@@ -112,15 +120,31 @@
                 handler (o, args);
             }
         }
+        
+        public void AttachSubmenu (string menuItemPath)
+        {
+            MenuItem parent = action_service.UIManager.GetWidget (menuItemPath) as MenuItem;
+            parent.Submenu = CreateMenu ();
+        }
+        
+        public MenuItem CreateSubmenu ()
+        {
+            MenuItem parent = (MenuItem)this["ShuffleMenuAction"].CreateMenuItem ();
+            parent.Submenu = CreateMenu ();
+            return parent;
+        }
             
         public Menu CreateMenu ()
         {
-            Menu menu = new Menu ();
-            menu.Append (this["ShuffleOffAction"].CreateMenuItem ());
-            menu.Append (new SeparatorMenuItem ());
-            menu.Append (this["ShuffleSongAction"].CreateMenuItem ());
-            menu.Append (this["ShuffleArtistAction"].CreateMenuItem ());
-            menu.Append (this["ShuffleAlbumAction"].CreateMenuItem ());
+            Menu menu = new Gtk.Menu ();
+            bool separator = false;
+            foreach (RadioAction action in this) {
+                menu.Append (action.CreateMenuItem ());
+                if (!separator) {
+                    separator = true;
+                    menu.Append (new SeparatorMenuItem ());
+                }
+            }
             menu.ShowAll ();
             return menu;
         }

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.Gui/TrackActions.cs	Sat Apr 12 00:09:08 2008
@@ -197,6 +197,10 @@
 
         private void UpdateActions ()
         {
+            if (TrackSelector == null || TrackSelector.TrackSelectionProxy == null) {
+                return;
+            }
+            
             Hyena.Collections.Selection selection = TrackSelector.TrackSelectionProxy.Selection;
             Source source = ServiceManager.SourceManager.ActiveSource;
             bool in_database = source is DatabaseSource;

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Banshee.ThickClient.mdp	Sat Apr 12 00:09:08 2008
@@ -97,6 +97,7 @@
     <File name="Banshee.Gui.Dialogs/ExtensionManagerDialog.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Gui/PersistentPaneController.cs" subtype="Code" buildaction="Compile" />
     <File name="Banshee.Collection.Gui/ColumnCellPositiveInt.cs" subtype="Code" buildaction="Compile" />
+    <File name="Banshee.Gui.Widgets/MainMenu.cs" subtype="Code" buildaction="Compile" />
   </Contents>
   <References>
     <ProjectReference type="Project" localcopy="False" refto="Hyena.Gui" />

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Makefile.am	Sat Apr 12 00:09:08 2008
@@ -42,6 +42,7 @@
 	Banshee.Gui.Widgets/ConnectedMessageBar.cs \
 	Banshee.Gui.Widgets/ConnectedSeekSlider.cs \
 	Banshee.Gui.Widgets/ConnectedVolumeButton.cs \
+	Banshee.Gui.Widgets/MainMenu.cs \
 	Banshee.Gui.Widgets/PlaylistMenuItem.cs \
 	Banshee.Gui.Widgets/RepeatActionButton.cs \
 	Banshee.Gui.Widgets/TrackInfoDisplay.cs \

Modified: trunk/banshee/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml
==============================================================================
--- trunk/banshee/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml	(original)
+++ trunk/banshee/src/Core/Banshee.ThickClient/Resources/core-ui-actions-layout.xml	Sat Apr 12 00:09:08 2008
@@ -75,14 +75,8 @@
       <menuitem name="RestartSong" action="RestartSongAction"/>
       <separator/>
       <placeholder name="PlaybackMenuAdditions"/>
-      <menuitem name="RepeatNone" action="RepeatNoneAction"/>
-      <menuitem name="RepeatAll" action="RepeatAllAction"/>
-      <menuitem name="RepeatSingle" action="RepeatSingleAction"/>
-      <separator/>
-      <menuitem name="ShuffleOff" action="ShuffleOffAction"/>
-      <menuitem name="ShuffleSong" action="ShuffleSongAction"/>
-      <menuitem name="ShuffleArtist" action="ShuffleArtistAction"/>
-      <menuitem name="ShuffleAlbum" action="ShuffleAlbumAction"/>
+      <menuitem name="RepeatMenu" action="RepeatMenuAction"/>
+      <menuitem name="ShuffleMenu" action="ShuffleMenuAction"/>
     </menu>
     
     <menu name="ToolsMenu" action="ToolsMenuAction">

Modified: trunk/banshee/src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea/NotificationAreaService.cs
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea/NotificationAreaService.cs	(original)
+++ trunk/banshee/src/Extensions/Banshee.NotificationArea/Banshee.NotificationArea/NotificationAreaService.cs	Sat Apr 12 00:09:08 2008
@@ -131,6 +131,23 @@
             
             for (int i = 0; i < menu.Children.Length; i++) {
                 if (menu.Children[i].Name == "Next") {
+                    int j = i;
+                    PlaybackRepeatActions repeat_group = interface_action_service.FindActionGroup ("PlaybackRepeat")
+                         as PlaybackRepeatActions;
+                    if (repeat_group != null) {
+                        menu.Insert (repeat_group.CreateSubmenu (), i++ + 2);
+                    }
+                    
+                    PlaybackShuffleActions shuffle_group = interface_action_service.FindActionGroup ("PlaybackShuffle")
+                         as PlaybackShuffleActions;
+                    if (shuffle_group != null) {
+                        menu.Insert (shuffle_group.CreateSubmenu (), i++ + 2);
+                    }
+                    
+                    if (j != i) {
+                        menu.Insert (new SeparatorMenuItem (), i++ + 2);
+                    }
+                    
                     rating_menu_item = new RatingMenuItem ();
                     rating_menu_item.Activated += OnItemRatingActivated;
                     ToggleRatingMenuSensitive ();

Modified: trunk/banshee/src/Extensions/Banshee.NotificationArea/Resources/NotificationAreaMenu.xml
==============================================================================
--- trunk/banshee/src/Extensions/Banshee.NotificationArea/Resources/NotificationAreaMenu.xml	(original)
+++ trunk/banshee/src/Extensions/Banshee.NotificationArea/Resources/NotificationAreaMenu.xml	Sat Apr 12 00:09:08 2008
@@ -1,22 +1,21 @@
 <ui>
-    <popup name="NotificationAreaIconMenu" action="NotificationAreaIconMenuAction">
-        <menuitem name="PlayPause" action="PlayPauseAction" />
-        <menuitem name="Previous" action="PreviousAction" />
-        <menuitem name="Next" action="NextAction" />
-        <!--<separator />
-        <menuitem name="RepeatNone" action="RepeatNoneAction" />
-        <menuitem name="RepeatAll" action="RepeatAllAction" />
-        <menuitem name="RepeatSingle" action="RepeatSingleAction" />-->
-        <separator />
-        <menuitem name="ToggleNotifications" action="ToggleNotificationsAction" />
-        <separator />
-        <menuitem name="Quit" action="QuitAction" />
-    </popup>
-    <menubar name="MainMenu">
-        <menu name="MediaMenu" action="MediaMenuAction">
-            <placeholder name="ClosePlaceholder">
-                 <menuitem name="Close" action="CloseAction" />
-            </placeholder>
-        </menu>
-    </menubar>
+  <!-- This is the context menu for the actual notification area -->
+  <popup name="NotificationAreaIconMenu" action="NotificationAreaIconMenuAction">
+    <menuitem name="PlayPause" action="PlayPauseAction"/>
+    <menuitem name="Previous" action="PreviousAction"/>
+    <menuitem name="Next" action="NextAction"/>
+    <separator/>
+    <menuitem name="ToggleNotifications" action="ToggleNotificationsAction"/>
+    <separator/>
+    <menuitem name="Quit" action="QuitAction"/>
+  </popup>
+  
+  <!-- This menu gets merged into the main menu to add the close window item -->
+  <menubar name="MainMenu">
+    <menu name="MediaMenu" action="MediaMenuAction">
+      <placeholder name="ClosePlaceholder">
+      <menuitem name="Close" action="CloseAction"/>
+      </placeholder>
+    </menu>
+  </menubar>
 </ui>

Modified: trunk/banshee/src/Libraries/Hyena/Hyena/Log.cs
==============================================================================
--- trunk/banshee/src/Libraries/Hyena/Hyena/Log.cs	(original)
+++ trunk/banshee/src/Libraries/Hyena/Hyena/Log.cs	Sat Apr 12 00:09:08 2008
@@ -100,7 +100,7 @@
             set { debugging = value; }
         }
         
-        private static void Commit (LogEntryType type, string message, string details, bool showUser)
+        public static void Commit (LogEntryType type, string message, string details, bool showUser)
         {
             if (type == LogEntryType.Debug && !Debugging) {
                 return;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]