Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 05838116d0 |
280
whipper/gui.py
280
whipper/gui.py
@@ -129,6 +129,7 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
self.track_view = None
|
||||
self.log_buffer = None
|
||||
self.release_details = None
|
||||
self.track_columns = None
|
||||
|
||||
self.info_labels = {}
|
||||
self.status_label = None
|
||||
@@ -149,35 +150,121 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
window = Gtk.ApplicationWindow(application=self)
|
||||
window.set_title("Whipper")
|
||||
window.set_icon_name("com.github.whipper_team.Whipper")
|
||||
window.set_default_size(1120, 760)
|
||||
window.set_border_width(12)
|
||||
window.set_default_size(1380, 900)
|
||||
window.set_border_width(8)
|
||||
self._install_css()
|
||||
|
||||
root = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
|
||||
root = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
|
||||
root.get_style_context().add_class("eac-shell")
|
||||
window.add(root)
|
||||
|
||||
root.pack_start(self._build_controls(), False, False, 0)
|
||||
root.pack_start(self._build_actions(), False, False, 0)
|
||||
root.pack_start(self._build_transport_strip(), False, False, 0)
|
||||
root.pack_start(self._build_progress(), False, False, 0)
|
||||
root.pack_start(self._build_main_content(), True, True, 0)
|
||||
root.pack_start(self._build_log(), True, True, 0)
|
||||
root.pack_start(self._build_log(), False, True, 0)
|
||||
|
||||
self._refresh_devices()
|
||||
self._load_gui_settings()
|
||||
window.show_all()
|
||||
return window
|
||||
|
||||
@staticmethod
|
||||
def _install_css():
|
||||
provider = Gtk.CssProvider()
|
||||
provider.load_from_data(
|
||||
b"""
|
||||
.eac-shell {
|
||||
background: #d9d9d9;
|
||||
}
|
||||
frame > border {
|
||||
border: 1px solid #8a8a8a;
|
||||
border-radius: 0;
|
||||
background: #ececec;
|
||||
padding: 4px;
|
||||
}
|
||||
frame > label {
|
||||
color: #1f1f1f;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.eac-toolbar {
|
||||
background: linear-gradient(to bottom, #f7f7f7, #d8d8d8);
|
||||
border: 1px solid #8a8a8a;
|
||||
padding: 6px;
|
||||
}
|
||||
.eac-toolbar button {
|
||||
border-radius: 0;
|
||||
padding: 4px 10px;
|
||||
background: linear-gradient(to bottom, #fefefe, #dbdbdb);
|
||||
border: 1px solid #7e7e7e;
|
||||
color: #111111;
|
||||
}
|
||||
.eac-toolbar button.suggested-action {
|
||||
background: linear-gradient(to bottom, #e5f2ff, #b7d4f3);
|
||||
}
|
||||
.eac-toolbar button.destructive-action {
|
||||
background: linear-gradient(to bottom, #fbe7e7, #e7b7b7);
|
||||
}
|
||||
.eac-matrix,
|
||||
.eac-log {
|
||||
background: #fcfcfc;
|
||||
color: #121212;
|
||||
border: 1px solid #919191;
|
||||
}
|
||||
.eac-log text {
|
||||
background: #fcfcfc;
|
||||
color: #111111;
|
||||
font: 10pt Monospace;
|
||||
}
|
||||
.eac-status {
|
||||
font-weight: 700;
|
||||
}
|
||||
.eac-subtle {
|
||||
color: #4c4c4c;
|
||||
}
|
||||
progressbar trough {
|
||||
min-height: 16px;
|
||||
border-radius: 0;
|
||||
background: #cfcfcf;
|
||||
border: 1px solid #8e8e8e;
|
||||
}
|
||||
progressbar progress {
|
||||
border-radius: 0;
|
||||
background: linear-gradient(to bottom, #8fc2f3, #4f84b6);
|
||||
}
|
||||
"""
|
||||
)
|
||||
Gtk.StyleContext.add_provider_for_screen(
|
||||
Gtk.Window().get_screen(),
|
||||
provider,
|
||||
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||
)
|
||||
|
||||
def _build_transport_strip(self):
|
||||
frame = Gtk.Frame(label="Extraction Control Center")
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8, margin=8)
|
||||
frame.add(box)
|
||||
box.pack_start(self._build_controls(), False, False, 0)
|
||||
box.pack_start(self._build_actions(), False, False, 0)
|
||||
return frame
|
||||
|
||||
def _build_controls(self):
|
||||
grid = Gtk.Grid(column_spacing=10, row_spacing=10)
|
||||
grid = Gtk.Grid(column_spacing=8, row_spacing=8)
|
||||
|
||||
grid.attach(Gtk.Label(label="Drive", xalign=0), 0, 0, 1, 1)
|
||||
self.device_combo = Gtk.ComboBoxText()
|
||||
self.device_combo.connect("changed", self._on_device_changed)
|
||||
grid.attach(self.device_combo, 1, 0, 2, 1)
|
||||
grid.attach(self.device_combo, 1, 0, 1, 1)
|
||||
|
||||
self.refresh_button = Gtk.Button(label="Refresh Drives")
|
||||
self.refresh_button = Gtk.Button(label="Detect Drives")
|
||||
self.refresh_button.connect("clicked", self._on_refresh_clicked)
|
||||
self.refresh_button.set_tooltip_text("Refresh the list of detected optical drives")
|
||||
grid.attach(self.refresh_button, 3, 0, 1, 1)
|
||||
grid.attach(self.refresh_button, 2, 0, 1, 1)
|
||||
|
||||
grid.attach(Gtk.Label(label="Status", xalign=0), 3, 0, 1, 1)
|
||||
self.status_label = Gtk.Label(label="Idle", xalign=0)
|
||||
self.status_label.set_selectable(True)
|
||||
grid.attach(self.status_label, 4, 0, 2, 1)
|
||||
|
||||
grid.attach(Gtk.Label(label="Output", xalign=0), 0, 1, 1, 1)
|
||||
self.output_button = Gtk.FileChooserButton(
|
||||
@@ -186,13 +273,21 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
)
|
||||
self.output_button.set_filename(os.path.expanduser("~"))
|
||||
self.output_button.connect("file-set", self._on_settings_changed)
|
||||
grid.attach(self.output_button, 1, 1, 3, 1)
|
||||
grid.attach(self.output_button, 1, 1, 2, 1)
|
||||
|
||||
grid.attach(Gtk.Label(label="Logger", xalign=0), 3, 1, 1, 1)
|
||||
self.logger_combo = Gtk.ComboBoxText()
|
||||
for logger_name in sorted(result.getLoggers()):
|
||||
self.logger_combo.append(logger_name, logger_name)
|
||||
self.logger_combo.set_active_id("whipper")
|
||||
self.logger_combo.connect("changed", self._on_settings_changed)
|
||||
grid.attach(self.logger_combo, 4, 1, 2, 1)
|
||||
|
||||
grid.attach(Gtk.Label(label="Working Dir", xalign=0), 0, 2, 1, 1)
|
||||
self.working_directory_entry = Gtk.Entry()
|
||||
self.working_directory_entry.set_placeholder_text("Optional working directory")
|
||||
self.working_directory_entry.connect("changed", self._on_settings_changed)
|
||||
grid.attach(self.working_directory_entry, 1, 2, 3, 1)
|
||||
grid.attach(self.working_directory_entry, 1, 2, 2, 1)
|
||||
|
||||
grid.attach(Gtk.Label(label="Country", xalign=0), 0, 3, 1, 1)
|
||||
self.country_entry = Gtk.Entry()
|
||||
@@ -204,40 +299,50 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
self.release_id_entry = Gtk.Entry()
|
||||
self.release_id_entry.set_placeholder_text("Optional release override")
|
||||
self.release_id_entry.connect("changed", self._on_settings_changed)
|
||||
grid.attach(self.release_id_entry, 3, 3, 1, 1)
|
||||
grid.attach(self.release_id_entry, 3, 3, 3, 1)
|
||||
|
||||
return grid
|
||||
|
||||
def _build_actions(self):
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=10)
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
|
||||
box.get_style_context().add_class("eac-toolbar")
|
||||
|
||||
self.read_button = Gtk.Button(label="Read Disc")
|
||||
self.read_button = Gtk.Button(label="Detect TOC")
|
||||
self.read_button.connect("clicked", self._on_read_clicked)
|
||||
self.read_button.set_tooltip_text("Read TOC and fetch matching MusicBrainz releases")
|
||||
box.pack_start(self.read_button, False, False, 0)
|
||||
|
||||
self.rip_button = Gtk.Button(label="Rip Selected Release")
|
||||
self.rip_button = Gtk.Button(label="Secure Rip")
|
||||
self.rip_button.connect("clicked", self._on_rip_clicked)
|
||||
self.rip_button.set_tooltip_text("Rip the current disc using the selected release metadata")
|
||||
self.rip_button.set_sensitive(False)
|
||||
self.rip_button.get_style_context().add_class("suggested-action")
|
||||
box.pack_start(self.rip_button, False, False, 0)
|
||||
|
||||
self.stop_button = Gtk.Button(label="Stop")
|
||||
self.stop_button = Gtk.Button(label="Abort")
|
||||
self.stop_button.connect("clicked", self._on_stop_clicked)
|
||||
self.stop_button.set_tooltip_text("Cancel the current scan or rip")
|
||||
self.stop_button.set_sensitive(False)
|
||||
self.stop_button.get_style_context().add_class("destructive-action")
|
||||
box.pack_start(self.stop_button, False, False, 0)
|
||||
|
||||
self.status_label = Gtk.Label(label="Idle", xalign=0)
|
||||
box.pack_start(self.status_label, True, True, 0)
|
||||
box.pack_start(Gtk.Separator(orientation=Gtk.Orientation.VERTICAL), False, False, 6)
|
||||
|
||||
action_hint = Gtk.Label(
|
||||
label="EAC-style flow: Detect TOC -> pick release -> Secure Rip",
|
||||
xalign=0,
|
||||
)
|
||||
action_hint.get_style_context().add_class("eac-subtle")
|
||||
box.pack_start(action_hint, True, True, 0)
|
||||
return box
|
||||
|
||||
def _build_progress(self):
|
||||
frame = Gtk.Frame(label="Progress")
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8, margin=10)
|
||||
frame = Gtk.Frame(label="Extraction Progress")
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, margin=8)
|
||||
frame.add(box)
|
||||
|
||||
self.progress_label = Gtk.Label(label="No task running", xalign=0)
|
||||
self.progress_label.get_style_context().add_class("eac-status")
|
||||
box.pack_start(self.progress_label, False, False, 0)
|
||||
|
||||
self.overall_bar = Gtk.ProgressBar(show_text=True)
|
||||
@@ -251,11 +356,18 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
return frame
|
||||
|
||||
def _build_main_content(self):
|
||||
pane = Gtk.Paned.new(Gtk.Orientation.VERTICAL)
|
||||
pane.set_wide_handle(True)
|
||||
pane.pack1(self._build_workspace(), resize=True, shrink=False)
|
||||
pane.pack2(self._build_log(), resize=False, shrink=False)
|
||||
self.main_pane = pane
|
||||
return pane
|
||||
|
||||
def _build_workspace(self):
|
||||
pane = Gtk.Paned.new(Gtk.Orientation.HORIZONTAL)
|
||||
pane.set_wide_handle(True)
|
||||
pane.pack1(self._build_left_panel(), resize=True, shrink=False)
|
||||
pane.pack1(self._build_left_panel(), resize=False, shrink=False)
|
||||
pane.pack2(self._build_right_panel(), resize=True, shrink=False)
|
||||
self.main_pane = pane
|
||||
return pane
|
||||
|
||||
def _build_left_panel(self):
|
||||
@@ -281,17 +393,24 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
|
||||
box.pack_start(info_frame, False, False, 0)
|
||||
|
||||
release_frame = Gtk.Frame(label="Matching Releases")
|
||||
release_frame = Gtk.Frame(label="Metadata / Releases")
|
||||
release_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8, margin=8)
|
||||
release_frame.add(release_box)
|
||||
|
||||
self.release_store = Gtk.ListStore(str, str, str, str, str, object)
|
||||
self.release_view = Gtk.TreeView(model=self.release_store)
|
||||
self.release_view.set_headers_clickable(False)
|
||||
self.release_view.set_enable_search(False)
|
||||
self.release_view.set_fixed_height_mode(True)
|
||||
self.release_view.set_grid_lines(Gtk.TreeViewGridLines.BOTH)
|
||||
self.release_view.get_style_context().add_class("eac-matrix")
|
||||
self.release_view.get_selection().connect("changed", self._on_release_selected)
|
||||
for index, title in enumerate(["Artist", "Title", "Year", "Type", "Country"]):
|
||||
renderer = Gtk.CellRendererText()
|
||||
column = Gtk.TreeViewColumn(title, renderer, text=index)
|
||||
column.set_resizable(True)
|
||||
if title in {"Artist", "Title"}:
|
||||
column.set_expand(True)
|
||||
self.release_view.append_column(column)
|
||||
|
||||
scroll = Gtk.ScrolledWindow()
|
||||
@@ -310,25 +429,46 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
self.release_details = Gtk.Label(label="Select a release to inspect it.", xalign=0, yalign=0)
|
||||
self.release_details.set_line_wrap(True)
|
||||
self.release_details.set_selectable(True)
|
||||
self.release_details.get_style_context().add_class("eac-subtle")
|
||||
details_scroll.add(self.release_details)
|
||||
release_box.pack_start(details_frame, False, False, 0)
|
||||
|
||||
box.pack_start(release_frame, True, True, 0)
|
||||
box.set_size_request(420, -1)
|
||||
return box
|
||||
|
||||
def _build_right_panel(self):
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
|
||||
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8)
|
||||
|
||||
tracks_frame = Gtk.Frame(label="Tracks")
|
||||
tracks_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=8, margin=8)
|
||||
tracks_frame = Gtk.Frame(label="Track Extraction Matrix")
|
||||
tracks_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=6, margin=8)
|
||||
tracks_frame.add(tracks_box)
|
||||
|
||||
self.track_store = Gtk.ListStore(str, str, str, str)
|
||||
self.track_columns = {
|
||||
"number": 0,
|
||||
"status": 1,
|
||||
"artist": 2,
|
||||
"title": 3,
|
||||
"length": 4,
|
||||
"test_crc": 5,
|
||||
"copy_crc": 6,
|
||||
"accuraterip": 7,
|
||||
}
|
||||
self.track_store = Gtk.ListStore(str, str, str, str, str, str, str, str)
|
||||
self.track_view = Gtk.TreeView(model=self.track_store)
|
||||
for index, title in enumerate(["#", "Artist", "Title", "Length"]):
|
||||
self.track_view.set_headers_clickable(False)
|
||||
self.track_view.set_enable_search(False)
|
||||
self.track_view.set_fixed_height_mode(True)
|
||||
self.track_view.set_grid_lines(Gtk.TreeViewGridLines.BOTH)
|
||||
self.track_view.get_style_context().add_class("eac-matrix")
|
||||
for index, title in enumerate(["#", "Status", "Artist", "Title", "Length", "Test CRC", "Copy CRC", "AR"]):
|
||||
renderer = Gtk.CellRendererText()
|
||||
column = Gtk.TreeViewColumn(title, renderer, text=index)
|
||||
column.set_resizable(True)
|
||||
if title in {"Artist", "Title"}:
|
||||
column.set_expand(True)
|
||||
if title == "Status":
|
||||
column.set_min_width(140)
|
||||
self.track_view.append_column(column)
|
||||
|
||||
track_scroll = Gtk.ScrolledWindow()
|
||||
@@ -337,16 +477,16 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
track_scroll.add(self.track_view)
|
||||
tracks_box.pack_start(track_scroll, True, True, 0)
|
||||
|
||||
tracks_box.pack_start(self._build_rip_options(), False, False, 0)
|
||||
box.pack_start(tracks_frame, True, True, 0)
|
||||
box.pack_start(self._build_rip_options(), False, False, 0)
|
||||
return box
|
||||
|
||||
def _build_rip_options(self):
|
||||
frame = Gtk.Frame(label="Rip Options")
|
||||
grid = Gtk.Grid(column_spacing=10, row_spacing=8, margin=10)
|
||||
frame = Gtk.Frame(label="Extraction Setup")
|
||||
grid = Gtk.Grid(column_spacing=8, row_spacing=6, margin=8)
|
||||
frame.add(grid)
|
||||
|
||||
self.unknown_check = Gtk.CheckButton(label="Allow ripping without metadata")
|
||||
self.unknown_check = Gtk.CheckButton(label="Allow unknown disc")
|
||||
self.unknown_check.set_active(True)
|
||||
self.unknown_check.connect("toggled", self._on_unknown_toggled)
|
||||
grid.attach(self.unknown_check, 0, 0, 2, 1)
|
||||
@@ -355,7 +495,7 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
self.cdr_check.connect("toggled", self._on_settings_changed)
|
||||
grid.attach(self.cdr_check, 2, 0, 1, 1)
|
||||
|
||||
self.keep_going_check = Gtk.CheckButton(label="Keep going on failed tracks")
|
||||
self.keep_going_check = Gtk.CheckButton(label="Continue on failed tracks")
|
||||
self.keep_going_check.set_active(True)
|
||||
self.keep_going_check.connect("toggled", self._on_settings_changed)
|
||||
grid.attach(self.keep_going_check, 0, 1, 2, 1)
|
||||
@@ -386,14 +526,6 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
self.offset_spin.connect("value-changed", self._on_settings_changed)
|
||||
grid.attach(self.offset_spin, 1, 3, 1, 1)
|
||||
|
||||
grid.attach(Gtk.Label(label="Logger", xalign=0), 2, 3, 1, 1)
|
||||
self.logger_combo = Gtk.ComboBoxText()
|
||||
for logger_name in sorted(result.getLoggers()):
|
||||
self.logger_combo.append(logger_name, logger_name)
|
||||
self.logger_combo.set_active_id("whipper")
|
||||
self.logger_combo.connect("changed", self._on_settings_changed)
|
||||
grid.attach(self.logger_combo, 3, 3, 1, 1)
|
||||
|
||||
grid.attach(Gtk.Label(label="Track Tpl", xalign=0), 0, 4, 1, 1)
|
||||
self.track_template_entry = Gtk.Entry()
|
||||
self.track_template_entry.set_text(cd_command.DEFAULT_TRACK_TEMPLATE)
|
||||
@@ -407,25 +539,28 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
grid.attach(self.disc_template_entry, 1, 5, 3, 1)
|
||||
|
||||
note = Gtk.Label(
|
||||
label="The configured drive offset is loaded automatically when whipper knows this drive.",
|
||||
label="Secure extraction is driven by whipper's native cdparanoia/cdrdao pipeline. The configured drive offset is loaded automatically when available.",
|
||||
xalign=0,
|
||||
)
|
||||
note.set_line_wrap(True)
|
||||
note.get_style_context().add_class("eac-subtle")
|
||||
grid.attach(note, 0, 6, 4, 1)
|
||||
|
||||
return frame
|
||||
|
||||
def _build_log(self):
|
||||
frame = Gtk.Frame(label="Log")
|
||||
frame = Gtk.Frame(label="Extraction Log")
|
||||
scroll = Gtk.ScrolledWindow()
|
||||
scroll.set_hexpand(True)
|
||||
scroll.set_vexpand(True)
|
||||
scroll.set_vexpand(False)
|
||||
scroll.set_min_content_height(220)
|
||||
frame.add(scroll)
|
||||
|
||||
text_view = Gtk.TextView()
|
||||
text_view.set_editable(False)
|
||||
text_view.set_cursor_visible(False)
|
||||
text_view.set_monospace(True)
|
||||
text_view.get_style_context().add_class("eac-log")
|
||||
self.log_buffer = text_view.get_buffer()
|
||||
scroll.add(text_view)
|
||||
return frame
|
||||
@@ -621,11 +756,24 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
for index, track in enumerate(metadata.tracks, start=1):
|
||||
self.track_store.append([
|
||||
str(index),
|
||||
"Ready",
|
||||
track.artist or "",
|
||||
track.title or "",
|
||||
_format_duration_ms(track.duration),
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
])
|
||||
|
||||
def _set_track_field(self, track_number, field, value):
|
||||
if track_number <= 0 or self.track_store is None or self.track_columns is None:
|
||||
return False
|
||||
row_index = track_number - 1
|
||||
if row_index < 0 or row_index >= len(self.track_store):
|
||||
return False
|
||||
self.track_store[row_index][self.track_columns[field]] = value
|
||||
return False
|
||||
|
||||
def _update_release_details(self, metadata):
|
||||
if metadata is None:
|
||||
self.release_details.set_text("Select a release to inspect it.")
|
||||
@@ -836,6 +984,14 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
self.track_bar.set_fraction(value)
|
||||
self.track_bar.set_text(description)
|
||||
self.progress_label.set_text("%s: %s" % (item_label, description))
|
||||
if item_label.startswith("Track "):
|
||||
try:
|
||||
track_number = int(item_label.split()[1])
|
||||
except (IndexError, ValueError):
|
||||
track_number = None
|
||||
if track_number is not None:
|
||||
percent = int(value * 100)
|
||||
self._set_track_field(track_number, "status", "%s %d%%" % (description, percent))
|
||||
return False
|
||||
|
||||
def _mark_track_finished(self, item_label, item_index, item_total, skipped=False):
|
||||
@@ -846,6 +1002,13 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
self.track_bar.set_fraction(1.0)
|
||||
self.track_bar.set_text("%s %s" % (item_label, "skipped" if skipped else "done"))
|
||||
self.progress_label.set_text("%s %s" % (item_label, "failed" if skipped else "verified"))
|
||||
if item_label.startswith("Track "):
|
||||
try:
|
||||
track_number = int(item_label.split()[1])
|
||||
except (IndexError, ValueError):
|
||||
track_number = None
|
||||
if track_number is not None:
|
||||
self._set_track_field(track_number, "status", "Skipped" if skipped else "Verified")
|
||||
return False
|
||||
|
||||
def _finish_rip(self, returncode, status="Done"):
|
||||
@@ -891,6 +1054,8 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
|
||||
if os.path.exists(path):
|
||||
GLib.idle_add(self._append_log, "%s already exists, verifying\n" % item_label)
|
||||
if track_number > 0:
|
||||
GLib.idle_add(self._set_track_field, track_number, "status", "Verifying existing")
|
||||
if not program.verifyTrack(runner, track_result):
|
||||
GLib.idle_add(self._append_log, "%s verification failed, reripping\n" % item_label)
|
||||
os.unlink(path)
|
||||
@@ -904,6 +1069,13 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
raise RipCancelledError("Rip cancelled")
|
||||
extra = "" if tries == 1 else " (try %d)" % tries
|
||||
GLib.idle_add(self._append_log, "%s%s: %s\n" % (item_label, extra, os.path.basename(path)))
|
||||
if track_number > 0:
|
||||
GLib.idle_add(
|
||||
self._set_track_field,
|
||||
track_number,
|
||||
"status",
|
||||
"Test & Copy%s" % extra,
|
||||
)
|
||||
|
||||
tag_list = program.getTagList(track_number, mbdiscid)
|
||||
if track_number > 0 and itable.tracks[track_number - 1].isrc is not None:
|
||||
@@ -940,6 +1112,19 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
track_result.copyduration += rip_task.copyduration
|
||||
if track_result.filename != rip_task.path:
|
||||
track_result.filename = rip_task.path
|
||||
if track_number > 0:
|
||||
GLib.idle_add(
|
||||
self._set_track_field,
|
||||
track_number,
|
||||
"test_crc",
|
||||
"%08X" % track_result.testcrc if track_result.testcrc is not None else "",
|
||||
)
|
||||
GLib.idle_add(
|
||||
self._set_track_field,
|
||||
track_number,
|
||||
"copy_crc",
|
||||
"%08X" % track_result.copycrc if track_result.copycrc is not None else "",
|
||||
)
|
||||
break
|
||||
except Exception as exc:
|
||||
if self.rip_cancel_requested:
|
||||
@@ -953,6 +1138,8 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
if settings["keep_going"]:
|
||||
track_result.skipped = True
|
||||
skipped_tracks.append(track_result)
|
||||
if track_number > 0:
|
||||
GLib.idle_add(self._set_track_field, track_number, "accuraterip", "Skipped")
|
||||
GLib.idle_add(self._mark_track_finished, item_label, item_index, item_total, True)
|
||||
return
|
||||
raise RuntimeError("%s can't be ripped" % item_label)
|
||||
@@ -962,6 +1149,8 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
return
|
||||
|
||||
if track_result.testcrc != track_result.copycrc:
|
||||
if track_number > 0:
|
||||
GLib.idle_add(self._set_track_field, track_number, "accuraterip", "CRC mismatch")
|
||||
raise RuntimeError("CRCs did not match for %s" % item_label)
|
||||
|
||||
if track_number == 0:
|
||||
@@ -985,6 +1174,7 @@ class WhipperGui(Gtk.Application if Gtk is not None else object):
|
||||
program.result.table.getTrackLength(track_number),
|
||||
track_number,
|
||||
)
|
||||
GLib.idle_add(self._set_track_field, track_number, "accuraterip", "Pending AR")
|
||||
|
||||
GLib.idle_add(self._mark_track_finished, item_label, item_index, item_total, False)
|
||||
|
||||
|
||||
@@ -277,6 +277,16 @@ def _make_ui_app(tmp_path):
|
||||
app.track_bar = FakeProgressBar()
|
||||
app.release_store = FakeListStore()
|
||||
app.track_store = FakeListStore()
|
||||
app.track_columns = {
|
||||
"number": 0,
|
||||
"status": 1,
|
||||
"artist": 2,
|
||||
"title": 3,
|
||||
"length": 4,
|
||||
"test_crc": 5,
|
||||
"copy_crc": 6,
|
||||
"accuraterip": 7,
|
||||
}
|
||||
app.release_view = FakeReleaseView(app.release_store)
|
||||
app.release_details = FakeLabel()
|
||||
app.info_labels = {key: FakeLabel() for key in [
|
||||
@@ -305,6 +315,7 @@ def _make_ui_app(tmp_path):
|
||||
"_set_running_state",
|
||||
"_update_release_store",
|
||||
"_update_track_store",
|
||||
"_set_track_field",
|
||||
"_update_release_details",
|
||||
"_update_rip_task_progress",
|
||||
"_finish_rip",
|
||||
@@ -390,7 +401,8 @@ def test_release_selection_and_progress_updates(monkeypatch, tmp_path):
|
||||
gui.WhipperGui._finish_rip(app, 0, "Done")
|
||||
|
||||
assert app.current_release is metadata
|
||||
assert app.track_store[0][1] == "Track Artist"
|
||||
assert app.track_store[0][2] == "Track Artist"
|
||||
assert app.track_store[0][1].startswith("Encoding")
|
||||
assert app.release_details.get_text().startswith("Artist: Artist")
|
||||
assert app.overall_bar.fraction == 1.0
|
||||
assert app.track_bar.fraction == 1.0
|
||||
|
||||
Reference in New Issue
Block a user