json works, minor animations

This commit is contained in:
liyaowhen
2024-07-23 10:51:51 -07:00
parent 8b7d3d0c2e
commit c09d61bcdd
11 changed files with 271 additions and 129 deletions
+26 -13
View File
@@ -46,6 +46,7 @@ namespace Song {
public List<PlaylistObject> playlists;
public signal void config_changed();
public signal void loaded();
public static Config get_instance() {
if (instance == null) {
@@ -86,35 +87,45 @@ namespace Song {
// Parse settings from JSON
if (json_config.has_member("playlists")) {
Json.Object _playlists = json_config.get_object_member("playlists");
_playlists.foreach_member((object) => {
print("\n." + _playlists.get_members().data + ".\n");
// invalid methoud down below
var members = _playlists.get_members();
members.foreach((member_name) => {
PlaylistObject _playList = new PlaylistObject();
_playList.name = object.get_string_member("name");
var object = _playlists.get_member(member_name).get_object();
_playList.name = member_name;
// TODO: ADD PROPERTIES _playList.properties = whatever
object.get_object_member("items").foreach_member((item) => {
// TODO: fix item iterator, it is invalid as it calls on each member, not each "object"
var items_object = object.get_object_member("items");
var items_list = items_object.get_members();
items_list.foreach((item) => {
PlaylistItem _item = new PlaylistItem();
_item.item_type = item.get_int_member("item_type");
_item.name = item.get_string_member("name");
_item.file = item.get_string_member("file");
if (item.has_member("picture")) {
_item.picture = item.get_string_member("picture");
var _item_object = items_object.get_object_member(item);
_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.has_member("source")) {
_item.picture = item.get_string_member("source");
if (_item_object.has_member("source")) {
_item.picture = _item_object.get_string_member("source");
}
_playList.items.append(_item);
});
playlists.append(_playList);
});
}
}
loaded();
} catch (Error e) {
print("Error reading configuration file: %s\n", e.message);
}
}
}
/*public List<PlaylistObject> get_playlists() {
@@ -203,6 +214,7 @@ namespace Song {
public static void init(string app_name) {
string config_dir = Environment.get_user_config_dir();
string app_config_dir = Path.build_filename(config_dir, app_name);
config_file_path = Path.build_filename(app_config_dir, "config.json");
File app_dir = File.new_for_path(app_config_dir);
@@ -221,6 +233,7 @@ namespace Song {
print("file never existed");
Config.get_instance().save.begin(); // Create the file with default values
}
}
}
}
+3 -1
View File
@@ -10,7 +10,8 @@ song_sources = [
'controllers/song_controller.vala',
'widgets/music_list_row.vala',
'widgets/song_controls.vala',
'playlist_object.vala'
'playlist_object.vala',
'widgets/new_playlist_popover.vala'
]
song_deps = [
@@ -19,6 +20,7 @@ song_deps = [
dependency('vte-2.91-gtk4'),
dependency('json-glib-1.0'),
dependency('gstreamer-1.0'),
dependency('gee-0.8'),
]
song_sources += gnome.compile_resources('song-resources',
+35 -31
View File
@@ -13,6 +13,8 @@ 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");
public string song_title = "";
public string song_url = "";
@@ -91,7 +93,7 @@ namespace Song {
// starting page (choose what kind of app should be)
var song_folder_button = new Gtk.Button();
/*var song_folder_button = new Gtk.Button();
var song_folder_button_content = new Adw.ButtonContent();
song_folder_button_content.set_icon_name("folder-symbolic");
song_folder_button_content.set_parent(song_folder_button);
@@ -122,24 +124,16 @@ namespace Song {
});
file_chooser.show();
});
if (settings.get_string("song-folder") == null) {
isPlaylistFolder = false;
} else isPlaylistFolder = true;
song_folder_button.destroy.connect(() => {
// for safety
song_folder_button_content.destroy();
});
}); */
var online_button = new Gtk.Button();
var online_button_content = new Adw.ButtonContent();
online_button_content.set_icon_name("globe-alt2-symbolic");
online_button_content.set_label("from the internet (spotify and youtube supported)");
online_button_content.set_parent(online_button);
online_button.set_hexpand(false);
online_button.sensitive = isPlaylistFolder;
online_button.destroy.connect(() => {
// for safety
@@ -152,7 +146,7 @@ namespace Song {
import_button_content.set_label("use your own music");
import_button_content.set_parent(import_button);
import_button.set_hexpand(false);
import_button.sensitive = isPlaylistFolder;
import_button.destroy.connect(() => {
// for safety
@@ -162,7 +156,7 @@ namespace Song {
var starting_page_content = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
starting_page_content.append(song_folder_button);
starting_page_content.append(online_button);
starting_page_content.append(import_button);
@@ -229,8 +223,18 @@ namespace Song {
next_button.show();
next_button.sensitive = false;
steps_state = "online";
var path = File.new_for_path(item_directory);
if (!path.query_exists(null)) {
try {
path.make_directory_with_parents(null);
} catch (GLib.Error e) {
print(e.message);
}
}
terminal.spawn_async(Vte.PtyFlags.DEFAULT,
settings.get_string("song-folder"),
item_directory,
{"bash"},
null,
GLib.SpawnFlags.DO_NOT_REAP_CHILD,
@@ -241,21 +245,10 @@ namespace Song {
GLib.Cancellable.get_current(),
(vterm, gid) => {
});
print(Environment.get_user_data_dir());
});
// check if there is a folder for the songs to be stored
if (this.settings.get_string("song-folder").length == 0) {
song_folder_button_content.set_label("Set download directory");
song_folder_button.add_css_class("suggested-action");
online_button.set_sensitive(false);
import_button.set_sensitive(false);
} else {
song_folder_button_content.set_label(settings.get_string("song-folder"));
settings.changed.connect(() => {
song_folder_button_content.set_label(settings.get_string("song-folder"));
});
}
download.connect(() => {
navigation_view_steps.push(downloading_page);
@@ -268,12 +261,12 @@ namespace Song {
terminal.set_input_enabled(false);
terminal.child_exited.connect(() => {
Settings _list = new Settings("com.liyaowhen.Song.playlists");
//Check if the song created had no errors
bool file_valid = true;
try {
var file = File.new_for_path(settings.get_string("song-folder") + "/" + song_title + ".mp3");
print("file is \n" + settings.get_string("song-folder") + "/" + song_title + ".mp3");
var file = File.new_for_path(item_directory + "/" + song_title + ".mp3");
print("file is \n" + item_directory + "/" + song_title + ".mp3");
file.read();
} catch (GLib.Error e) {
print(e.message);
@@ -289,6 +282,17 @@ namespace Song {
foreach(string str in _list.get_strv(main_content.current_playlist)) {
print("this playlist has \n" + str);
}*/
PlaylistItem item = new PlaylistItem();
item.name = song_title;
item.file = "%s.%s".printf(Path.build_filename(item_directory, song_title), "mp3");
item.source = song_url;
var main_content = SongController.main_view_content;
main_content.current_playlist.add_item(item);
Config.get_instance().save.begin();
//TODO: implement
}
//TODO implement error page
+1 -1
View File
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/liyaowhen/Song">
<file preprocess="xml-stripblanks">window.ui</file>
<file preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
<file preprocess="xml-stripblanks">icons/globe-alt2-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/arrow-into-box-symbolic.svg</file>
<!--file>style.css</file!-->
</gresource>
</gresources>
+11 -2
View File
@@ -4,7 +4,7 @@ namespace Song {
public Settings settings = new Settings("com.liyaowhen.Song.playlists");
public MainViewContent main_content;
public string current_playlist;
public PlaylistObject current_playlist;
public MainView(Window _window) {
this.window = _window;
@@ -67,7 +67,6 @@ namespace Song {
public class MainViewContent : Gtk.Box {
private Settings settings = new Settings("com.liyaowhen.Song.playlists");
private Adw.NavigationView navigation_view;
public PlaylistObject current_playlist;
@@ -84,6 +83,16 @@ namespace Song {
construct {
SongController.main_view_content = this;
var config = Config.get_instance();
config.config_changed.connect(() => {
if (config.playlists.length() == 1) {
config.playlists.foreach((i) => {
change_page(i);
return;
});
}
});
}
public void change_page(PlaylistObject playlist) {
+93
View File
@@ -0,0 +1,93 @@
namespace Song {
public class NewPlaylistPopover : Adw.Dialog {
private bool valid_entry = false;
private bool _isBoth_ = true;
construct {
valid_entry = false;
Gtk.Button cancel = new Gtk.Button.with_label ("Cancel");
cancel.clicked.connect(() => {
close();
});
Gtk.Button confirm = new Gtk.Button.with_label ("Confirm");
confirm.sensitive = false;
var header = new Adw.HeaderBar ();
header.show_end_title_buttons = false;
header.show_start_title_buttons = false;
header.pack_end (confirm);
header.pack_start (cancel);
Gtk.Entry entry = new Gtk.Entry();
set_focus(entry);
List<weak PlaylistObject> already_existing_playlists = Config.get_instance().playlists.copy();
Gee.HashSet<string> already_existing_playlists_string;
already_existing_playlists.foreach ((i) => {
already_existing_playlists_string.add(i.name);
});
entry.changed.connect(() => {
if (entry.get_buffer ().length == 0) {
valid_entry = false;
confirm.sensitive = false;
} else {
if (!already_existing_playlists_string.contains(entry.text)) {
valid_entry = true;
confirm.sensitive = true;
} else {
valid_entry = false;
confirm.sensitive = false;
}
}
});
confirm.clicked.connect(() => {
if (valid_entry) {
var config = Config.get_instance ();
var playlist = new PlaylistObject();
playlist.name = entry.text;
config.playlists.append(playlist);
config.save();
}
});
var is_song = new Gtk.CheckButton.with_label ("song");
var is_video = new Gtk.CheckButton.with_label("video");
var is_both = new Gtk.CheckButton.with_label ("both");
is_both.activate.connect(() => {
_isBoth_ = true;
is_song.sensitive = false;
is_video.sensitive = false;
});
var check_box_row = new Gtk.Box(Gtk.Orientation.HORIZONTAL, 5);
check_box_row.vexpand = true;
check_box_row.hexpand = true;
check_box_row.halign = Gtk.Align.CENTER;
check_box_row.append(is_song);
check_box_row.append(is_video);
check_box_row.append(is_both);
// use settings to determine this later
is_both.set_active(true);
var box = new Gtk.Box(Gtk.Orientation.VERTICAL, 5);
box.append(entry);
box.append(check_box_row);
var content = new Adw.ToolbarView ();
content.add_top_bar (header);
content.set_content(box);
set_child(content);
set_title("Playlist Name");
}
}
}
+43 -10
View File
@@ -1,31 +1,64 @@
namespace Song {
public class PlaylistButton : Gtk.Button {
public class PlaylistButton : Gtk.Box {
private Settings settings = new Settings ("com.liyaowhen.Song");
public signal void removal_mode();
public signal void exit_removal_mode();
private PlaylistObject playlist;
private Gtk.Button remove_button;
private Gtk.Revealer remove_button_revealer;
public PlaylistButton (PlaylistObject _playlist) {
this.playlist = _playlist;
initialize();
}
construct {
orientation = Gtk.Orientation.HORIZONTAL;
add_css_class("toolbar");
remove_button = new Gtk.Button.from_icon_name("app-remove-symbolic");
remove_button_revealer = new Gtk.Revealer();
remove_button_revealer.set_child(remove_button);
remove_button_revealer.transition_type = Gtk.RevealerTransitionType.SWING_LEFT;
remove_button_revealer.set_reveal_child(false);
var main_button = new Gtk.Button();
main_button.hexpand = true;
append(main_button);
append(remove_button_revealer);
hexpand = true;
clicked.connect(() => {
main_button.clicked.connect(() => {
//assumes that main_view is already instanciated
SongController.main_view_content.change_page(playlist);
});
Timeout.add(1, () => {
if (playlist.name != null) {
main_button.label = playlist.name;
}
});
Config.get_instance().loaded.connect(() => {
if (playlist.name != null) {
main_button.label = playlist.name;
}
});
Config.get_instance().config_changed.connect(() => {
if (playlist.name != null) {
main_button.label = playlist.name;
}
});
}
public void initialize() {
set_label(playlist.name);
public void enter_removal_mode() {
remove_button_revealer.set_reveal_child(true);
}
public void exit_removal_mode() {
remove_button_revealer.set_reveal_child(false);
}
}
}
+40 -13
View File
@@ -38,7 +38,7 @@ namespace Song {
public class SideBarContent : Gtk.Box {
private Settings settings = new Settings("com.liyaowhen.Song.playlists");
public List<PlaylistButton> playlist_buttons;
public Gee.HashSet<PlaylistButton> playlist_buttons = new Gee.HashSet<PlaylistButton>();
private MainView main_view;
public SideBarContent() {
@@ -79,10 +79,28 @@ namespace Song {
var button = new PlaylistButton(_playlist);
if (!firstDeclared) {initial_playlist = _playlist; firstDeclared = true;}
playlist_buttons.append(button);
playlist_buttons.add(button);
append(button);
});
config.config_changed.connect(() => {
playlist_buttons.clear();
config.playlists.foreach((_playlist) => {
var button = new PlaylistButton(_playlist);
playlist_buttons.add(button);
append(button);
});
});
Timeout.add(1000, () => {
if (playlist_buttons == null) {
print("\n playlist buttons empty");
} else {
print("\n playlist not empty");
}
});
//print("sidbar requesting main_view_content switch to playlist of name:\n" + playlists.nth_data(0).name);
Timeout.add(1, () => {
@@ -99,16 +117,6 @@ namespace Song {
}
/*private void reconfigure_playlist_button_group() {
foreach (Playlist i in playlists) {
foreach (Playlist j in playlists) {
if (i != j) {
i.set_group(j);
}
}
}
}*/
}
@@ -120,7 +128,7 @@ namespace Song {
public SideBarControls(SideBarContent _sidebar_content) {
this.sidebar_content = _sidebar_content;
}
construct {
@@ -147,6 +155,25 @@ namespace Song {
action_bar.pack_start(select_button);
//action_bar.set_center_widget(empty_spacer());
action_bar.pack_end(options_button);
select_button.toggled.connect((i) => {
if (sidebar_content == null) {
print("\n sidebar is null");
} else if (sidebar_content.playlist_buttons == null) {
print("\n sidebar buttons are null");
}
if (i.get_active()) {
sidebar_content.playlist_buttons.foreach((e) => {
e.enter_removal_mode();
print(e.name);
});
} else {
sidebar_content.playlist_buttons.foreach((e) => {
e.exit_removal_mode();
print(e.name);
});
}
});
// signals
+6 -8
View File
@@ -12,10 +12,11 @@ namespace Song {
private bool isDragging;
private Gtk.Button progress_bar_controller;
private string item_directory = Path.build_path("/", Environment.get_user_config_dir(), "com.liyaowhen.Song");
public bool isPlaying;
public PlaylistItem current_item;
public Gst.Element playbin;
public SongControls() {
@@ -52,12 +53,9 @@ namespace Song {
}
print(position.to_string() + "\n" + duration.to_string() + "\n");
} else {
if (isDragging) print("stillDragging");
if (playbin == null) print("playbinnull");
print("what went wrong");
}
print("working");
return true;
});
@@ -144,9 +142,9 @@ namespace Song {
string file_path = item.file;
print("song full path is " + file_path);
playbin.set_state(Gst.State.NULL);
playbin.set_property("uri", file_path);
//playbin.set_state(Gst.State.PLAYING);
//isPlaying = true;
playbin.set_property("uri", File.new_for_path(file_path).get_uri());
playbin.set_state(Gst.State.PLAYING);
isPlaying = true;
}
-49
View File
@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk" version="4.0"/>
<requires lib="Adw" version="1.0"/>
<template class="SongWindow" parent="AdwApplicationWindow">
<property name="default-width">600</property>
<property name="default-height">300</property>
<property name="content">
<object class="AdwToolbarView">
<child type="top">
<object class="AdwHeaderBar" id="header_bar">
<child type="end">
<object class="GtkMenuButton">
<property name="primary">True</property>
<property name="icon-name">open-menu-symbolic</property>
<property name="tooltip-text" translatable="yes">Menu</property>
<property name="menu-model">primary_menu</property>
</object>
</child>
</object>
</child>
<property name="content">
<object class="GtkLabel" id="label">
<property name="label">Hello, World!</property>
<style>
<class name="title-1"/>
</style>
</object>
</property>
</object>
</property>
</template>
<menu id="primary_menu">
<section>
<item>
<attribute name="label" translatable="yes">_Preferences</attribute>
<attribute name="action">app.preferences</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_Keyboard Shortcuts</attribute>
<attribute name="action">win.show-help-overlay</attribute>
</item>
<item>
<attribute name="label" translatable="yes">_About Song</attribute>
<attribute name="action">app.about</attribute>
</item>
</section>
</menu>
</interface>
+13 -1
View File
@@ -29,11 +29,22 @@ namespace Song {
//title_bar.set_decoration_layout("icon:close");
title_bar.show_title = false;
var add_playlist = new Gtk.Button();
var add_playlist_content = new Adw.ButtonContent();
add_playlist_content.set_icon_name("tab-new-symbolic");
add_playlist_content.set_label("New Playlist");
add_playlist.set_child(add_playlist_content);
add_playlist.clicked.connect(() => {
var popover = new NewPlaylistPopover();
popover.present(this);
});
var add_button = new Gtk.Button();
var add_button_content = new Adw.ButtonContent ();
add_button_content.set_icon_name("tab-new-symbolic");
add_button_content.set_label("new song");
add_button_content.set_parent(add_button);
add_button.set_child(add_button_content);
add_button.clicked.connect(() => {
new_music_popover_show();
@@ -41,6 +52,7 @@ namespace Song {
var collapse_button = new Gtk.Button.from_icon_name ("folder-open-symbolic");
title_bar.pack_start (collapse_button);
title_bar.pack_start(add_playlist);
title_bar.pack_start(add_button);