Skip to content

Commit

Permalink
feat: added lyrics highlighting based on timestamp
Browse files Browse the repository at this point in the history
  • Loading branch information
Dzheremi2 committed Dec 30, 2024
1 parent 989b52e commit 911f102
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 43 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ flathub/
build/
_build/
po/qa.po
io.github.dzheremi2.Chronograph.flatpak
2 changes: 1 addition & 1 deletion chronograph/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def do_activate(self) -> None: # pylint: disable=arguments-differ
self.create_actions(
{
("quit", ("<primary>q",)),
("toggle_sidebar", ("F9",), shared.win),
# ("toggle_sidebar", ("F9",), shared.win),
("toggle_search", ("<primary>f",), shared.win),
("select_dir", ("<primary><shift>o",), shared.win),
("append_line", ("<Alt><primary>a",), shared.win),
Expand Down
13 changes: 7 additions & 6 deletions chronograph/ui/SongCard.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ def __init__(self, file: Union[FileID3, FileVorbis]) -> None:
)
self.cover_button.connect("clicked", self.on_play_button_clicked)
self.play_button.connect("clicked", self.on_play_button_clicked)
self.metadata_editor_button.connect(
"clicked",
lambda *_: self.set_property(
"cover", open("/home/dzheremi/Pictures/pp.jpg", "rb").read()
),
)
# self.metadata_editor_button.connect(
# "clicked",
# lambda *_: self.set_property(
# "cover", open("/home/dzheremi/Pictures/pp.jpg", "rb").read()
# ),
# )
self.bind_props()
self.invalidate_cover(self.cover_img)

Expand Down Expand Up @@ -119,6 +119,7 @@ def on_play_button_clicked(self, *_args) -> None:
self.invalidate_update("title", "sync_page")
self.invalidate_update("artist", "sync_page")
mediastream = Gtk.MediaFile.new_for_filename(self._file.path)
mediastream.connect("notify::timestamp", shared.win.on_timestamp_changed)
shared.win.controls.set_media_stream(mediastream)
shared.win.controls_shrinked.set_media_stream(mediastream)
shared.win.navigation_view.push(shared.win.sync_navigation_page)
Expand Down
1 change: 1 addition & 0 deletions chronograph/utils/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def songcard_idle(file: Union[FileID3, FileVorbis]) -> None:
File of song
"""
from chronograph.ui.SongCard import SongCard

song_card = SongCard(file)
shared.win.library.append(song_card)
song_card.get_parent().set_focusable(False)
Expand Down
49 changes: 46 additions & 3 deletions chronograph/window.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import threading

import requests
from gi.repository import Adw, Gio, GLib, Gtk # type: ignore
from gi.repository import Adw, Gio, GLib, Gtk, Pango # type: ignore

from chronograph import shared
from chronograph.ui.BoxDialog import BoxDialog
Expand Down Expand Up @@ -112,6 +112,7 @@ def __init__(self, **kwargs) -> None:
self.lrclib_window_results_list.connect("row-selected", self.set_lyrics)
self.sync_navigation_page.connect("hiding", self.reset_sync_editor)
self.quick_edit_copy_button.connect("clicked", self.copy_quick_editor_text)
self.toggle_repeat_button.connect("toggled", self.toggle_repeat)
self.lrclib_window_collapsed_results_list.connect(
"row-selected", self.set_lyrics
)
Expand Down Expand Up @@ -283,7 +284,9 @@ def on_sync_line_action(self, *_args) -> None:
pass

if re.search(pattern, shared.selected_line.get_text()) is None:
shared.selected_line.set_text(timestamp + shared.selected_line.get_text())
shared.selected_line.set_text(
timestamp + shared.selected_line.get_text()
)
else:
replacement = rf"{timestamp}"
shared.selected_line.set_text(
Expand Down Expand Up @@ -330,7 +333,9 @@ def on_100ms_forw_action(self, *_args) -> None:
new_timestamp = f"[{timestamp // 60000:02d}:{(timestamp % 60000) // 1000:02d}.{timestamp % 1000:03d}]"
shared.selected_line.set_text(
re.sub(
r"\[([^\[\]]+)\]", rf"{new_timestamp}", shared.selected_line.get_text()
r"\[([^\[\]]+)\]",
rf"{new_timestamp}",
shared.selected_line.get_text(),
)
)
self.controls.get_media_stream().seek(timestamp * 1000)
Expand Down Expand Up @@ -490,3 +495,41 @@ def copy_quick_editor_text(self, *_args) -> None:
self.quck_editor_toast_overlay.add_toast(
Adw.Toast(title=_("Copied successfully"))
)

def on_timestamp_changed(self, media_stream: Gtk.MediaStream, *_) -> None:
"""Higlights line with timestamp larger that current and smaller that next
Parameters
----------
media_stream : Gtk.MediaStream
`Gtk.MediaStream` to get timestamp from
"""
attributes = Pango.AttrList().from_string("0 -1 weight ultrabold")
try:
lines = []
timestamps = []
for line in self.sync_lines:
line.set_attributes(None)
if (timing := timing_parser(line.get_text())) is not None:
lines.append(line)
timestamps.append(timing)
else:
break
timestamp = media_stream.get_timestamp() // 1000
for i in range(len(timestamps)):
if timestamp > timestamps[i] and timestamp < timestamps[i + 1]:
lines[i].set_attributes(attributes)
break
elif timestamp >= timestamps[-1]:
lines[-1].set_attributes(attributes)
except (TypeError, AttributeError, IndexError):
pass

def toggle_repeat(self, *_args) -> None:
"""Toggles repeat mode in player"""
if self.toggle_repeat_button.get_active():
self.controls.get_media_stream().set_loop(True)
self.controls_shrinked.get_media_stream().set_loop(True)
else:
self.controls.get_media_stream().set_loop(False)
self.controls_shrinked.get_media_stream().set_loop(False)
3 changes: 3 additions & 0 deletions chronograph/window.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ChronographWindow(Adw.ApplicationWindow):
search_lrclib_collapsed_status_page: Adw.StatusPage
lrclib_window_nothing_found_status: Adw.StatusPage
lrclib_window_collapsed_nothing_found_status: Adw.StatusPage
parsing_in_progress: Adw.StatusPage

# Library view widgets
help_overlay: Gtk.ShortcutsWindow
Expand Down Expand Up @@ -98,3 +99,5 @@ class ChronographWindow(Adw.ApplicationWindow):
def on_show_preferences_action(self, *args) -> None: ...
def on_open_quick_editor_action(self, *_args) -> None: ...
def copy_quick_editor_text(self, *_args) -> None: ...
def on_timestamp_changed(self, media_stream: Gtk.MediaStream, *_) -> None: ...
def toggle_repeat(self, *_args) -> None: ...
69 changes: 36 additions & 33 deletions data/gtk/window.blp
Original file line number Diff line number Diff line change
Expand Up @@ -440,17 +440,18 @@ Adw.NavigationView lrclib_window_collapsed_navigation_view {

template $ChronographWindow : Adw.ApplicationWindow {
title: _("Chronograph");
width-request: 294;
height-request: 360;
width-request: 360;
height-request: 100;

Adw.Breakpoint {
condition ("max-width: 564px")

setters {
overlay_split_view.collapsed: true;
// overlay_split_view.collapsed: true;
controls_box_shrinked.visible: true;
syncing_buttons_box.halign: center;
lrclib_window_main_clamp.child: lrclib_window_collapsed_navigation_view;
header_bar.show-title: false;
}
}

Expand All @@ -461,40 +462,41 @@ template $ChronographWindow : Adw.ApplicationWindow {

Adw.OverlaySplitView overlay_split_view {
sidebar-width-fraction: .2;

[sidebar]
Adw.NavigationPage sidebar_nav_page {
title: _("Saves");

Adw.ToolbarView {
[top]
Adw.HeaderBar {
[start]
Button {
icon-name: "toggle-sidebar-symbolic";
tooltip-text: _("Toggle sidebar");
action-name: "win.toggle_sidebar";
}
}

ScrolledWindow {
ListBox sidebar {
styles ["navigation-sidebar"]
}
}
}
}
collapsed: true;

// [sidebar]
// Adw.NavigationPage sidebar_nav_page {
// title: _("Saves");

// Adw.ToolbarView {
// [top]
// Adw.HeaderBar {
// [start]
// Button {
// icon-name: "toggle-sidebar-symbolic";
// tooltip-text: _("Toggle sidebar");
// action-name: "win.toggle_sidebar";
// }
// }

// ScrolledWindow {
// ListBox sidebar {
// styles ["navigation-sidebar"]
// }
// }
// }
// }

Adw.ToolbarView library_view {
[top]
Adw.HeaderBar header_bar {
[start]
Button show_sidebar_button {
icon-name: "toggle-sidebar-symbolic";
tooltip-text: _("Toggle sidebar");
action-name: "win.toggle_sidebar";
visible: bind overlay_split_view.show-sidebar inverted;
}
// [start]
// Button show_sidebar_button {
// icon-name: "toggle-sidebar-symbolic";
// tooltip-text: _("Toggle sidebar");
// action-name: "win.toggle_sidebar";
// visible: bind overlay_split_view.show-sidebar inverted;
// }

MenuButton open_source_button {
icon-name: "open-source-symbolic";
Expand Down Expand Up @@ -659,6 +661,7 @@ Adw.NavigationPage sync_navigation_page {
Button info_button_shrinked {
tooltip-text: bind info_button.tooltip-text bidirectional;
icon-name: bind info_button.icon-name bidirectional;
action-name: "win.show_file_info";
}
}

Expand Down

0 comments on commit 911f102

Please sign in to comment.