GitLab repository storage has been migrated to hashed layout. Please contact Infrastructure team if you notice any issues with repositories or hooks.

Commit f0b6d516 authored by Aaron Bockover's avatar Aaron Bockover Committed by Aaron Bockover

Handle invalid integer durations

2006-03-19  Aaron Bockover  <aaron@abock.org>

    * entagged-sharp/EncodingInfo.cs: Handle invalid integer durations

    * src/PlayerInterface.cs: Moved the audio-CD specific view and ripping
    stuff into AudioCdSource; do not treat the LibrarySource as anything
    special; it now handles track additions like any good source should

    * src/Banshee.Base/Sources/AudioCdSource.cs: Handle ripping directly in
    the source; create a custom view to handle the audio CD status bar
    and embed the playlist view

    * src/Banshee.Base/Sources/LibrarySource.cs: Raise the proper
    OnTrackAdded/OnTrackRemoved events

    * src/Banshee.Base/AudioCd/AudioCdDisk.cs: Make Tracks property
    IEnumerable
parent 02530c8c
2006-03-19 Aaron Bockover <aaron@abock.org>
* entagged-sharp/EncodingInfo.cs: Handle invalid integer durations
* src/PlayerInterface.cs: Moved the audio-CD specific view and ripping
stuff into AudioCdSource; do not treat the LibrarySource as anything
special; it now handles track additions like any good source should
* src/Banshee.Base/Sources/AudioCdSource.cs: Handle ripping directly in
the source; create a custom view to handle the audio CD status bar
and embed the playlist view
* src/Banshee.Base/Sources/LibrarySource.cs: Raise the proper
OnTrackAdded/OnTrackRemoved events
* src/Banshee.Base/AudioCd/AudioCdDisk.cs: Make Tracks property
IEnumerable
2006-03-19 Aaron Bockover <aaron@abock.org>
* data/UIManagerLayout.xml: Added RefreshSong
......
......@@ -78,7 +78,15 @@ namespace Entagged.Audioformats
//Sets the length of the song in seconds
public TimeSpan Duration {
set { content["DURATION"] = value; }
get { return (TimeSpan) content["DURATION"]; }
get {
object o = content["DURATION"];
if(o is TimeSpan) {
return (TimeSpan)o;
}
int duration = (int)o;
return duration < 0 ? new TimeSpan(0) : new TimeSpan(duration * TimeSpan.TicksPerSecond);
}
}
public bool Vbr {
......
/***************************************************************************
* AudioCdDisk.cs
*
* Copyright (C) 2005 Novell
* Written by Aaron Bockover (aaron@aaronbock.net)
* Copyright (C) 2005-2006 Novell, Inc.
* Written by Aaron Bockover <aaron@abock.org>
****************************************************************************/
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
......@@ -214,7 +213,7 @@ namespace Banshee.Base
private void HandleUpdated()
{
Gtk.Application.Invoke(delegate {
ThreadAssist.ProxyToMain(delegate {
EventHandler handler = Updated;
if(handler != null) {
handler(this, new EventArgs());
......@@ -222,17 +221,6 @@ namespace Banshee.Base
});
}
public AudioCdLookupStatus Status {
get {
return status;
}
private set {
status = value;
HandleUpdated();
}
}
[DllImport("libc")]
private static extern int ioctl(int device, EjectOperation request);
......@@ -273,46 +261,41 @@ namespace Banshee.Base
}
}
public string Udi {
get {
return udi;
public AudioCdLookupStatus Status {
get { return status; }
private set {
status = value;
HandleUpdated();
}
}
public string Udi {
get { return udi; }
}
public string DeviceNode {
get {
return device_node;
}
get { return device_node; }
}
public string DriveName {
get {
return drive_name;
}
get { return drive_name; }
}
public string Title {
get {
return album_title;
}
get { return album_title; }
}
public int TrackCount {
get {
return tracks.Length;
}
get { return tracks.Length; }
}
public bool Valid {
get {
return true;
}
get { return true; }
}
public AudioCdTrackInfo [] Tracks {
get {
return tracks;
}
public IEnumerable Tracks {
get { return tracks; }
}
}
}
/***************************************************************************
* AudioCdSource.cs
*
* Copyright (C) 2005 Novell
* Written by Aaron Bockover (aaron@aaronbock.net)
* Copyright (C) 2005-2006 Novell, Inc.
* Written by Aaron Bockover <aaron@abock.org>
****************************************************************************/
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
......@@ -30,31 +30,91 @@ using System;
using System.Data;
using System.Collections;
using Mono.Unix;
using Gtk;
using Banshee.Base;
using Banshee.Widgets;
namespace Banshee.Sources
{
public class AudioCdSource : Source, IImportSource
{
private AudioCdDisk disk;
private VBox box;
private Alignment container;
private HighlightMessageArea audiocd_statusbar;
public AudioCdSource(AudioCdDisk disk) : base(disk.Title, 200)
{
this.disk = disk;
disk.Updated += OnDiskUpdated;
container = new Alignment(0.0f, 0.0f, 1.0f, 1.0f);
audiocd_statusbar = new HighlightMessageArea();
audiocd_statusbar.BorderWidth = 5;
audiocd_statusbar.LeftPadding = 15;
audiocd_statusbar.ButtonClicked += delegate { disk.QueryMetadata(); };
box = new VBox();
box.Spacing = 5;
box.PackStart(container, true, true, 0);
box.PackStart(audiocd_statusbar, false, false, 0);
container.Show();
box.Show();
}
public override int Count {
get {
return disk.TrackCount;
private void UpdateAudioCdStatus()
{
string status = null;
Gdk.Pixbuf icon = null;
switch(disk.Status) {
case AudioCdLookupStatus.ReadingDisk:
status = Catalog.GetString("Reading table of contents from CD...");
icon = IconThemeUtils.LoadIcon(22, "media-cdrom", "gnome-dev-cdrom-audio", "source-cd-audio");
audiocd_statusbar.ShowCloseButton = false;
break;
case AudioCdLookupStatus.SearchingMetadata:
status = Catalog.GetString("Searching for CD metadata...");
icon = IconThemeUtils.LoadIcon(22, "system-search", Stock.Find);
audiocd_statusbar.ShowCloseButton = false;
break;
case AudioCdLookupStatus.SearchingCoverArt:
status = Catalog.GetString("Searching for CD cover art...");
icon = IconThemeUtils.LoadIcon(22, "system-search", Stock.Find);
audiocd_statusbar.ShowCloseButton = false;
break;
case AudioCdLookupStatus.ErrorNoConnection:
status = Catalog.GetString("Cannot search for CD metadata: " +
"there is no available Internet connection");
icon = IconThemeUtils.LoadIcon(22, "network-wired", Stock.Network);
audiocd_statusbar.ShowCloseButton = true;
break;
case AudioCdLookupStatus.ErrorLookup:
status = Catalog.GetString("Could not fetch metadata for CD.");
icon = IconThemeUtils.LoadIcon(22, Stock.DialogError);
audiocd_statusbar.ShowCloseButton = true;
break;
case AudioCdLookupStatus.Success:
default:
status = null;
icon = null;
break;
}
}
public AudioCdDisk Disk {
get {
return disk;
if(disk.Status == AudioCdLookupStatus.ErrorLookup) {
audiocd_statusbar.ButtonLabel = Stock.Refresh;
audiocd_statusbar.ButtonUseStock = true;
} else {
audiocd_statusbar.ButtonLabel = null;
}
audiocd_statusbar.Visible = status != null;
audiocd_statusbar.Message = String.Format("<big>{0}</big>", GLib.Markup.EscapeText(status));
audiocd_statusbar.Pixbuf = icon;
}
public override bool Eject()
......@@ -64,17 +124,53 @@ namespace Banshee.Sources
return true;
}
public override void Activate()
{
InterfaceElements.DetachPlaylistContainer();
container.Add(InterfaceElements.PlaylistContainer);
UpdateAudioCdStatus();
}
public void Import()
{
SourceManager.SetActiveSource(this);
Globals.ActionManager["ImportCDAction"].Activate();
ImportDisk();
OnUpdated();
}
private void ImportDisk()
{
ArrayList list = new ArrayList();
foreach(AudioCdTrackInfo track in disk.Tracks) {
if(track.CanRip) {
list.Add(track);
}
}
if(list.Count > 0) {
AudioCdRipper ripper = new AudioCdRipper();
// ripper.HaveTrackInfo += OnAudioCdRipperTrackRipped;
foreach(AudioCdTrackInfo track in list) {
ripper.QueueTrack(track);
}
ripper.Start();
} else {
HigMessageDialog dialog = new HigMessageDialog(InterfaceElements.MainWindow, DialogFlags.Modal,
MessageType.Info, ButtonsType.Ok,
Catalog.GetString("Invalid Selection"),
Catalog.GetString("You must select at least one track to import.")
);
dialog.Run();
dialog.Destroy();
}
}
private void OnDiskUpdated(object o, EventArgs args)
{
ThreadAssist.ProxyToMain(delegate {
Name = disk.Title;
UpdateAudioCdStatus();
OnUpdated();
});
}
......@@ -83,17 +179,25 @@ namespace Banshee.Sources
public override Gdk.Pixbuf Icon {
get { return icon; }
}
public override int Count {
get { return disk.TrackCount; }
}
public AudioCdDisk Disk {
get { return disk; }
}
public override IEnumerable Tracks {
get {
return disk.Tracks;
}
get { return disk.Tracks; }
}
public override bool SearchEnabled {
get {
return false;
}
get { return false; }
}
public override Gtk.Widget ViewWidget {
get { return box; }
}
}
}
/***************************************************************************
* LibrarySource.cs
*
* Copyright (C) 2005 Novell
* Written by Aaron Bockover (aaron@aaronbock.net)
* Copyright (C) 2005-2006 Novell, Inc.
* Written by Aaron Bockover <aaron@abock.org>
****************************************************************************/
/* THIS FILE IS LICENSED UNDER THE MIT LICENSE AS OUTLINED IMMEDIATELY BELOW:
......@@ -59,17 +58,13 @@ namespace Banshee.Sources
private LibrarySource() : base(Catalog.GetString("Music Library"), 0)
{
Globals.Library.TrackRemoved += delegate(object o, LibraryTrackRemovedArgs args) {
if (!updating) {
updating = true;
GLib.Timeout.Add(500, DelayedUpdateHandler);
}
OnTrackRemoved(args.Track);
OnUpdated();
};
Globals.Library.TrackAdded += delegate(object o, LibraryTrackAddedArgs args) {
if (!updating) {
updating = true;
GLib.Timeout.Add(500, DelayedUpdateHandler);
}
OnTrackAdded(args.Track);
OnUpdated();
};
}
......@@ -84,21 +79,15 @@ namespace Banshee.Sources
}
public override IEnumerable Tracks {
get {
return Globals.Library.Tracks.Values;
}
get { return Globals.Library.Tracks.Values; }
}
public override int Count {
get {
return Globals.Library.Tracks.Count;
}
get { return Globals.Library.Tracks.Count; }
}
public override Gdk.Pixbuf Icon {
get {
return IconThemeUtils.LoadIcon(22, "user-home", "source-library");
}
get { return IconThemeUtils.LoadIcon(22, Gtk.Stock.Home, "user-home", "source-library"); }
}
}
}
......@@ -86,8 +86,6 @@ namespace Banshee
private ActionButton sync_dap_button;
[Widget] private ProgressBar dapDiskUsageBar;
private HighlightMessageArea audiocd_statusbar;
private bool incrementedCurrentSongPlayCount;
public Gtk.Window Window {
......@@ -147,12 +145,7 @@ namespace Banshee
PlayerEngineCore.EventChanged += OnPlayerEngineEventChanged;
PlayerEngineCore.StateChanged += OnPlayerEngineStateChanged;
if(Globals.AudioCdCore != null) {
Globals.AudioCdCore.DiskRemoved += OnAudioCdCoreDiskRemoved;
Globals.AudioCdCore.Updated += OnAudioCdCoreUpdated;
}
DapCore.DapAdded += OnDapCoreDeviceAdded;
LogCore.Instance.Updated += OnLogCoreUpdated;
ImportManager.Instance.ImportRequested += OnImportManagerImportRequested;
......@@ -313,13 +306,6 @@ namespace Banshee
volumeButton.VolumeChanged += OnVolumeScaleChanged;
// Footer
audiocd_statusbar = new HighlightMessageArea();
audiocd_statusbar.BorderWidth = 5;
audiocd_statusbar.LeftPadding = 15;
audiocd_statusbar.ButtonClicked += OnAudioCdStatusBarButtonClicked;
(gxml["MainContainer"] as Box).PackStart(audiocd_statusbar, false, false, 0);
LabelStatusBar = new Label(Catalog.GetString("Banshee Music Player"));
LabelStatusBar.Show();
......@@ -938,6 +924,8 @@ namespace Banshee
ThreadAssist.ProxyToMain(HandleSourceChanged);
}
private uint source_update_draw_timeout = 0;
private void OnSourceManagerSourceUpdated(SourceEventArgs args)
{
if(args.Source == SourceManager.ActiveSource) {
......@@ -945,6 +933,12 @@ namespace Banshee
if(playlistModel.Count() == 0 && args.Source.Count > 0) {
playlistModel.ReloadSource();
} else if(source_update_draw_timeout == 0) {
source_update_draw_timeout = GLib.Timeout.Add(500, delegate {
playlistView.QueueDraw();
source_update_draw_timeout = 0;
return false;
});
}
gxml["SearchLabel"].Sensitive = args.Source.SearchEnabled;
......@@ -1005,7 +999,7 @@ namespace Banshee
}
alignment.Add(SourceManager.ActiveSource.ViewWidget);
alignment.ShowAll();
alignment.Show();
gxml["PlaylistHeaderBox"].Visible = SourceManager.ActiveSource.ShowPlaylistHeader;
}
......@@ -1013,6 +1007,10 @@ namespace Banshee
private void OnSourceTrackAdded(object o, TrackEventArgs args)
{
if(SourceManager.ActiveSource == o) {
if(searchEntry.IsQueryAvailable && !DoesTrackMatchSearch(args.Track)) {
return;
}
playlistModel.AddTrack(args.Track);
}
}
......@@ -1062,68 +1060,7 @@ namespace Banshee
Globals.ActionManager["RenameSourceAction"].Label = Catalog.GetString("Rename Playlist");
}
}
private void OnAudioCdStatusBarButtonClicked(object o, EventArgs args)
{
AudioCdSource source = SourceManager.ActiveSource as AudioCdSource;
if(source == null) {
return;
}
source.Disk.QueryMetadata();
}
private void UpdateAudioCdStatus(AudioCdDisk disk)
{
string status = null;
Gdk.Pixbuf icon = null;
switch(disk.Status) {
case AudioCdLookupStatus.ReadingDisk:
status = Catalog.GetString("Reading table of contents from CD...");
icon = IconThemeUtils.LoadIcon(22, "media-cdrom", "gnome-dev-cdrom-audio", "source-cd-audio");
audiocd_statusbar.ShowCloseButton = false;
break;
case AudioCdLookupStatus.SearchingMetadata:
status = Catalog.GetString("Searching for CD metadata...");
icon = IconThemeUtils.LoadIcon(22, "system-search", Stock.Find);
audiocd_statusbar.ShowCloseButton = false;
break;
case AudioCdLookupStatus.SearchingCoverArt:
status = Catalog.GetString("Searching for CD cover art...");
icon = IconThemeUtils.LoadIcon(22, "system-search", Stock.Find);
audiocd_statusbar.ShowCloseButton = false;
break;
case AudioCdLookupStatus.ErrorNoConnection:
status = Catalog.GetString("Cannot search for CD metadata: " +
"there is no available Internet connection");
icon = IconThemeUtils.LoadIcon(22, "network-wired", Stock.Network);
audiocd_statusbar.ShowCloseButton = true;
break;
case AudioCdLookupStatus.ErrorLookup:
status = Catalog.GetString("Could not fetch metadata for CD.");
icon = IconThemeUtils.LoadIcon(22, Stock.DialogError);
audiocd_statusbar.ShowCloseButton = true;
break;
case AudioCdLookupStatus.Success:
default:
status = null;
icon = null;
break;
}
if(disk.Status == AudioCdLookupStatus.ErrorLookup) {
audiocd_statusbar.ButtonLabel = Stock.Refresh;
audiocd_statusbar.ButtonUseStock = true;
} else {
audiocd_statusbar.ButtonLabel = null;
}
audiocd_statusbar.Visible = status != null;
audiocd_statusbar.Message = String.Format("<big>{0}</big>", GLib.Markup.EscapeText(status));
audiocd_statusbar.Pixbuf = icon;
}
// Called when SourceManager emits an ActiveSourceChanged event.
private void HandleSourceChanged(object o, EventArgs args)
{
......@@ -1133,14 +1070,10 @@ namespace Banshee
}
searchEntry.CancelSearch();
audiocd_statusbar.Visible = false;
if(source is DapSource) {
DapSource dap_source = source as DapSource;
UpdateDapDiskUsageBar(dap_source);
} else if(source is AudioCdSource) {
AudioCdSource cdSource = source as AudioCdSource;
UpdateAudioCdStatus(cdSource.Disk);
}
UpdateViewName(source); // Bold label below track info
......@@ -1204,43 +1137,6 @@ namespace Banshee
args.Dap.SaveFinished += OnDapSaveFinished;
}
private void OnAudioCdCoreDiskRemoved(object o, AudioCdCoreDiskRemovedArgs args)
{
Source source = SourceManager.ActiveSource;
if(source == null) {
return;
}
if(source is AudioCdSource) {
AudioCdSource cdSource = source as AudioCdSource;
if(cdSource.Disk.Udi == args.Udi) {
SourceManager.SetActiveSource(LibrarySource.Instance);
}
}
}
private void OnAudioCdCoreUpdated(object o, EventArgs args)
{
Source source = SourceManager.ActiveSource;
if(source == null) {
return;
}
playlistView.QueueDraw();
if(source is AudioCdSource && playlistModel.FirstTrack != null
&& playlistModel.FirstTrack.GetType() == typeof(AudioCdTrackInfo)) {
AudioCdSource cdSource = source as AudioCdSource;
AudioCdTrackInfo track = playlistModel.FirstTrack as AudioCdTrackInfo;
if(cdSource.Disk.DeviceNode == track.Device) {
(gxml["ViewNameLabel"] as Label).Markup = "<b>" +
GLib.Markup.EscapeText(cdSource.Disk.Title) + "</b>";
UpdateAudioCdStatus(cdSource.Disk);
}
}
}
private void OnDapSaveFinished(object o, EventArgs args)
{
if(SourceManager.ActiveSource is DapSource
......@@ -1775,7 +1671,7 @@ namespace Banshee
playlistView.Selection.SelectPath(path);
}
private void OnAudioCdRipperTrackRipped(object o, HaveTrackInfoArgs args)
/*private void OnAudioCdRipperTrackRipped(object o, HaveTrackInfoArgs args)
{
if(SourceManager.ActiveSource is LibrarySource) {
ThreadAssist.ProxyToMain(delegate {
......@@ -1786,7 +1682,7 @@ namespace Banshee
playlistModel.AddTrack(args.TrackInfo);
});
}
}
}*/
private void EjectSource(Source source)
{
......@@ -1817,15 +1713,6 @@ namespace Banshee
try {
TrackInfo ti = new LibraryTrackInfo(args.FileName);
args.ReturnMessage = String.Format("{0} - {1}", ti.Artist, ti.Title);
if(SourceManager.ActiveSource is LibrarySource) {
ThreadAssist.ProxyToMain(delegate {
if(searchEntry.IsQueryAvailable && !DoesTrackMatchSearch(ti)) {
return;
}
playlistModel.AddTrack(ti);
});
}
} catch(Entagged.Audioformats.Exceptions.CannotReadException) {
Console.WriteLine(Catalog.GetString("Cannot Import") + ": {0}", args.FileName);
args.ReturnMessage = Catalog.GetString("Scanning") + "...";
......@@ -1996,29 +1883,8 @@ namespace Banshee
private void OnImportCDAction(object o, EventArgs args)
{
ArrayList list = new ArrayList();
foreach(object [] node in playlistModel) {
if(node[0] is AudioCdTrackInfo && ((AudioCdTrackInfo)node[0]).CanRip) {
list.Add(node[0] as AudioCdTrackInfo);
}
}
if(list.Count > 0) {
AudioCdRipper ripper = new AudioCdRipper();
ripper.HaveTrackInfo += OnAudioCdRipperTrackRipped;
foreach(AudioCdTrackInfo track in list) {
ripper.QueueTrack(track);
}
ripper.Start();
} else {
HigMessageDialog dialog = new HigMessageDialog(WindowPlayer, DialogFlags.Modal,
MessageType.Info, ButtonsType.Ok,
Catalog.GetString("Invalid Selection"),
Catalog.GetString("You must select at least one track to import.")
);
dialog.Run();
dialog.Destroy();
if(SourceManager.ActiveSource is AudioCdSource) {
((IImportSource)SourceManager.ActiveSource).Import();
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment