Loading src/application/application-window.vala +308 −171 Original line number Diff line number Diff line Loading @@ -22,111 +22,151 @@ namespace MLM { /** * MLM GUI application window class. */ [GtkTemplate (ui = "/mx/unam/MLM/mlm.ui")] public class ApplicationWindow : Gtk.ApplicationWindow { /* Cascade Style Sheet. */ private const string CSS_URI = "resource:///mx/unam/MLM/mlm.css"; /* CD icon name. */ private const string ICON_NAME_CD = "media-optical-cd-audio-symbolic"; /* Avatar icon name. */ private const string ICON_NAME_AVATAR = "avatar-default-symbolic"; /* Play icon name. */ private const string ICON_NAME_PLAY = "media-playback-start-symbolic"; /* Pause icon name. */ private const string ICON_NAME_PAUSE = "media-playback-pause-symbolic"; /* Icon size. */ private const Gtk.IconSize ICON_SIZE = Gtk.IconSize.SMALL_TOOLBAR; /* The header bar. */ [GtkChild] private Gtk.HeaderBar header_bar; /* The previous button. */ [GtkChild] private Gtk.Button previous_button; /* The next button. */ [GtkChild] private Gtk.Button next_button; /* The save button. */ [GtkChild] private Gtk.Button save_button; /* The encode menu button. */ [GtkChild] private Gtk.MenuButton reencode_menu_button; private Gtk.MenuButton encode_menu_button; /* The encode popover. */ [GtkChild] private Gtk.Popover reencode_popover; private Gtk.Popover encode_popover; /* The encode progress bar. */ [GtkChild] private Gtk.ProgressBar bar; private Gtk.ProgressBar encode_progress_bar; /* The tags frame. */ [GtkChild] private Gtk.Frame tags_frame; /* The artist entry. */ [GtkChild] private Gtk.Entry artist_entry; /* The title entry. */ [GtkChild] private Gtk.Entry title_entry; /* The album entry. */ [GtkChild] private Gtk.Entry album_entry; /* The band entry. */ [GtkChild] private Gtk.Entry band_entry; /* The year spin button. */ [GtkChild] private Gtk.SpinButton year_spin_button; /* The year adjustment. */ [GtkChild] private Gtk.Adjustment year_adjustment; /* The disc spin button. */ [GtkChild] private Gtk.SpinButton disc_spin_button; /* The track spin button. */ [GtkChild] private Gtk.SpinButton track_spin_button; /* The total spin button. */ [GtkChild] private Gtk.SpinButton total_spin_button; /* The genre combo box. */ [GtkChild] private Gtk.ComboBox genre_combobox; private Gtk.ComboBox genre_combo_box; /* The genre entry. */ [GtkChild] private Gtk.Entry genre_entry; /* The genre model. */ [GtkChild] private Gtk.ListStore genre_model; /* The comment entry. */ [GtkChild] private Gtk.Entry comment_entry; /* The composer entry. */ [GtkChild] private Gtk.Entry composer_entry; /* The original entry. */ [GtkChild] private Gtk.Entry original_entry; /* The cover image. */ [GtkChild] private Gtk.Image cover_image; /* The artist image. */ [GtkChild] private Gtk.Image artist_image; /* The play image. */ [GtkChild] private Gtk.Image play_image; /* The play adjustment. */ [GtkChild] private Gtk.Adjustment play_adjustment; /* The time label. */ [GtkChild] private Gtk.Label time_label; /* The filename label. */ [GtkChild] private Gtk.Label filename_label; private bool ignore_popover; /* The MLM application. */ private Application mlm; private const string CSS_URI = "resource:///mx/unam/MLM/mlm.css"; private const string ICON_NAME_CD = "media-optical-cd-audio-symbolic"; private const string ICON_NAME_AVATAR = "avatar-default-symbolic"; private const string ICON_NAME_PLAY = "media-playback-start-symbolic"; private const string ICON_NAME_PAUSE = "media-playback-pause-symbolic"; private const Gtk.IconSize ICON_SIZE = Gtk.IconSize.SMALL_TOOLBAR; /** * Initializes the application window. * @param application the application. */ public ApplicationWindow(Gtk.Application application) { GLib.Object(application: application); mlm = application as Application; Gtk.Window.set_default_icon_name("mlm"); var provider = new Gtk.CssProvider(); try { Loading @@ -139,156 +179,122 @@ namespace MLM { provider, 999); var date_time = new GLib.DateTime.now_local(); year_adjustment.upper = date_time.get_year(); reencode.bind_property("active", popover, "visible", GLib.BindingFlags.BIDIRECTIONAL); encode_menu_button.bind_property( "active", encode_popover, "visible", GLib.BindingFlags.BIDIRECTIONAL); genre_model.set_sort_column_id(0, Gtk.SortType.ASCENDING); } /* The on match selected callback. */ [GtkCallback] public bool on_match_selected(Gtk.TreeModel m, Gtk.TreeIter i) { genre_combobox.set_active_iter(i); private bool on_match_selected(Gtk.TreeModel m, Gtk.TreeIter i) { genre_combo_box.set_active_iter(i); return true; } /* The on previous clicked callback. */ [GtkCallback] public void on_previous_clicked() { private void on_previous_clicked() { mlm.previous(); } /* The on next clicked callback. */ [GtkCallback] public void on_next_clicked() { private void on_next_clicked() { mlm.next(); } /* The on popover visibility changed callback. */ [GtkCallback] public void on_clear_artist_clicked() {} [GtkCallback] public void on_clear_cover_clicked() {} private uint8[]? select_image(string title) { var dialog = new Gtk.FileChooserDialog(title, this, Gtk.FileChooserAction.OPEN, _("_Cancel"), Gtk.ResponseType.CANCEL, _("_Open"), Gtk.ResponseType.ACCEPT); int r = dialog.run(); string fn = dialog.get_filename(); dialog.destroy(); if (r != Gtk.ResponseType.ACCEPT) return null; try { uint8[] data; FileUtils.get_data(fn, out data); return data; } catch (GLib.FileError fe) { warning(_("There was an error loading image '%s'").printf(fn)); } return null; } [GtkCallback] public void on_open_artist_clicked() { var data = select_image(_("Select image for artist")); mlm.set_artist_data(data); update_image(artist_image, data); } [GtkCallback] public void on_open_cover_clicked() { var data = select_image(_("Select image for cover")); mlm.set_cover_data(data); update_image(cover_image, data); } [GtkCallback] public void popover_visibility_changed() { if (!popover.visible) { private void on_popover_visibility_changed() { if (!encode_popover.visible) { mlm.stop_encoder(); } else { progress_bar.set_fraction(0.0); mlm.start_encoder() encode_progress_bar.set_fraction(0.0); mlm.start_encoder(); } } /* The on save clicked callback. */ [GtkCallback] public void on_save_clicked() { private void on_save_clicked() { mlm.save(); save.sensitive = false; save_button.sensitive = false; } private void player_state_changed(Gst.State state) { switch (state) { case Gst.State.PLAYING: /* The on play clicked callback. */ [GtkCallback] private void on_play_clicked() { if (!mlm.is_player_playing()) { play_image.set_from_icon_name(ICON_NAME_PAUSE, ICON_SIZE); GLib.Idle.add(monitor_play); break; case Gst.State.PAUSED: int64 d, p; if (player.get_completion(out d, out p) == 0.0) reset_timer(); mlm.start_player(); } else { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); break; } mlm.pause_player(); } public void upgrade_progress_bar(double percentage) { progress_bar.set_fraction(percentage); } public void hide_progress_bar() { ignore_popover = true; popover.visible = false; ignore_popover = false; /* The on open artist image clicked callback. */ [GtkCallback] private void on_open_artist_image_clicked() { var data = select_image(_("Select image for artist")); mlm.set_artist_picture_data(data); update_image(artist_image, data); } private void reset_timer() { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); play_adjustment.set_value(0.0); time.set_text("00:00"); /* The on clear artist image clicked callback. */ [GtkCallback] private void on_clear_artist_image_clicked() { mlm.set_artist_picture_data(null); set_default_image(artist_image); save_button.sensitive = true; } private bool monitor_play() { if (!player.working) { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); return false; /* The on open cover image clicked callback. */ [GtkCallback] private void on_open_cover_image_clicked() { var data = select_image(_("Select image for cover")); mlm.set_cover_picture_data(data); update_image(cover_image, data); } int64 position = -1, duration = -1; double p = player.get_completion(out position, out duration); play_adjustment.set_value(p); int64 tsecs = duration / 1000000000l; int mins = (int)(tsecs / 60); int secs = (int)(tsecs % 60); time.set_text("%02d:%02d".printf(mins, secs)); return true; /* The on clear cover image clicked callback. */ [GtkCallback] private void on_clear_cover_image_clicked() { mlm.set_cover_picture_data(null); set_default_image(cover_image); save_button.sensitive = true; } /* The on scale change callback. */ [GtkCallback] public void on_play_clicked() { if (!player.working) { play_image.set_from_icon_name(ICON_NAME_PAUSE, ICON_SIZE); mlm.play(); } else { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); mlm.pause(); private bool on_scale_change_value(Gtk.ScrollType scroll, double value) { if (value < 0.0) value = 0.0; if (value > 1.0) value = 1.0; if (!mlm.seek_player(value)) { reset_timer(); return true; } return false; } /* The on window destroy callback. */ [GtkCallback] public void on_window_destroy() { private void on_window_destroy() { mlm.quit(); } /* The on tags changed callback. */ [GtkCallback] public void tags_changed() { save.sensitive = true; private void on_tags_changed() { save_button.sensitive = true; } /* The on window key press callback. */ [GtkCallback] public bool on_window_key_press(Gdk.EventKey e) { private bool on_window_key_press(Gdk.EventKey e) { if (e.keyval == Gdk.Key.Page_Up) { on_previous_clicked(); return true; Loading @@ -308,19 +314,42 @@ namespace MLM { return false; } [GtkCallback] public bool on_scale_change_value(Gtk.ScrollType scroll, double value) { if (value < 0.0) value = 0.0; if (value > 1.0) value = 1.0; if (!player.seek(value)) { reset_timer(); return true; /** * Updates the encoding popover. * @param percentage the percentage of the encoding. */ public void update_encoding(double percentage) { encode_progress_bar.set_fraction(percentage); } return false; /** * Hides the encoding popover. */ public void hide_encoding() { encode_popover.visible = false; } /** * Sets the view at play started. */ public void play_started() { play_image.set_from_icon_name(ICON_NAME_PAUSE, ICON_SIZE); GLib.Idle.add(monitor_player); } /** * Sets the view at play paused. */ public void play_paused() { if (mlm.player_completion() == 0.0) reset_timer(); play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); } /** * Shows a warning dialog. * @param message the warning message. */ public void warning(string message) { var dialog = new Gtk.MessageDialog( this, Gtk.DialogFlags.DESTROY_WITH_PARENT, Loading @@ -331,6 +360,154 @@ namespace MLM { dialog.destroy(); } /* Monitors the player in the model. */ private bool monitor_player() { if (!mlm.is_player_playing()) { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); return false; } play_adjustment.set_value(mlm.player_completion()); time_label.set_text(mlm.player_time()); return true; } /* Resets the timer. */ private void reset_timer() { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); play_adjustment.set_value(0.0); time_label.set_text("00:00"); } /** * Enables the UI. */ public void enable_ui(bool enable) { encode_menu_button.sensitive = previous_button.sensitive = next_button.sensitive = save_button.sensitive = tags_frame.sensitive = enable; } /** * Updates the view. * @param filename the filename. * @param tags the tags. * @param current the current file index. * @param total the total number of files. */ public void update_view(string filename, FileTags tags, int current, int total) { header_bar.set_subtitle("%d / %d".printf(current, total)); var basename = GLib.Path.get_basename(filename); var markup = GLib.Markup.printf_escaped("<b>%s</b>", basename); filename_label.set_markup(markup); reset_timer(); artist_entry.text = tags.artist != null ? tags.artist : ""; title_entry.text = tags.title != null ? tags.title : ""; album_entry.text = tags.album != null ? tags.album : ""; band_entry.text = tags.band != null ? tags.band : ""; year_spin_button.value = tags.year != -1 ? tags.year : 1900; disc_spin_button.value = tags.disc != -1 ? tags.disc : 1; track_spin_button.value = tags.track != -1 ? tags.track : 1; total_spin_button.value = tags.total != -1 ? tags.total : 1; genre_entry.text = (tags.genre >= 0 && tags.genre < Genre.total()) ? Genre.all()[tags.genre].to_string() : ""; comment_entry.text = tags.comment != null ? tags.comment : ""; composer_entry.text = tags.composer != null ? tags.composer : ""; original_entry.text = tags.original != null ? tags.original : ""; update_image(cover_image, tags.cover_picture); update_image(artist_image, tags.artist_picture); previous_button.sensitive = current != 1; next_button.sensitive = current < total; save_button.sensitive = false; } /** * Updates the model. * @param tags the tags to update. */ public void update_model(FileTags tags) { tags.artist = artist_entry.text != "" ? artist_entry.text : null; tags.title = title_entry.text != "" ? title_entry.text : null; tags.album = album_entry.text != "" ? album_entry.text : null; tags.band = band_entry.text != "" ? band_entry.text : null; tags.year = (int)year_spin_button.value; tags.disc = (int)disc_spin_button.value; tags.track = (int)track_spin_button.value; tags.total = (int)total_spin_button.value; tags.genre = genre_entry.text != "" ? Genre.index_of(genre_entry.text) : -1; tags.comment = comment_entry.text != "" ? comment_entry.text : null; tags.composer = composer_entry.text != "" ? composer_entry.text : null; tags.original = original_entry.text != "" ? original_entry.text : null; } /** * Returns the normalized filename for the view. * @param filename the filename. */ public string get_normalized_filename(string filename) { var norm = ""; int cont = 0; do { string d = Path.get_dirname(filename); string s = GLib.Path.DIR_SEPARATOR_S; string a = artist_entry.text.replace("/", "_"); string t = title_entry.text.replace("/", "_"); string e = (cont == 0) ? ".mp3" : "-%d.mp3".printf(cont); norm = d + s + a + " - " + t + e; cont++; } while (GLib.FileUtils.test(norm, GLib.FileTest.EXISTS)); return norm; } /** * Shows the about dialog. */ public void about() { string[] authors = { "Canek Peláez Valdés <canek@ciencias.unam.mx>" }; Gtk.show_about_dialog( this, "authors", authors, "comments", _("A Gtk+ based music library maintainer"), "copyright", "Copyright © 2013-2018 Canek Peláez Valdés", "license-type", Gtk.License.GPL_3_0, "logo-icon-name", "mlm", "version", Config.PACKAGE_VERSION, "website", ("https://canek@aztlan.fciencias.unam.mx/" + "gitlab/canek/mlm.git"), "wrap-license", true); } /* Selects an image from a file. */ private uint8[]? select_image(string title) { var dialog = new Gtk.FileChooserDialog(title, this, Gtk.FileChooserAction.OPEN, _("_Cancel"), Gtk.ResponseType.CANCEL, _("_Open"), Gtk.ResponseType.ACCEPT); int r = dialog.run(); string fn = dialog.get_filename(); dialog.destroy(); if (r != Gtk.ResponseType.ACCEPT) return null; try { uint8[] data; FileUtils.get_data(fn, out data); return data; } catch (GLib.FileError fe) { warning(_("There was an error loading image '%s'").printf(fn)); } return null; } /* Sets a default image. */ private void set_default_image(Gtk.Image image) { if (image == cover_image) image.set_from_icon_name(ICON_NAME_CD, ICON_SIZE); Loading @@ -339,10 +516,12 @@ namespace MLM { image.pixel_size = 140; } private void update_image(Gtk.Image image, uint8[] data) { if (data == null) /* Updates an image. */ private void update_image(Gtk.Image image, uint8[] data) { if (data == null) { set_default_image(image); return; } var mis = new MemoryInputStream.from_data(data, null); Gdk.Pixbuf thumb = null; try { Loading @@ -353,53 +532,11 @@ namespace MLM { Gdk.InterpType.BILINEAR); } catch (GLib.Error e) { warning(_("Could not set pixbuf from data.")); set_default_image(image); return; } save_button.sensitive = true; image.set_from_pixbuf(thumb); } private bool dispose_player() { if (player == null || player.state == Gst.State.NULL) { player = new Player(filename); player.state_changed.connect(player_state_changed); return false; } return true; } private void define_genre(string g) { Gtk.TreeIter iter = {}; if (!genre_model.get_iter_first(out iter)) return; int c = 0; do { string ig; genre_model.get(iter, 0, out ig); if (g == ig) genre_combobox.active = c; c++; } while (genre_model.iter_next(ref iter)); } private void define_filename(string f) { _filename = f; var basename = GLib.Path.get_basename(_filename); var markup = GLib.Markup.printf_escaped("<b>%s</b>", basename); filename_widget.set_markup(markup); if (player != null) player.finish(); reset_timer(); GLib.Idle.add(dispose_player); } private void define_current(int c) { _current = c; header.set_subtitle("%d / %d".printf(_current, _last)); } private void define_last(int l) { _last = l; header.set_subtitle("%d / %d".printf(_current, _last)); } } } src/application/application.vala +195 −117 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
src/application/application-window.vala +308 −171 Original line number Diff line number Diff line Loading @@ -22,111 +22,151 @@ namespace MLM { /** * MLM GUI application window class. */ [GtkTemplate (ui = "/mx/unam/MLM/mlm.ui")] public class ApplicationWindow : Gtk.ApplicationWindow { /* Cascade Style Sheet. */ private const string CSS_URI = "resource:///mx/unam/MLM/mlm.css"; /* CD icon name. */ private const string ICON_NAME_CD = "media-optical-cd-audio-symbolic"; /* Avatar icon name. */ private const string ICON_NAME_AVATAR = "avatar-default-symbolic"; /* Play icon name. */ private const string ICON_NAME_PLAY = "media-playback-start-symbolic"; /* Pause icon name. */ private const string ICON_NAME_PAUSE = "media-playback-pause-symbolic"; /* Icon size. */ private const Gtk.IconSize ICON_SIZE = Gtk.IconSize.SMALL_TOOLBAR; /* The header bar. */ [GtkChild] private Gtk.HeaderBar header_bar; /* The previous button. */ [GtkChild] private Gtk.Button previous_button; /* The next button. */ [GtkChild] private Gtk.Button next_button; /* The save button. */ [GtkChild] private Gtk.Button save_button; /* The encode menu button. */ [GtkChild] private Gtk.MenuButton reencode_menu_button; private Gtk.MenuButton encode_menu_button; /* The encode popover. */ [GtkChild] private Gtk.Popover reencode_popover; private Gtk.Popover encode_popover; /* The encode progress bar. */ [GtkChild] private Gtk.ProgressBar bar; private Gtk.ProgressBar encode_progress_bar; /* The tags frame. */ [GtkChild] private Gtk.Frame tags_frame; /* The artist entry. */ [GtkChild] private Gtk.Entry artist_entry; /* The title entry. */ [GtkChild] private Gtk.Entry title_entry; /* The album entry. */ [GtkChild] private Gtk.Entry album_entry; /* The band entry. */ [GtkChild] private Gtk.Entry band_entry; /* The year spin button. */ [GtkChild] private Gtk.SpinButton year_spin_button; /* The year adjustment. */ [GtkChild] private Gtk.Adjustment year_adjustment; /* The disc spin button. */ [GtkChild] private Gtk.SpinButton disc_spin_button; /* The track spin button. */ [GtkChild] private Gtk.SpinButton track_spin_button; /* The total spin button. */ [GtkChild] private Gtk.SpinButton total_spin_button; /* The genre combo box. */ [GtkChild] private Gtk.ComboBox genre_combobox; private Gtk.ComboBox genre_combo_box; /* The genre entry. */ [GtkChild] private Gtk.Entry genre_entry; /* The genre model. */ [GtkChild] private Gtk.ListStore genre_model; /* The comment entry. */ [GtkChild] private Gtk.Entry comment_entry; /* The composer entry. */ [GtkChild] private Gtk.Entry composer_entry; /* The original entry. */ [GtkChild] private Gtk.Entry original_entry; /* The cover image. */ [GtkChild] private Gtk.Image cover_image; /* The artist image. */ [GtkChild] private Gtk.Image artist_image; /* The play image. */ [GtkChild] private Gtk.Image play_image; /* The play adjustment. */ [GtkChild] private Gtk.Adjustment play_adjustment; /* The time label. */ [GtkChild] private Gtk.Label time_label; /* The filename label. */ [GtkChild] private Gtk.Label filename_label; private bool ignore_popover; /* The MLM application. */ private Application mlm; private const string CSS_URI = "resource:///mx/unam/MLM/mlm.css"; private const string ICON_NAME_CD = "media-optical-cd-audio-symbolic"; private const string ICON_NAME_AVATAR = "avatar-default-symbolic"; private const string ICON_NAME_PLAY = "media-playback-start-symbolic"; private const string ICON_NAME_PAUSE = "media-playback-pause-symbolic"; private const Gtk.IconSize ICON_SIZE = Gtk.IconSize.SMALL_TOOLBAR; /** * Initializes the application window. * @param application the application. */ public ApplicationWindow(Gtk.Application application) { GLib.Object(application: application); mlm = application as Application; Gtk.Window.set_default_icon_name("mlm"); var provider = new Gtk.CssProvider(); try { Loading @@ -139,156 +179,122 @@ namespace MLM { provider, 999); var date_time = new GLib.DateTime.now_local(); year_adjustment.upper = date_time.get_year(); reencode.bind_property("active", popover, "visible", GLib.BindingFlags.BIDIRECTIONAL); encode_menu_button.bind_property( "active", encode_popover, "visible", GLib.BindingFlags.BIDIRECTIONAL); genre_model.set_sort_column_id(0, Gtk.SortType.ASCENDING); } /* The on match selected callback. */ [GtkCallback] public bool on_match_selected(Gtk.TreeModel m, Gtk.TreeIter i) { genre_combobox.set_active_iter(i); private bool on_match_selected(Gtk.TreeModel m, Gtk.TreeIter i) { genre_combo_box.set_active_iter(i); return true; } /* The on previous clicked callback. */ [GtkCallback] public void on_previous_clicked() { private void on_previous_clicked() { mlm.previous(); } /* The on next clicked callback. */ [GtkCallback] public void on_next_clicked() { private void on_next_clicked() { mlm.next(); } /* The on popover visibility changed callback. */ [GtkCallback] public void on_clear_artist_clicked() {} [GtkCallback] public void on_clear_cover_clicked() {} private uint8[]? select_image(string title) { var dialog = new Gtk.FileChooserDialog(title, this, Gtk.FileChooserAction.OPEN, _("_Cancel"), Gtk.ResponseType.CANCEL, _("_Open"), Gtk.ResponseType.ACCEPT); int r = dialog.run(); string fn = dialog.get_filename(); dialog.destroy(); if (r != Gtk.ResponseType.ACCEPT) return null; try { uint8[] data; FileUtils.get_data(fn, out data); return data; } catch (GLib.FileError fe) { warning(_("There was an error loading image '%s'").printf(fn)); } return null; } [GtkCallback] public void on_open_artist_clicked() { var data = select_image(_("Select image for artist")); mlm.set_artist_data(data); update_image(artist_image, data); } [GtkCallback] public void on_open_cover_clicked() { var data = select_image(_("Select image for cover")); mlm.set_cover_data(data); update_image(cover_image, data); } [GtkCallback] public void popover_visibility_changed() { if (!popover.visible) { private void on_popover_visibility_changed() { if (!encode_popover.visible) { mlm.stop_encoder(); } else { progress_bar.set_fraction(0.0); mlm.start_encoder() encode_progress_bar.set_fraction(0.0); mlm.start_encoder(); } } /* The on save clicked callback. */ [GtkCallback] public void on_save_clicked() { private void on_save_clicked() { mlm.save(); save.sensitive = false; save_button.sensitive = false; } private void player_state_changed(Gst.State state) { switch (state) { case Gst.State.PLAYING: /* The on play clicked callback. */ [GtkCallback] private void on_play_clicked() { if (!mlm.is_player_playing()) { play_image.set_from_icon_name(ICON_NAME_PAUSE, ICON_SIZE); GLib.Idle.add(monitor_play); break; case Gst.State.PAUSED: int64 d, p; if (player.get_completion(out d, out p) == 0.0) reset_timer(); mlm.start_player(); } else { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); break; } mlm.pause_player(); } public void upgrade_progress_bar(double percentage) { progress_bar.set_fraction(percentage); } public void hide_progress_bar() { ignore_popover = true; popover.visible = false; ignore_popover = false; /* The on open artist image clicked callback. */ [GtkCallback] private void on_open_artist_image_clicked() { var data = select_image(_("Select image for artist")); mlm.set_artist_picture_data(data); update_image(artist_image, data); } private void reset_timer() { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); play_adjustment.set_value(0.0); time.set_text("00:00"); /* The on clear artist image clicked callback. */ [GtkCallback] private void on_clear_artist_image_clicked() { mlm.set_artist_picture_data(null); set_default_image(artist_image); save_button.sensitive = true; } private bool monitor_play() { if (!player.working) { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); return false; /* The on open cover image clicked callback. */ [GtkCallback] private void on_open_cover_image_clicked() { var data = select_image(_("Select image for cover")); mlm.set_cover_picture_data(data); update_image(cover_image, data); } int64 position = -1, duration = -1; double p = player.get_completion(out position, out duration); play_adjustment.set_value(p); int64 tsecs = duration / 1000000000l; int mins = (int)(tsecs / 60); int secs = (int)(tsecs % 60); time.set_text("%02d:%02d".printf(mins, secs)); return true; /* The on clear cover image clicked callback. */ [GtkCallback] private void on_clear_cover_image_clicked() { mlm.set_cover_picture_data(null); set_default_image(cover_image); save_button.sensitive = true; } /* The on scale change callback. */ [GtkCallback] public void on_play_clicked() { if (!player.working) { play_image.set_from_icon_name(ICON_NAME_PAUSE, ICON_SIZE); mlm.play(); } else { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); mlm.pause(); private bool on_scale_change_value(Gtk.ScrollType scroll, double value) { if (value < 0.0) value = 0.0; if (value > 1.0) value = 1.0; if (!mlm.seek_player(value)) { reset_timer(); return true; } return false; } /* The on window destroy callback. */ [GtkCallback] public void on_window_destroy() { private void on_window_destroy() { mlm.quit(); } /* The on tags changed callback. */ [GtkCallback] public void tags_changed() { save.sensitive = true; private void on_tags_changed() { save_button.sensitive = true; } /* The on window key press callback. */ [GtkCallback] public bool on_window_key_press(Gdk.EventKey e) { private bool on_window_key_press(Gdk.EventKey e) { if (e.keyval == Gdk.Key.Page_Up) { on_previous_clicked(); return true; Loading @@ -308,19 +314,42 @@ namespace MLM { return false; } [GtkCallback] public bool on_scale_change_value(Gtk.ScrollType scroll, double value) { if (value < 0.0) value = 0.0; if (value > 1.0) value = 1.0; if (!player.seek(value)) { reset_timer(); return true; /** * Updates the encoding popover. * @param percentage the percentage of the encoding. */ public void update_encoding(double percentage) { encode_progress_bar.set_fraction(percentage); } return false; /** * Hides the encoding popover. */ public void hide_encoding() { encode_popover.visible = false; } /** * Sets the view at play started. */ public void play_started() { play_image.set_from_icon_name(ICON_NAME_PAUSE, ICON_SIZE); GLib.Idle.add(monitor_player); } /** * Sets the view at play paused. */ public void play_paused() { if (mlm.player_completion() == 0.0) reset_timer(); play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); } /** * Shows a warning dialog. * @param message the warning message. */ public void warning(string message) { var dialog = new Gtk.MessageDialog( this, Gtk.DialogFlags.DESTROY_WITH_PARENT, Loading @@ -331,6 +360,154 @@ namespace MLM { dialog.destroy(); } /* Monitors the player in the model. */ private bool monitor_player() { if (!mlm.is_player_playing()) { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); return false; } play_adjustment.set_value(mlm.player_completion()); time_label.set_text(mlm.player_time()); return true; } /* Resets the timer. */ private void reset_timer() { play_image.set_from_icon_name(ICON_NAME_PLAY, ICON_SIZE); play_adjustment.set_value(0.0); time_label.set_text("00:00"); } /** * Enables the UI. */ public void enable_ui(bool enable) { encode_menu_button.sensitive = previous_button.sensitive = next_button.sensitive = save_button.sensitive = tags_frame.sensitive = enable; } /** * Updates the view. * @param filename the filename. * @param tags the tags. * @param current the current file index. * @param total the total number of files. */ public void update_view(string filename, FileTags tags, int current, int total) { header_bar.set_subtitle("%d / %d".printf(current, total)); var basename = GLib.Path.get_basename(filename); var markup = GLib.Markup.printf_escaped("<b>%s</b>", basename); filename_label.set_markup(markup); reset_timer(); artist_entry.text = tags.artist != null ? tags.artist : ""; title_entry.text = tags.title != null ? tags.title : ""; album_entry.text = tags.album != null ? tags.album : ""; band_entry.text = tags.band != null ? tags.band : ""; year_spin_button.value = tags.year != -1 ? tags.year : 1900; disc_spin_button.value = tags.disc != -1 ? tags.disc : 1; track_spin_button.value = tags.track != -1 ? tags.track : 1; total_spin_button.value = tags.total != -1 ? tags.total : 1; genre_entry.text = (tags.genre >= 0 && tags.genre < Genre.total()) ? Genre.all()[tags.genre].to_string() : ""; comment_entry.text = tags.comment != null ? tags.comment : ""; composer_entry.text = tags.composer != null ? tags.composer : ""; original_entry.text = tags.original != null ? tags.original : ""; update_image(cover_image, tags.cover_picture); update_image(artist_image, tags.artist_picture); previous_button.sensitive = current != 1; next_button.sensitive = current < total; save_button.sensitive = false; } /** * Updates the model. * @param tags the tags to update. */ public void update_model(FileTags tags) { tags.artist = artist_entry.text != "" ? artist_entry.text : null; tags.title = title_entry.text != "" ? title_entry.text : null; tags.album = album_entry.text != "" ? album_entry.text : null; tags.band = band_entry.text != "" ? band_entry.text : null; tags.year = (int)year_spin_button.value; tags.disc = (int)disc_spin_button.value; tags.track = (int)track_spin_button.value; tags.total = (int)total_spin_button.value; tags.genre = genre_entry.text != "" ? Genre.index_of(genre_entry.text) : -1; tags.comment = comment_entry.text != "" ? comment_entry.text : null; tags.composer = composer_entry.text != "" ? composer_entry.text : null; tags.original = original_entry.text != "" ? original_entry.text : null; } /** * Returns the normalized filename for the view. * @param filename the filename. */ public string get_normalized_filename(string filename) { var norm = ""; int cont = 0; do { string d = Path.get_dirname(filename); string s = GLib.Path.DIR_SEPARATOR_S; string a = artist_entry.text.replace("/", "_"); string t = title_entry.text.replace("/", "_"); string e = (cont == 0) ? ".mp3" : "-%d.mp3".printf(cont); norm = d + s + a + " - " + t + e; cont++; } while (GLib.FileUtils.test(norm, GLib.FileTest.EXISTS)); return norm; } /** * Shows the about dialog. */ public void about() { string[] authors = { "Canek Peláez Valdés <canek@ciencias.unam.mx>" }; Gtk.show_about_dialog( this, "authors", authors, "comments", _("A Gtk+ based music library maintainer"), "copyright", "Copyright © 2013-2018 Canek Peláez Valdés", "license-type", Gtk.License.GPL_3_0, "logo-icon-name", "mlm", "version", Config.PACKAGE_VERSION, "website", ("https://canek@aztlan.fciencias.unam.mx/" + "gitlab/canek/mlm.git"), "wrap-license", true); } /* Selects an image from a file. */ private uint8[]? select_image(string title) { var dialog = new Gtk.FileChooserDialog(title, this, Gtk.FileChooserAction.OPEN, _("_Cancel"), Gtk.ResponseType.CANCEL, _("_Open"), Gtk.ResponseType.ACCEPT); int r = dialog.run(); string fn = dialog.get_filename(); dialog.destroy(); if (r != Gtk.ResponseType.ACCEPT) return null; try { uint8[] data; FileUtils.get_data(fn, out data); return data; } catch (GLib.FileError fe) { warning(_("There was an error loading image '%s'").printf(fn)); } return null; } /* Sets a default image. */ private void set_default_image(Gtk.Image image) { if (image == cover_image) image.set_from_icon_name(ICON_NAME_CD, ICON_SIZE); Loading @@ -339,10 +516,12 @@ namespace MLM { image.pixel_size = 140; } private void update_image(Gtk.Image image, uint8[] data) { if (data == null) /* Updates an image. */ private void update_image(Gtk.Image image, uint8[] data) { if (data == null) { set_default_image(image); return; } var mis = new MemoryInputStream.from_data(data, null); Gdk.Pixbuf thumb = null; try { Loading @@ -353,53 +532,11 @@ namespace MLM { Gdk.InterpType.BILINEAR); } catch (GLib.Error e) { warning(_("Could not set pixbuf from data.")); set_default_image(image); return; } save_button.sensitive = true; image.set_from_pixbuf(thumb); } private bool dispose_player() { if (player == null || player.state == Gst.State.NULL) { player = new Player(filename); player.state_changed.connect(player_state_changed); return false; } return true; } private void define_genre(string g) { Gtk.TreeIter iter = {}; if (!genre_model.get_iter_first(out iter)) return; int c = 0; do { string ig; genre_model.get(iter, 0, out ig); if (g == ig) genre_combobox.active = c; c++; } while (genre_model.iter_next(ref iter)); } private void define_filename(string f) { _filename = f; var basename = GLib.Path.get_basename(_filename); var markup = GLib.Markup.printf_escaped("<b>%s</b>", basename); filename_widget.set_markup(markup); if (player != null) player.finish(); reset_timer(); GLib.Idle.add(dispose_player); } private void define_current(int c) { _current = c; header.set_subtitle("%d / %d".printf(_current, _last)); } private void define_last(int l) { _last = l; header.set_subtitle("%d / %d".printf(_current, _last)); } } }
src/application/application.vala +195 −117 File changed.Preview size limit exceeded, changes collapsed. Show changes