mirror of
https://gitlab.com/liyaowhen/youtubecollector-git.git
synced 2026-09-30 17:02:59 +00:00
import playlist feat wip
This commit is contained in:
@@ -0,0 +1 @@
|
||||
disable = true
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"C_Cpp.default.compileCommands": "/home/liyaowhen/Documents/YoutubeCollector/youtubecollector/builddir/compile_commands.json",
|
||||
"C_Cpp.default.configurationProvider": "mesonbuild.mesonbuild"
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id" : "com.liyaowhen.YoutubeCollector",
|
||||
"runtime" : "org.gnome.Platform",
|
||||
"runtime-version" : "master",
|
||||
"runtime-version" : "46",
|
||||
"sdk" : "org.gnome.Sdk",
|
||||
"sdk-extensions" : [
|
||||
"org.freedesktop.Sdk.Extension.vala"
|
||||
@@ -12,7 +12,21 @@
|
||||
"--share=ipc",
|
||||
"--socket=fallback-x11",
|
||||
"--device=dri",
|
||||
"--socket=wayland"
|
||||
"--socket=wayland",
|
||||
"--socket=x11",
|
||||
"--socket=wayland",
|
||||
"--talk-name=org.freedesktop.DBus",
|
||||
"--talk-name=org.freedesktop.portal.Desktop",
|
||||
"--system-talk-name=org.freedesktop.UDisks2",
|
||||
"--system-talk-name=org.freedesktop.UPower",
|
||||
"--filesystem=host",
|
||||
"--filesystem=home",
|
||||
"--filesystem=xdg-download",
|
||||
"--filesystem=host-os",
|
||||
"--talk-name=org.freedesktop.DBus",
|
||||
"--own-name=org.freedesktop.DBus",
|
||||
"--session-bus=yes",
|
||||
"--system-bus=yes"
|
||||
],
|
||||
"build-options" : {
|
||||
"append-path" : "/usr/lib/sdk/vala/bin",
|
||||
@@ -31,14 +45,37 @@
|
||||
"*.a"
|
||||
],
|
||||
"modules" : [
|
||||
{
|
||||
{
|
||||
"name": "vte",
|
||||
"buildsystem": "meson",
|
||||
"config-opts": ["-Dgtk4=true", "-Dgtk3=false", "-Dsixel=true"],
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://gitlab.gnome.org/GNOME/vte/-/archive/3c8f66be867aca6656e4109ce880b6ea7431b895/vte-3c8f66be867aca6656e4109ce880b6ea7431b895.tar.gz",
|
||||
"sha256": "320618260a29c99ab68d1e8674f6d4926bbf1e7e6541e8e04898fad85bb6e1b9"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "json-glib",
|
||||
"buildsystem": "meson",
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://gitlab.gnome.org/GNOME/json-glib/-/archive/23ae2f59bea7405d95218e82edb7f3c4c7c80a87/json-glib-23ae2f59bea7405d95218e82edb7f3c4c7c80a87.tar.gz",
|
||||
"sha256": "9fa88f1b8fc926bfd7c4115354a06f79b7b30fa367450a3e7a36932e3b7022ba"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name" : "youtubecollector",
|
||||
"builddir" : true,
|
||||
"buildsystem" : "meson",
|
||||
"sources" : [
|
||||
{
|
||||
"type" : "git",
|
||||
"url" : "file:///home/liyaowhen/Documents/YoutubeCollector/youtubecollector"
|
||||
"url" : "https://gitlab.com/liyaowhen/song"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
id: com.liyaowhen.YoutubeCollector
|
||||
runtime: org.freedesktop.Platform
|
||||
runtime-version: '23.08'
|
||||
sdk: org.freedesktop.Sdk
|
||||
command: hello
|
||||
modules:
|
||||
- name: hello
|
||||
buildsystem: simple
|
||||
build-commands:
|
||||
- install -Dm755 hello.sh /app/bin/hello
|
||||
sources:
|
||||
- type: script
|
||||
dest-filename: hello.sh
|
||||
commands:
|
||||
- echo "Hello world, from a sandbox"
|
||||
@@ -18,10 +18,10 @@
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
public class Application : Adw.Application {
|
||||
public Application () {
|
||||
Object (application_id: "com.liyaowhen.Song", flags: ApplicationFlags.DEFAULT_FLAGS);
|
||||
Object (application_id: "com.liyaowhen.YoutubeCollector", flags: ApplicationFlags.DEFAULT_FLAGS);
|
||||
}
|
||||
|
||||
construct {
|
||||
@@ -41,7 +41,7 @@ namespace Song {
|
||||
base.activate ();
|
||||
var win = this.active_window;
|
||||
if (win == null) {
|
||||
win = new Song.Window (this);
|
||||
win = new YoutubeCollector.Window (this);
|
||||
}
|
||||
win.present ();
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Song {
|
||||
var about = new Adw.AboutWindow () {
|
||||
transient_for = this.active_window,
|
||||
application_name = "song",
|
||||
application_icon = "com.liyaowhen.Song",
|
||||
application_icon = "com.liyaowhen.YoutubeCollector",
|
||||
developer_name = "Leo Wen",
|
||||
version = "0.1.0",
|
||||
developers = developers,
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
class BackgroundContainer : Gtk.DrawingArea {
|
||||
// WIP entirely
|
||||
// TODO: make this able to
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
using Gtk;
|
||||
|
||||
namespace YoutubeCollector {
|
||||
|
||||
|
||||
/* to ensure that doing things on the main_view_content or sidebar_content
|
||||
in this SongController allows for those objects to exist, instead of
|
||||
doing functions related to this controller in the bare construct {},
|
||||
put it in a signal that will be released when the SongController is ready to use */
|
||||
public class AppController : Object {
|
||||
|
||||
public static MainViewContent main_view_content; // main view content should avoid using this controller during instanciation
|
||||
public static SideBarContent sidebar_content;
|
||||
public static SideBar side_bar;
|
||||
public static Adw.OverlaySplitView split_view;
|
||||
public static MainView main_view;
|
||||
|
||||
public static SongControls song_controls;
|
||||
|
||||
public static YoutubeCollector.Window window;
|
||||
|
||||
public static Adw.ToastOverlay toast_overlay = new Adw.ToastOverlay();
|
||||
|
||||
public static string app_data_dir = Path.build_filename (Environment.get_user_data_dir (), "com.liyaowhen.YoutubeCollector");
|
||||
|
||||
public static async void append_yt_playlist(PlaylistObject playlist, string source) {
|
||||
try {
|
||||
GLib.Dir dir = GLib.Dir.open(Path.build_filename(Environment.get_user_data_dir(), "com.liyaowhen.YoutubeCollector", playlist.name));
|
||||
|
||||
Gee.HashSet<string> files = new Gee.HashSet<string>();
|
||||
string? filename;
|
||||
while ((filename = dir.read_name()) != null) {
|
||||
files.add(filename);
|
||||
}
|
||||
|
||||
playlist.items.foreach((i) => {
|
||||
if (files.contains(i.file)) {
|
||||
files.remove(i.file);
|
||||
}
|
||||
});
|
||||
|
||||
files.foreach((i) => {
|
||||
PlaylistItem item = new PlaylistItem();
|
||||
item.source = source;
|
||||
item.file = i;
|
||||
item.name = i;
|
||||
playlist.add_item(item);
|
||||
return true;
|
||||
});
|
||||
|
||||
var config = Config.get_instance();
|
||||
config.save.begin();
|
||||
} catch (GLib.FileError e) {
|
||||
print(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class SignalHub : Object {
|
||||
private static SignalHub? instance = null;
|
||||
|
||||
public signal void mouse_clicked();
|
||||
|
||||
public signal void enter_yt_search_mode();
|
||||
public signal void exit_yt_search_mode();
|
||||
public signal void request_search(string query);
|
||||
public YtSearchBar yt_search_bar;
|
||||
|
||||
public signal void start_drag();
|
||||
public signal void end_drag();
|
||||
public bool isDragging = false;
|
||||
|
||||
public static SignalHub get_instance () {
|
||||
if (instance == null) {
|
||||
instance = new SignalHub();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
public class ActiveProcesses : Object {
|
||||
|
||||
public Gee.HashSet<string> active_subprocesses = new Gee.HashSet<string>();
|
||||
|
||||
public signal void add_process(string id) {
|
||||
active_subprocesses.add(id);
|
||||
}
|
||||
|
||||
public signal void process_completed(string process) {
|
||||
active_subprocesses.remove(process);
|
||||
}
|
||||
|
||||
public static ActiveProcesses? instance = null;
|
||||
|
||||
public static ActiveProcesses get_instance() {
|
||||
if (instance == null) {
|
||||
instance = new ActiveProcesses();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
using Gtk;
|
||||
|
||||
namespace Song {
|
||||
|
||||
|
||||
/* to ensure that doing things on the main_view_content or sidebar_content
|
||||
in this SongController allows for those objects to exist, instead of
|
||||
doing functions related to this controller in the bare construct {},
|
||||
put it in a signal that will be released when the SongController is ready to use */
|
||||
public class SongController : Object {
|
||||
|
||||
public static MainViewContent main_view_content; // main view content should avoid using this controller during instanciation
|
||||
public static SideBarContent sidebar_content;
|
||||
public static SideBar side_bar;
|
||||
public static Adw.OverlaySplitView split_view;
|
||||
public static MainView main_view;
|
||||
|
||||
public static SongControls song_controls;
|
||||
|
||||
public static Song.Window window;
|
||||
|
||||
public static Adw.ToastOverlay toast_overlay = new Adw.ToastOverlay();
|
||||
|
||||
}
|
||||
|
||||
public class SignalHub : Object {
|
||||
private static SignalHub? instance = null;
|
||||
|
||||
public signal void mouse_clicked();
|
||||
|
||||
public signal void enter_yt_search_mode();
|
||||
public signal void exit_yt_search_mode();
|
||||
public signal void request_search(string query);
|
||||
public YtSearchBar yt_search_bar;
|
||||
|
||||
public signal void start_drag();
|
||||
public signal void end_drag();
|
||||
public bool isDragging = false;
|
||||
|
||||
public static SignalHub get_instance () {
|
||||
if (instance == null) {
|
||||
instance = new SignalHub();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+51
-10
@@ -25,7 +25,7 @@
|
||||
|
||||
*/
|
||||
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
|
||||
public enum PlaylistType {
|
||||
VIDEO_ONLY = 0,
|
||||
@@ -101,15 +101,30 @@ namespace Song {
|
||||
_playList.name = member_name;
|
||||
// TODO: ADD PROPERTIES _playList.properties = whatever
|
||||
// TODO: fix item iterator, it is invalid as it calls on each member, not each "object"
|
||||
Json.Object? items_object = null;
|
||||
Json.Array? items_object = null;
|
||||
if (object.has_member("items")) {
|
||||
items_object = object.get_object_member("items");
|
||||
items_object = object.get_array_member("items");
|
||||
}
|
||||
if (items_object != null) {
|
||||
var items_list = items_object.get_members();
|
||||
items_list.foreach((item) => {
|
||||
var item_iterator = items_object.get_length();
|
||||
|
||||
for (int i = 0; i < item_iterator; i++) {
|
||||
PlaylistItem _item = new PlaylistItem();
|
||||
var _item_object = items_object.get_object_member(item);
|
||||
var _item_object = items_object.get_object_element(i);
|
||||
_item.item_type = _item_object.get_int_member("item_type");
|
||||
_item.name = _item_object.get_string_member("name");
|
||||
_item.file = _item_object.get_string_member("file");
|
||||
if (_item_object.has_member("picture")) {
|
||||
_item.picture = _item_object.get_string_member("picture");
|
||||
}
|
||||
if (_item_object.has_member("source")) {
|
||||
_item.picture = _item_object.get_string_member("source");
|
||||
}
|
||||
_playList.items.append(_item);
|
||||
}
|
||||
/*items_list.foreach((item) => {
|
||||
PlaylistItem _item = new PlaylistItem();
|
||||
var _item_object = items_object.get_(item);
|
||||
_item.item_type = _item_object.get_int_member("item_type");
|
||||
_item.name = item;
|
||||
_item.file = _item_object.get_string_member("file");
|
||||
@@ -120,7 +135,7 @@ namespace Song {
|
||||
_item.picture = _item_object.get_string_member("source");
|
||||
}
|
||||
_playList.items.append(_item);
|
||||
});
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,6 +157,22 @@ namespace Song {
|
||||
|
||||
return playlists.;
|
||||
}*/
|
||||
public bool allocate_playlist_space(PlaylistObject playlist) {
|
||||
string app_data_dir = Path.build_filename(Environment.get_user_data_dir(), "com.liyaowhen.YoutubeCollector");
|
||||
var playlist_folder = Path.build_filename(app_data_dir, playlist.name);
|
||||
|
||||
var playlist_folder_item = File.new_for_path(playlist_folder);
|
||||
if (!playlist_folder_item.query_exists(null)) {
|
||||
try {
|
||||
playlist_folder_item.make_directory_with_parents(null);
|
||||
} catch (Error e) {
|
||||
print(e.message);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Save configuration to file
|
||||
public async void save() {
|
||||
@@ -171,7 +202,7 @@ namespace Song {
|
||||
|
||||
// items
|
||||
builder.set_member_name("items");
|
||||
builder.begin_object();
|
||||
builder.begin_array();
|
||||
|
||||
// foreach item
|
||||
item.items.foreach((e) => {
|
||||
@@ -179,7 +210,7 @@ namespace Song {
|
||||
builder.begin_object();
|
||||
|
||||
builder.set_member_name("name");
|
||||
builder.add_string_value("name");
|
||||
builder.add_string_value(e.name);
|
||||
|
||||
builder.set_member_name("item_type");
|
||||
builder.add_int_value(e.item_type);
|
||||
@@ -201,7 +232,7 @@ namespace Song {
|
||||
});
|
||||
|
||||
// items end
|
||||
builder.end_object();
|
||||
builder.end_array();
|
||||
|
||||
builder.end_object();
|
||||
}
|
||||
@@ -244,6 +275,16 @@ namespace Song {
|
||||
Config.get_instance().save.begin(); // Create the file with default values
|
||||
}
|
||||
|
||||
string data_dir = Environment.get_user_data_dir();
|
||||
File data = File.new_for_path(data_dir);
|
||||
if (!data.query_exists(null)) {
|
||||
try {
|
||||
data.make_directory_with_parents(null);
|
||||
} catch (Error e) {
|
||||
print("Error creating directory: %s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -1,14 +1,14 @@
|
||||
int main (string[] args) {
|
||||
Gst.init(ref args);
|
||||
|
||||
Song.Config.init("com.liyaowhen.Song");
|
||||
var config = Song.Config.get_instance ();
|
||||
YoutubeCollector.Config.init("com.liyaowhen.YoutubeCollector");
|
||||
var config = YoutubeCollector.Config.get_instance ();
|
||||
|
||||
Song.PlaylistObject playlist = new Song.PlaylistObject();
|
||||
YoutubeCollector.PlaylistObject playlist = new YoutubeCollector.PlaylistObject();
|
||||
playlist.name = "QQ";
|
||||
|
||||
|
||||
var app = new Song.Application ();
|
||||
var app = new YoutubeCollector.Application ();
|
||||
|
||||
return app.run (args);
|
||||
}
|
||||
|
||||
+2
-1
@@ -7,13 +7,14 @@ youtubecollector_sources = [
|
||||
'json_config.vala',
|
||||
'widgets/main_view.vala',
|
||||
'widgets/playlist.vala',
|
||||
'controllers/song_controller.vala',
|
||||
'controllers/app_controller.vala',
|
||||
'widgets/music_list_row.vala',
|
||||
'widgets/song_controls.vala',
|
||||
'playlist_object.vala',
|
||||
'widgets/new_playlist_popover.vala',
|
||||
'widgets/yt_search.vala',
|
||||
'background.vala',
|
||||
'widgets/import_playlist_popover.vala',
|
||||
]
|
||||
|
||||
youtubecollector_deps = [
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using GLib;
|
||||
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
public class NewMusicPopover : Adw.Dialog {
|
||||
|
||||
private Settings settings = new Settings ("com.liyaowhen.Song");
|
||||
private Settings settings = new Settings ("com.liyaowhen.YoutubeCollector");
|
||||
|
||||
public signal void download();
|
||||
|
||||
@@ -13,7 +13,9 @@ namespace Song {
|
||||
private Gtk.Button next_button;
|
||||
private bool isPlaylistFolder;
|
||||
|
||||
private string item_directory = Path.build_path("/", Environment.get_user_data_dir(), "com.liyaowhen.Song");
|
||||
private PlaylistObject playlist;
|
||||
|
||||
private string item_directory = Path.build_path("/", Environment.get_user_data_dir(), "com.liyaowhen.YoutubeCollector");
|
||||
|
||||
public string song_title = "";
|
||||
public string song_url = "";
|
||||
@@ -89,6 +91,8 @@ namespace Song {
|
||||
|
||||
private void provide_ui() {
|
||||
|
||||
playlist = AppController.main_view_content.current_playlist;
|
||||
|
||||
navigation_view_steps = new Adw.NavigationView();
|
||||
|
||||
// starting page (choose what kind of app should be)
|
||||
@@ -223,6 +227,9 @@ namespace Song {
|
||||
next_button.show();
|
||||
next_button.sensitive = false;
|
||||
steps_state = "online";
|
||||
|
||||
item_directory = Path.build_path("/", item_directory, playlist.name);
|
||||
print(item_directory);
|
||||
|
||||
var path = File.new_for_path(item_directory);
|
||||
if (!path.query_exists(null)) {
|
||||
@@ -285,13 +292,17 @@ namespace Song {
|
||||
|
||||
PlaylistItem item = new PlaylistItem();
|
||||
item.name = song_title;
|
||||
item.file = "%s.%s".printf(Path.build_filename(item_directory, song_title), "mp3");
|
||||
item.file = "%s.%s".printf(song_title, "mp3");
|
||||
item.source = song_url;
|
||||
|
||||
var main_content = SongController.main_view_content;
|
||||
var main_content = AppController.main_view_content;
|
||||
main_content.current_playlist.add_item(item);
|
||||
|
||||
Config.get_instance().save.begin();
|
||||
next_button.label = "Finish";
|
||||
next_button.clicked.connect(() => {
|
||||
close();
|
||||
});
|
||||
//TODO: implement
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
|
||||
public class PlaylistObject : Object {
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/home/liyaowhen/Documents/YoutubeCollector/youtubecollector/song
|
||||
@@ -0,0 +1,77 @@
|
||||
namespace YoutubeCollector {
|
||||
public class ImportPlaylistPopover : Adw.AlertDialog {
|
||||
|
||||
private Adw.ToolbarView toolbar_view = new Adw.ToolbarView ();
|
||||
private Gtk.Entry entry = new Gtk.Entry ();
|
||||
|
||||
construct {
|
||||
var cancel_button = new Gtk.Button.with_label ("Cancel");
|
||||
cancel_button.clicked.connect(() => {
|
||||
close();
|
||||
});
|
||||
|
||||
var import_button = new Gtk.Button.with_label ("Import");
|
||||
import_button.clicked.connect(() => {
|
||||
close();
|
||||
|
||||
Subprocess import_process;
|
||||
SubprocessLauncher import_process_launcher = new SubprocessLauncher(GLib.SubprocessFlags.STDIN_PIPE | GLib.SubprocessFlags.STDOUT_PIPE | GLib.SubprocessFlags.STDERR_PIPE);
|
||||
import_process_launcher.set_cwd(Path.build_filename (Environment.get_user_data_dir (), "com.liyaowhen.YoutubeCollector", AppController.main_view_content.current_playlist.name));
|
||||
|
||||
var active_processes = ActiveProcesses.get_instance ();
|
||||
|
||||
try {
|
||||
import_process = import_process_launcher.spawnv ({ "yt-dlp", entry.get_text ()});
|
||||
} catch (GLib.Error e) {
|
||||
print(e.message);
|
||||
}
|
||||
|
||||
string id = import_process.get_identifier ();
|
||||
active_processes.add_process (id);
|
||||
|
||||
import_process.communicate_utf8_async.begin (null, null, (obj, res) => {
|
||||
string? stdout;
|
||||
string? stderr;
|
||||
try {
|
||||
import_process.communicate_utf8_async.end(res, out stdout, out stderr);
|
||||
} catch (GLib.Error e) {
|
||||
print(e.message);
|
||||
}
|
||||
|
||||
if (stdout != null) {
|
||||
print(stdout + "stdout");
|
||||
active_processes.process_completed(id);
|
||||
AppController.append_yt_playlist.begin (AppController.main_view_content.current_playlist, entry.get_text());
|
||||
}
|
||||
|
||||
if (stderr != null) {
|
||||
print ("STDERR: %s\n", stderr);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
var bottom_bar = new Adw.HeaderBar();
|
||||
bottom_bar.show_end_title_buttons = false;
|
||||
bottom_bar.show_start_title_buttons = false;
|
||||
|
||||
bottom_bar.pack_start (cancel_button);
|
||||
bottom_bar.pack_end (import_button);
|
||||
|
||||
var content = new Adw.Clamp();
|
||||
content.set_margin_bottom (5);
|
||||
content.set_margin_end (10);
|
||||
content.set_margin_start (10);
|
||||
content.set_margin_top (10);
|
||||
content.set_child(entry);
|
||||
|
||||
entry.placeholder_text = "Add Youtube Playlist Link Here:";
|
||||
|
||||
toolbar_view.add_bottom_bar (bottom_bar);
|
||||
toolbar_view.set_content(content);
|
||||
|
||||
set_child(toolbar_view);
|
||||
}
|
||||
}
|
||||
}
|
||||
+89
-17
@@ -1,13 +1,14 @@
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
public class MainView : Adw.NavigationPage {
|
||||
private Window window;
|
||||
|
||||
public Settings settings = new Settings("com.liyaowhen.Song.playlists");
|
||||
public Settings settings = new Settings("com.liyaowhen.YoutubeCollector.playlists");
|
||||
public MainViewContent main_content;
|
||||
public PlaylistObject current_playlist;
|
||||
private Gtk.Revealer add_button_revealer = new Gtk.Revealer();
|
||||
private Gtk.Revealer add_buttons_revealer = new Gtk.Revealer();
|
||||
private Gtk.Revealer controls_revealer = new Gtk.Revealer();
|
||||
private Gtk.Revealer exit_yt_search_mode_revealer = new Gtk.Revealer();
|
||||
private Gtk.Revealer active_processes_revealer = new Gtk.Revealer();
|
||||
private Adw.HeaderBar action_bar;
|
||||
|
||||
|
||||
@@ -17,7 +18,7 @@ namespace Song {
|
||||
}
|
||||
|
||||
construct {
|
||||
SongController.main_view = this;
|
||||
AppController.main_view = this;
|
||||
|
||||
// make ui
|
||||
var toolbar_view = new Adw.ToolbarView ();
|
||||
@@ -39,15 +40,32 @@ namespace Song {
|
||||
add_button_content.set_label("Add Item");
|
||||
add_button.set_child(add_button_content);
|
||||
add_button.valign = Gtk.Align.CENTER;
|
||||
add_button_revealer.set_child(add_button);
|
||||
add_button_revealer.set_reveal_child(true);
|
||||
add_button_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_RIGHT;
|
||||
|
||||
var import_playlist = new Gtk.Button();
|
||||
var import_playlist_content = new Adw.ButtonContent();
|
||||
import_playlist_content.set_icon_name("application-exit-symbolic");
|
||||
import_playlist_content.set_label("Import Youtube Playlist");
|
||||
import_playlist.set_child(import_playlist_content);
|
||||
import_playlist.valign = Gtk.Align.CENTER;
|
||||
|
||||
var button_container = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 5);
|
||||
button_container.append(add_button);
|
||||
button_container.append(import_playlist);
|
||||
|
||||
add_buttons_revealer.set_child(button_container);
|
||||
add_buttons_revealer.set_reveal_child(true);
|
||||
add_buttons_revealer.transition_type = Gtk.RevealerTransitionType.SLIDE_RIGHT;
|
||||
|
||||
add_button.clicked.connect(() => {
|
||||
var popover = new NewMusicPopover();
|
||||
popover.present(this);
|
||||
});
|
||||
|
||||
import_playlist.clicked.connect(() => {
|
||||
var popover = new ImportPlaylistPopover();
|
||||
popover.present(this);
|
||||
});
|
||||
|
||||
var exit_yt_search_mode = new Gtk.Button.from_icon_name("go-previous-symbolic");
|
||||
exit_yt_search_mode.valign = Gtk.Align.CENTER;
|
||||
exit_yt_search_mode_revealer.set_child(exit_yt_search_mode);
|
||||
@@ -58,31 +76,84 @@ namespace Song {
|
||||
SignalHub.get_instance().exit_yt_search_mode();
|
||||
});
|
||||
|
||||
// active processes indicator
|
||||
var active_processes_container = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
|
||||
var active_processes_popover = new Gtk.Popover();
|
||||
active_processes_popover.set_child(active_processes_container);
|
||||
|
||||
Gee.HashSet<Gtk.Box> job_boxes = new Gee.HashSet<Gtk.Box>();
|
||||
|
||||
var active_processes_button = new Gtk.MenuButton();
|
||||
active_processes_button.set_popover(active_processes_popover);
|
||||
active_processes_button.margin_top = 5;
|
||||
active_processes_button.margin_bottom = 5;
|
||||
//active_processes_button.add_css_class("suggested-action");
|
||||
var active_processes_spinner = new Gtk.Spinner();
|
||||
active_processes_spinner.spinning = true;
|
||||
active_processes_button.set_child(active_processes_spinner);
|
||||
|
||||
active_processes_revealer.set_child(active_processes_button);
|
||||
active_processes_revealer.set_reveal_child(false);
|
||||
active_processes_revealer.set_transition_type(Gtk.RevealerTransitionType.SLIDE_LEFT);
|
||||
var active_processes_controller = ActiveProcesses.get_instance();
|
||||
|
||||
var active_processes = active_processes_controller.active_subprocesses;
|
||||
active_processes_controller.add_process.connect_after((process) => {
|
||||
active_processes = active_processes_controller.active_subprocesses;
|
||||
|
||||
active_processes_revealer.set_reveal_child(true);
|
||||
|
||||
var job_box = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
|
||||
var job_title = new Gtk.Label(process);
|
||||
var job_progress = new Gtk.ProgressBar();
|
||||
job_box.append(job_title);
|
||||
job_box.append(job_progress);
|
||||
job_box.name = process;
|
||||
job_boxes.add(job_box);
|
||||
|
||||
active_processes_container.append(job_box);
|
||||
});
|
||||
|
||||
active_processes_controller.process_completed.connect_after((process) => {
|
||||
job_boxes.foreach((i) => {
|
||||
if (i.name == process) {
|
||||
job_boxes.remove(i);
|
||||
active_processes_container.remove(i);
|
||||
if (active_processes.size == 0) {
|
||||
active_processes_revealer.set_reveal_child(false);
|
||||
}
|
||||
print("removed");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
action_bar = new Adw.HeaderBar();
|
||||
action_bar.show_back_button = false;
|
||||
action_bar.title_widget = new YtSearchBar();
|
||||
action_bar.pack_start(collapse_button);
|
||||
action_bar.pack_start(add_button_revealer);
|
||||
action_bar.pack_start(add_buttons_revealer);
|
||||
action_bar.pack_start(exit_yt_search_mode_revealer);
|
||||
action_bar.pack_end(active_processes_revealer);
|
||||
action_bar.margin_start = 5;
|
||||
|
||||
collapse_button.clicked.connect(() => {
|
||||
if(SongController.split_view.get_collapsed ()){
|
||||
SongController.split_view.show_sidebar = false;
|
||||
if(AppController.split_view.get_collapsed ()){
|
||||
AppController.split_view.show_sidebar = false;
|
||||
collapse_button.visible = true;
|
||||
} else {
|
||||
SongController.split_view.show_sidebar = true;
|
||||
AppController.split_view.show_sidebar = true;
|
||||
collapse_button.visible = false;
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Timeout.add(1, () => {
|
||||
if (SongController.side_bar != null && SongController.split_view != null) {
|
||||
if (SongController.split_view.get_show_sidebar()) {
|
||||
if (AppController.side_bar != null && AppController.split_view != null) {
|
||||
if (AppController.split_view.get_show_sidebar()) {
|
||||
collapse_button.visible = false;
|
||||
} else collapse_button.visible = true;
|
||||
SongController.side_bar.collapsing.connect(() => {
|
||||
AppController.side_bar.collapsing.connect(() => {
|
||||
collapse_button.visible = true;
|
||||
|
||||
});
|
||||
@@ -111,7 +182,7 @@ namespace Song {
|
||||
private void instanciate_signals() {
|
||||
var signal_hub = SignalHub.get_instance();
|
||||
signal_hub.enter_yt_search_mode.connect(() => {
|
||||
add_button_revealer.set_reveal_child(false);
|
||||
add_buttons_revealer.set_reveal_child(false);
|
||||
controls_revealer.set_reveal_child(false);
|
||||
exit_yt_search_mode_revealer.set_reveal_child(true);
|
||||
action_bar.set_margin_start(-5);
|
||||
@@ -119,7 +190,7 @@ namespace Song {
|
||||
});
|
||||
|
||||
signal_hub.exit_yt_search_mode.connect(() => {
|
||||
add_button_revealer.set_reveal_child(true);
|
||||
add_buttons_revealer.set_reveal_child(true);
|
||||
controls_revealer.set_reveal_child(true);
|
||||
exit_yt_search_mode_revealer.set_reveal_child(false);
|
||||
action_bar.set_margin_start(0);
|
||||
@@ -175,7 +246,7 @@ namespace Song {
|
||||
}
|
||||
|
||||
construct {
|
||||
SongController.main_view_content = this;
|
||||
AppController.main_view_content = this;
|
||||
|
||||
var config = Config.get_instance();
|
||||
config.config_changed.connect(() => {
|
||||
@@ -183,6 +254,7 @@ namespace Song {
|
||||
if (config.playlists.length() == 1) {
|
||||
config.playlists.foreach((i) => {
|
||||
change_page(i);
|
||||
print("called");
|
||||
return;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
public class MusicListRow : Gtk.Box {
|
||||
|
||||
private Settings settings = new Settings("com.liyaowhen.Song.playlists");
|
||||
private Settings settings = new Settings("com.liyaowhen.YoutubeCollector.playlists");
|
||||
public PlaylistItem item;
|
||||
private PlaylistObject playlist;
|
||||
|
||||
@@ -37,22 +37,22 @@ namespace Song {
|
||||
play_button.add_css_class("flat");
|
||||
|
||||
play_button.clicked.connect(() => {
|
||||
if (SongController.song_controls.current_item != item) {
|
||||
SongController.song_controls.change_item(item);
|
||||
if (AppController.song_controls.current_item != item) {
|
||||
AppController.song_controls.change_item(item, playlist);
|
||||
play_button.icon_name = "media-playback-pause-symbolic";
|
||||
Timeout.add(1, () => {
|
||||
if (SongController.song_controls.current_item != item) {
|
||||
if (AppController.song_controls.current_item != item) {
|
||||
// when another song is called to play, reset the button state
|
||||
play_button.icon_name = "media-playback-start-symbolic";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
} else if (SongController.song_controls.isPlaying) {
|
||||
SongController.song_controls.pause();
|
||||
} else if (AppController.song_controls.isPlaying) {
|
||||
AppController.song_controls.pause();
|
||||
play_button.icon_name = "media-playback-start-symbolic";
|
||||
} else if (!SongController.song_controls.isPlaying) {
|
||||
SongController.song_controls.play();
|
||||
} else if (!AppController.song_controls.isPlaying) {
|
||||
AppController.song_controls.play();
|
||||
play_button.icon_name = "media-playback-pause-symbolic";
|
||||
}
|
||||
});
|
||||
@@ -65,7 +65,7 @@ namespace Song {
|
||||
|
||||
|
||||
var add_playlists_menu = new Menu();
|
||||
fill_playlists(add_playlists_menu);
|
||||
fill_playlists.begin(add_playlists_menu);
|
||||
|
||||
var menu = new Menu();
|
||||
menu.append_section("Add To Other Playlists", add_playlists_menu);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
public class NewPlaylistPopover : Adw.Dialog {
|
||||
|
||||
private bool valid_entry = false;
|
||||
@@ -51,8 +51,13 @@ namespace Song {
|
||||
var config = Config.get_instance ();
|
||||
var playlist = new PlaylistObject();
|
||||
playlist.name = entry.text;
|
||||
config.playlists.append(playlist);
|
||||
config.save();
|
||||
if (config.allocate_playlist_space (playlist)) {
|
||||
config.playlists.append(playlist);
|
||||
config.save.begin();
|
||||
close();
|
||||
} else {
|
||||
//TODO: return error for already existing playlist
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
public class PlaylistButton : Gtk.Box {
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Song {
|
||||
|
||||
main_button.clicked.connect(() => {
|
||||
//assumes that main_view is already instanciated
|
||||
SongController.main_view_content.change_page(playlist);
|
||||
AppController.main_view_content.change_page(playlist);
|
||||
});
|
||||
|
||||
Timeout.add(1, () => {
|
||||
|
||||
+10
-10
@@ -1,8 +1,8 @@
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
|
||||
public class SideBar : Adw.NavigationPage {
|
||||
|
||||
private Settings settings = new Settings("com.liyaowhen.Song");
|
||||
private Settings settings = new Settings("com.liyaowhen.YoutubeCollector");
|
||||
private Window window;
|
||||
|
||||
public SideBarContent side_bar_content;
|
||||
@@ -17,17 +17,17 @@ namespace Song {
|
||||
}
|
||||
|
||||
construct {
|
||||
SongController.side_bar = this;
|
||||
AppController.side_bar = this;
|
||||
|
||||
var toolbar_view = new Adw.ToolbarView();
|
||||
|
||||
var collapse_button = new Gtk.Button.from_icon_name ("folder-open-symbolic");
|
||||
collapse_button.clicked.connect(() => {
|
||||
if(SongController.split_view.get_show_sidebar()){
|
||||
SongController.split_view.show_sidebar = false;
|
||||
if(AppController.split_view.get_show_sidebar()){
|
||||
AppController.split_view.show_sidebar = false;
|
||||
collapse_button.set_icon_name("folder-open-symbolic");
|
||||
} else {
|
||||
SongController.split_view.show_sidebar = true;
|
||||
AppController.split_view.show_sidebar = true;
|
||||
collapse_button.set_icon_name("folder-symbolic");
|
||||
}
|
||||
collapsing();
|
||||
@@ -70,7 +70,7 @@ namespace Song {
|
||||
|
||||
public class SideBarContent : Gtk.Box {
|
||||
|
||||
private Settings settings = new Settings("com.liyaowhen.Song.playlists");
|
||||
private Settings settings = new Settings("com.liyaowhen.YoutubeCollector.playlists");
|
||||
public Gee.HashSet<PlaylistButton> playlist_buttons = new Gee.HashSet<PlaylistButton>();
|
||||
private MainView main_view;
|
||||
|
||||
@@ -148,15 +148,15 @@ namespace Song {
|
||||
|
||||
//print("sidbar requesting main_view_content switch to playlist of name:\n" + playlists.nth_data(0).name);
|
||||
Timeout.add(1, () => {
|
||||
if (SongController.main_view_content != null) {
|
||||
if (AppController.main_view_content != null) {
|
||||
if (initial_playlist != null) {
|
||||
SongController.main_view_content.change_page(initial_playlist);
|
||||
AppController.main_view_content.change_page(initial_playlist);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}, 1);
|
||||
SongController.sidebar_content = this;
|
||||
AppController.sidebar_content = this;
|
||||
|
||||
//reconfigure_playlist_button_group(); DOES NOT WORK FOR SOME REASON
|
||||
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
using Gst;
|
||||
|
||||
/*
|
||||
TODO: Work towards removing song controller entirely, instead use external apps to preview the files instead
|
||||
*/
|
||||
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
public class SongControls : Gtk.Box {
|
||||
|
||||
private Settings songs_list = new Settings("com.liyaowhen.Song.playlists");
|
||||
private Settings settings = new Settings("com.liyaowhen.Song");
|
||||
private Settings songs_list = new Settings("com.liyaowhen.YoutubeCollector.playlists");
|
||||
private Settings settings = new Settings("com.liyaowhen.YoutubeCollector");
|
||||
|
||||
public Gtk.Scale progress_bar;
|
||||
public Gtk.Adjustment progress_bar_adjustment;
|
||||
public PlaylistObject? playlist = null;
|
||||
private bool isDragging;
|
||||
private Gtk.Button progress_bar_controller;
|
||||
private uint? seekTimeout = null;
|
||||
|
||||
private string item_directory = Path.build_path("/", Environment.get_user_config_dir(), "com.liyaowhen.Song");
|
||||
private string item_directory = Path.build_path("/", Environment.get_user_config_dir(), "com.liyaowhen.YoutubeCollector");
|
||||
|
||||
public bool isPlaying;
|
||||
public PlaylistItem current_item;
|
||||
@@ -102,7 +106,7 @@ namespace Song {
|
||||
// add controls to control the music
|
||||
music_controls();
|
||||
|
||||
SongController.song_controls = this;
|
||||
AppController.song_controls = this;
|
||||
}
|
||||
|
||||
|
||||
@@ -160,13 +164,12 @@ namespace Song {
|
||||
isPlaying = false;
|
||||
}
|
||||
|
||||
public void change_item(PlaylistItem item) {
|
||||
public void change_item(PlaylistItem item, PlaylistObject playlist) {
|
||||
this.playlist = playlist;
|
||||
print("song is now " + item.name + "\n");
|
||||
current_item = item;
|
||||
string file_path = item.file;
|
||||
print("song full path is " + file_path);
|
||||
playbin.set_state(Gst.State.NULL);
|
||||
playbin.set_property("uri", File.new_for_path(file_path).get_uri());
|
||||
playbin.set_property("uri", File.new_build_filename(Environment.get_user_data_dir(), "com.liyaowhen.YoutubeCollector", playlist.name, item.file).get_uri());
|
||||
playbin.set_start_time(0);
|
||||
playbin.set_state(Gst.State.PLAYING);
|
||||
isPlaying = true;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
public enum YtSearchBarStates {
|
||||
ENLARGING,
|
||||
SHRINKING,
|
||||
@@ -238,7 +238,7 @@ namespace Song {
|
||||
}
|
||||
try {
|
||||
search_process = new Subprocess(GLib.SubprocessFlags.STDIN_PIPE | GLib.SubprocessFlags.STDOUT_PIPE | GLib.SubprocessFlags.STDERR_PIPE,
|
||||
Environment.get_user_config_dir() + "/com.liyaowhen.Song/search-utility", query);
|
||||
Environment.get_user_config_dir() + "/com.liyaowhen.YoutubeCollector/search-utility", query);
|
||||
} catch (GLib.Error e) {
|
||||
print(e.message);
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,8 +1,8 @@
|
||||
namespace Song {
|
||||
namespace YoutubeCollector {
|
||||
public class Window : Adw.ApplicationWindow {
|
||||
|
||||
|
||||
private Settings settings = new Settings ("com.liyaowhen.Song");
|
||||
private Settings settings = new Settings ("com.liyaowhen.YoutubeCollector");
|
||||
public SideBar sidebar;
|
||||
public MainView main_view;
|
||||
public Gtk.ShortcutAction ctrl_z = new Gtk.SignalAction("ctrl_z");
|
||||
@@ -13,7 +13,7 @@ namespace Song {
|
||||
|
||||
construct {
|
||||
|
||||
SongController.window = this;
|
||||
AppController.window = this;
|
||||
|
||||
var provider = new Gtk.CssProvider();
|
||||
provider.load_from_path("style.css");
|
||||
@@ -66,7 +66,7 @@ namespace Song {
|
||||
split_view.set_sidebar (sidebar);
|
||||
split_view.set_content(main_view);
|
||||
split_view.collapsed = false;
|
||||
SongController.split_view = split_view;
|
||||
AppController.split_view = split_view;
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user