/* * Copyright (C) 2004-2005 Vadim Berezniker * http://www.kryptolus.com * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "common.h" #include "sabbu.h" #include "kryArray.h" #include "kryString.h" #include "krySSACommandParser.h" #include "krySSACommandHighlighter.h" #include "krySSAKaraokeParser.h" #include "stringutils.h" #include "gui_main_karaoke.h" #include "gui_text_editor.h" #include "gui_event_list.h" #include "kry_waveform_group.h" #include "gui_waveforms.h" #include "kry_region.h" extern struct sabbu app; kryEventKaraokeTime *gui_main_karaoke_create_empty_time_part(kryEventKaraokeText *event); kryEventKaraokeTextBox *gui_main_karaoke_add_part_before(char *text, gboolean after); KryMarker *marker_hidden_start; KryMarker *marker_hidden_end; KryMarker *marker_karaoke_start; KryMarker *marker_karaoke_end; KryRegionFixedList *karaoke_region_list; gboolean marker_karaoke_added; kryEventKaraokeTime *gui_main_karaoke_create_empty_time_part(kryEventKaraokeText *event) { kryEventKaraokeTime *event_time = new kryEventKaraokeTime(); event_time->SetParamOffset(0); event_time->SetParamLength(-1); event->SetDuration(-1); event->SetPartTime(event_time); event_time->SetEventText(event); return event_time; } void gui_main_karaoke_reflow(kryEventKaraokeTextBox *first_event) { if(!first_event) first_event = (kryEventKaraokeTextBox *) app.ui.karaoke_start; GtkRequisition req; int pos_x = 0, pos_y = 0; int max_row_height = 0; if(first_event->GetEventPrev() && first_event->GetEventPrev()->GetEventPrev()) { int x, y, width; x = first_event->GetEventPrev()->GetEventPrev()->GetX(); y = first_event->GetEventPrev()->GetEventPrev()->GetY(); width = ((kryEventKaraokeTextBox *) first_event->GetEventPrev()->GetEventPrev())->GetWidth(); pos_x = x + width; pos_y = y; } for(kryEventKaraokeTextBox *event = first_event; event; event = event->GetEventNext()) { if(event->GetIsSilence()) { //gtk_layout_move(app.ui.karaoke_container, event->GetBox(), -1000, -1000); continue; } gtk_widget_size_request(event->GetBox(), &req); if(req.height > max_row_height) max_row_height = req.height; if(pos_x + req.width + 4> GTK_WIDGET(app.ui.karaoke_container)->allocation.width) { pos_x = 0; pos_y += max_row_height; max_row_height = 0; } event->SetX(pos_x); event->SetY(pos_y); event->SetWidth(req.width); event->SetHeight(req.height); gtk_layout_move(app.ui.karaoke_container, event->GetBox(), pos_x, pos_y); pos_x += req.width; } } void gui_karaoke_grab_times_cb(GtkWidget *widget, gpointer param) { kryEventKaraokeText *event = app.ui.karaoke_selection; if(event->GetIsTimed()) { kry_region_fixed_list_remove(karaoke_region_list, kry_marker_get_value(event->GetMarkerStart()), kry_marker_get_value(event->GetMarkerEnd())); } kry_marker_set_value(event->GetMarkerStart(), kry_marker_get_value(app.ui.marker_active_start)); kry_marker_set_value(event->GetMarkerEnd(), kry_marker_get_value(app.ui.marker_active_end)); event->SetIsTimed(TRUE); kry_region_fixed_list_add(karaoke_region_list, kry_marker_get_value(event->GetMarkerStart()), kry_marker_get_value(event->GetMarkerEnd())); gui_main_grab_times_cb(NULL, TRUE); gui_main_set_time_modified(FALSE); } void gui_karaoke_set_selected_event(kryEvent *event_generic) { kryListIterator iter; /* if(app.ui.karaoke_selection) { kryEventKaraokeText *event = app.ui.karaoke_selection; if(event->GetEventPrev()) { kry_waveform_group_marker_show(app.ui.waveform_group, event->GetEventPrev()->GetMarkerEnd()); if(event->GetEventPrev()->GetIsLocked()) { kry_waveform_group_marker_show(app.ui.waveform_group, event->GetEventPrev()->GetMarkerStart()); if(event->GetEventPrev()->GetEventPrev()) kry_waveform_group_marker_show(app.ui.waveform_group, event->GetEventPrev()->GetEventPrev()->GetMarkerEnd()); } } if(event->GetEventNext() && event->GetEventNext()->GetIsSilence()) { if(event->GetEventNext()->GetIsLocked()) { kry_waveform_group_marker_show(app.ui.waveform_group, event->GetEventNext()->GetMarkerEnd()); kry_waveform_group_marker_show(app.ui.waveform_group, event->GetEventNext()->GetEventNext()->GetMarkerStart()); } kry_waveform_group_marker_show(app.ui.waveform_group, event->GetEventNext()->GetMarkerStart()); } }*/ if(app.ui.karaoke_mode == KARAOKE_MODE_LINE) { gboolean diff_row = FALSE; GtkTreeModel *model; GtkTreeSelection *selection = gui_event_list_get_selection(app.ui.event_list); GList *selected = gtk_tree_selection_get_selected_rows(selection, &model); GtkTreeIter iter; kryEvent *selected_event; gtk_tree_model_get_iter(model, &iter, (GtkTreePath *) selected->data); gtk_tree_model_get(model, &iter, PTR_COLUMN, &selected_event, -1); if(selected_event != event_generic) diff_row = TRUE; g_list_foreach(selected, (GFunc) gtk_tree_path_free, NULL); g_list_free(selected); if(diff_row) { char *path = kry_strdup_printf(KRY_LOC "%d", event_generic->GetIndex()); GtkTreePath *treepath = gtk_tree_path_new_from_string(path); gtk_tree_model_get_iter(model, &iter, treepath); gtk_tree_selection_select_iter(selection, &iter); gtk_tree_path_free(treepath); kry_free(path); return; } } kryEventKaraokeTextBox *event = (kryEventKaraokeTextBox *) event_generic; char *text; char *new_text; //kry_waveform_group_region_remove_by_type(app.ui.waveform_group, WAVEFORM_COLOR_SELECTION_HIGHLIGHT); if(app.ui.karaoke_mode == KARAOKE_MODE_BOX && app.ui.karaoke_selection) { GtkLabel *label = ((kryEventKaraokeTextBox *) app.ui.karaoke_selection)->GetLabel(); text = (char *) gtk_label_get_text(label); new_text = kry_strdup_printf(KRY_LOC "%s", text); gtk_label_set_markup(label, new_text); kry_free(new_text); } app.ui.karaoke_selection = event; if(app.ui.time_modified) return; if(marker_hidden_start) { kry_waveform_group_marker_show(app.ui.waveform_group, marker_hidden_start); marker_hidden_start = NULL; } if(marker_hidden_end) { kry_waveform_group_marker_show(app.ui.waveform_group, marker_hidden_end); marker_hidden_end = NULL; } if(event->GetIsTimed()) { marker_hidden_start = event->GetMarkerStart(); marker_hidden_end = event->GetMarkerEnd(); kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetMarkerStart()); kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetMarkerEnd()); kry_marker_set_value(marker_karaoke_start, kry_marker_get_value(event->GetMarkerStart())); kry_marker_set_value(marker_karaoke_end, kry_marker_get_value(event->GetMarkerEnd())); gui_main_set_time_modified(FALSE); } return; if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) { GtkLabel *label = event->GetLabel(); text = (char *) gtk_label_get_text(label); new_text = kry_strdup_printf(KRY_LOC "%s", text); gtk_label_set_markup(label, new_text); kry_free(new_text); } app.ui.marker_active_start = event->GetMarkerStart(); app.ui.marker_active_end = event->GetMarkerEnd(); /*if(event->GetEventPrev()) { kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetEventPrev()->GetMarkerEnd()); if(event->GetEventPrev()->GetIsLocked()) { kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetEventPrev()->GetMarkerStart()); if(event->GetEventPrev()->GetEventPrev()) kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetEventPrev()->GetEventPrev()->GetMarkerEnd()); } } if(event->GetEventNext() && event->GetEventNext()->GetIsSilence()) { if(event->GetEventNext()->GetIsLocked()) { kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetEventNext()->GetMarkerEnd()); kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetEventNext()->GetEventNext()->GetMarkerStart()); } kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetEventNext()->GetMarkerStart()); }*/ gui_combo_box_set_text(app.ui.karaoke_type_combo, gui_main_karaoke_get_type_string(event)); g_signal_emit_by_name(event->GetMarkerStart(), "value-changed", kry_marker_get_value(event->GetMarkerStart())); g_signal_emit_by_name(event->GetMarkerEnd(), "value-changed", kry_marker_get_value(event->GetMarkerEnd())); } void gui_main_karaoke_part_clicked_cb(GtkEventBox *box, GdkEventButton *gdkevent, kryEventKaraokeText *event) { gui_karaoke_set_selected_event(event); } void gui_main_karaoke_type_changed_cb(GtkComboBox *combo, gpointer data) { if(!app.ui.karaoke_selection) return; app.ui.karaoke_selection->SetKaraokeType(gui_main_karaoke_get_type(KRY_TS(gtk_combo_box_get_active_text((combo))))); } void gui_main_karaoke_marker_changed_cb(KryMarker *marker, long position_old, kryEventKaraokeTextBox *event) { if(kry_marker_get_value(marker) == -1 || !app.ui.karaoke_parts) return; /*if(event->GetEventNext() && marker == event->GetMarkerEnd()) kry_marker_set_value(event->GetEventNext()->GetMarkerStart(), kry_marker_get_value(marker)); if(event->GetEventPrev() && marker == event->GetMarkerStart()) kry_marker_set_value(event->GetEventPrev()->GetMarkerEnd(), kry_marker_get_value(marker)); if(marker == event->GetMarkerEnd() && event->GetEventNext() && event->GetEventNext()->GetIsSilence() && event->GetEventNext()->GetIsLocked()) kry_marker_set_value(event->GetEventNext()->GetMarkerEnd(), kry_marker_get_value(marker)); if(marker == event->GetMarkerStart() && event->GetEventPrev() && event->GetEventPrev()->GetIsSilence()) { if(kry_marker_get_value(event->GetEventPrev()->GetMarkerStart()) != kry_marker_get_value(event->GetEventPrev()->GetMarkerEnd())) { //g_warning("unlocked %s", event->GetText()); event->GetEventPrev()->SetIsLocked(FALSE); if(event->GetEventPrev()->GetEventPrev()) kry_waveform_group_marker_show(app.ui.waveform_group, event->GetEventPrev()->GetEventPrev()->GetMarkerEnd()); kry_waveform_group_marker_show(app.ui.waveform_group, event->GetEventPrev()->GetMarkerStart()); } else if(!event->GetEventPrev()->GetIsLocked()) { //g_warning("hiding %s", event->GetText()); event->GetEventPrev()->SetIsLocked(TRUE); if(event->GetEventPrev()->GetEventPrev()) kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetEventPrev()->GetEventPrev()->GetMarkerEnd()); kry_waveform_group_marker_hide(app.ui.waveform_group, event->GetEventPrev()->GetMarkerStart()); } } if(kry_marker_get_value(event->GetMarkerStart()) > kry_marker_get_value(event->GetMarkerEnd())) kry_marker_set_value(event->GetMarkerEnd(), kry_marker_get_value(event->GetMarkerStart()));*/ event->SetDuration((kry_marker_get_value(event->GetMarkerEnd()) - kry_marker_get_value(event->GetMarkerStart()))); /*if(app.ui.karaoke_mode == KARAOKE_MODE_LINE && !event->GetIsSilence()) gui_event_list_update_line(app.ui.event_list, event); if(event == event_first && marker == event->GetMarkerStart()) kry_marker_set_value(app.ui.marker_event_start, kry_marker_get_value(event->GetMarkerStart())); else if(event == event_last && marker == event->GetMarkerEnd()) kry_marker_set_value(app.ui.marker_event_end, kry_marker_get_value(event->GetMarkerEnd()));*/ } kryEventKaraokeTextBox *gui_main_karaoke_add_silence_before(kryList *list, kryEventKaraokeText *sibling) { kryEventKaraokeText *event = sibling; kryEventKaraokeTextBox *new_event = new kryEventKaraokeTextBox(); new_event->SetText((char *) ""); new_event->SetEventNext(event); new_event->SetEventPrev(event->GetEventPrev()); new_event->SetIsSilence(TRUE); new_event->SetIsLocked(TRUE); kryEvent *event_command = event->GetCommandPrev(); if(!event_command) event_command = event->GetPartTime(); int index = list->IndexOf(event_command); list->Insert(new_event, index); if(new_event->GetEventNext()) new_event->GetEventNext()->SetEventPrev(new_event); if(new_event->GetEventPrev()) new_event->GetEventPrev()->SetEventNext(new_event); kryEventKaraokeTime *event_time = gui_main_karaoke_create_empty_time_part(new_event); index = list->IndexOf(new_event); list->Insert(event_time, index); if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) { //GtkWidget *box = ((kryEventKaraokeTextBox *) new_event)->GetBox(); //gtk_layout_put(app.ui.karaoke_container, box, box->allocation.x, box->allocation.y); } return new_event; } void gui_main_karaoke_region_selected_cb(KryRegion *region, kryEventKaraokeText *event) { if(event->GetIsSilence()) return; gui_karaoke_set_selected_event(event); } void gui_main_karaoke_event_init(kryEventKaraokeText *event) { event->CreateUI(); g_signal_connect(event->GetMarkerStart(), "value-changed", G_CALLBACK(gui_main_marker_changed_cb), event); g_signal_connect(event->GetMarkerStart(), "value-changed", G_CALLBACK(gui_main_karaoke_marker_changed_cb), event); g_signal_connect(event->GetMarkerEnd(), "value-changed", G_CALLBACK(gui_main_marker_changed_cb), event); g_signal_connect(event->GetMarkerEnd(), "value-changed", G_CALLBACK(gui_main_karaoke_marker_changed_cb), event); if(app.ui.karaoke_selection == event) { app.ui.marker_active_start = event->GetMarkerStart(); app.ui.marker_active_end = event->GetMarkerEnd(); } if(event->GetDuration() != -1) { kry_waveform_group_marker_add(app.ui.waveform_group, event->GetMarkerStart()); kry_waveform_group_marker_add(app.ui.waveform_group, event->GetMarkerEnd()); KryRegion *region = KRY_REGION(kry_region_new(event->GetMarkerStart(), event->GetMarkerEnd(), event->GetIsSilence() ? WAVEFORM_COLOR_SILENCE_HIGHLIGHT : -1)); g_signal_connect(region, "selected", G_CALLBACK(gui_main_karaoke_region_selected_cb), event); kry_waveform_group_region_add(app.ui.waveform_group, region); g_object_unref(G_OBJECT(region)); } } void gui_main_karaoke_print_list() { g_warning("print list"); for(kryEventKaraokeText *part = app.ui.karaoke_start; part; part = part->GetEventNext()) { g_warning("Part: '%10s' (Prev '%10s') [%d]", part->GetText(), part->GetEventPrev() ? part->GetEventPrev()->GetText() : "NULL", part->GetIndex()); } g_warning("done"); } kryEventKaraokeTextBox *gui_main_karaoke_add_part_before_real(kryList *list, kryEventKaraokeText *sibling, char *text, gboolean after) { kryEventKaraokeText *event = sibling; kryEventKaraokeTextBox *new_event = new kryEventKaraokeTextBox(); kryEventKaraokeText *event_silence = event->GetEventPrev(); GtkTreeIter iter; if(app.ui.karaoke_mode == KARAOKE_MODE_LINE) gui_main_karaoke_line_add(after, &iter); if(event_silence) event_silence->GetEventNext()->SetEventPrev(NULL); new_event->SetText(text); new_event->SetEventPrev(event_silence); if(event_silence) new_event->GetEventPrev()->SetEventNext(new_event); event_silence = gui_main_karaoke_add_silence_before(app.ui.karaoke_parts, event); gui_main_karaoke_event_init(event_silence); event_silence->SetEventPrev(new_event); new_event->SetEventNext(event_silence); int index = list->IndexOf(event_silence->GetPartTime()); list->Insert(new_event, index); if(!new_event->GetEventPrev()) app.ui.karaoke_start = new_event; gui_main_karaoke_event_init(new_event); kryEventKaraokeTime *event_time = gui_main_karaoke_create_empty_time_part(new_event); index = list->IndexOf(new_event); list->Insert(event_time, index); if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) { GtkWidget *box = ((kryEventKaraokeTextBox *) new_event)->GetBox(); gtk_layout_put(app.ui.karaoke_container, box, box->allocation.x, box->allocation.y); gtk_widget_show_all(new_event->GetBox()); } else if(app.ui.karaoke_mode == KARAOKE_MODE_LINE) { gui_event_list_update_line(app.ui.event_list, new_event, &iter); } return new_event; } kryEventKaraokeTextBox *gui_main_karaoke_add_part_before(char *text, gboolean after) { return gui_main_karaoke_add_part_before_real(app.ui.karaoke_parts, app.ui.karaoke_selection, text, after); } void gui_main_karaoke_line_add(gboolean after, GtkTreeIter *iter_new) { GtkTreeModel *model; GtkTreeSelection *selection = gui_event_list_get_selection(app.ui.event_list); GList *sel = gtk_tree_selection_get_selected_rows(selection, &model); GtkTreePath *path = (GtkTreePath *) sel->data; GtkTreeIter iter; gtk_tree_model_get_iter(model, &iter, path); if(after) gtk_list_store_insert_after(GTK_LIST_STORE(model), iter_new, &iter); else gtk_list_store_insert_before(GTK_LIST_STORE(model), iter_new, &iter); g_list_foreach (sel, (GFunc) gtk_tree_path_free, NULL); g_list_free(sel); } gboolean gui_main_karaoke_split_entry_cb(GtkWidget *widget, GdkEventKey *event, GtkDialog *dialog) { if(event->keyval == GDK_Return) gtk_dialog_response(dialog, GTK_RESPONSE_OK); return FALSE; } void gui_main_karaoke_split_word_real(GList *words) { kryEventKaraokeText *event = app.ui.karaoke_selection; kryEventKaraokeText *first_event = NULL; GList *parts = NULL; int start = kry_marker_get_value(event->GetMarkerStart()); int end = kry_marker_get_value(event->GetMarkerEnd()); int length_mili = end - start; int time_offset = start; int length = 0; for(GList *ptr = words; ptr; ptr = ptr->next) length += strlen((char *) ptr->data); // g_warning("before"); // for(kryEventKaraokeText *event = app.ui.karaoke_start; event; event = event->GetEventNext()) // { //g_warning("event: %s (prev %s)", event->GetText(), event->GetEventPrev() ? event->GetEventPrev()->GetText() : "NONE"); //} int last_index = event->GetIndex(); for(GList *ptr = words; ptr; ptr = ptr->next) { kryEventKaraokeText *cur_event = event; char *text = (char *) ptr->data; if(ptr->next) { cur_event = gui_main_karaoke_add_part_before(text, FALSE); cur_event->SetIndex(last_index); last_index++; } else { cur_event->SetText(text); cur_event->SetIsSilence(FALSE); cur_event->SetIndex(last_index); for(kryEventKaraokeText *part = cur_event->GetEventNext(); part; part = part->GetEventNext()) { if(part->GetIsSilence()) continue; part->SetIndex(++last_index); } if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) { char *new_text = kry_strdup_printf(KRY_LOC "%s", text); gtk_label_set_markup(((kryEventKaraokeTextBox *) cur_event)->GetLabel(), new_text); } else { gui_event_list_update_line(app.ui.event_list, cur_event); gui_text_editor_set_text(app.ui.text_editor, cur_event->GetText()); } } if(!first_event) first_event = cur_event; parts = g_list_append(parts, cur_event); } /* g_warning("after"); for(kryEventKaraokeText *event = app.ui.karaoke_start; event; event = event->GetEventNext()) { g_warning("event: %s (prev %s)", event->GetText(), event->GetEventPrev() ? event->GetEventPrev()->GetText() : "NONE"); }*/ for(GList *ptr = parts; ptr; ptr = ptr->next) { kryEventKaraokeTextBox *event = (kryEventKaraokeTextBox *) ptr->data; int duration; if(ptr->next) duration = (strlen(event->GetText()) * length_mili) / length; else duration = end - time_offset; if(duration % 10 != 0) duration -= duration % 10; kry_marker_set_value(event->GetMarkerStart(), time_offset); kry_marker_set_value(event->GetMarkerEnd(), time_offset + duration); if(ptr->next && event->GetEventPrev() && event->GetEventPrev()->GetIsLocked()) { kryEventKaraokeText *silence = event->GetEventPrev(); kry_marker_set_value(silence->GetMarkerStart(), time_offset); kry_marker_set_value(silence->GetMarkerEnd(), time_offset); } time_offset += duration; } if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) gui_main_karaoke_reflow((kryEventKaraokeTextBox *) first_event); gui_karaoke_set_selected_event(app.ui.karaoke_selection); g_list_free(parts); } void gui_main_karaoke_split_word(char *text) { kryString str(text); int prev_pos = 0; GList *words = NULL; for(int i = 0; i <= str.GetLength(); i++) { if(i == str.GetLength() || str[i] == ' ') { char *word = kry_strdup(str.Mid(prev_pos, i - prev_pos).GetBuffer()); words = g_list_append(words, word); while(str[i] == ' ' && i < str.GetLength()) i++; prev_pos = i; if(i < str.GetLength()) i--; } } gui_main_karaoke_split_word_real(words); g_list_foreach(words, (GFunc) kry_free_minimal, NULL); g_list_free(words); } void gui_main_karaoke_split_word_cb(GtkWidget *widget, gpointer data) { kryEventKaraokeText *event = app.ui.karaoke_selection; GtkLabel *label = GTK_LABEL(gtk_label_new(_("Separate the text into multiple parts by adding spaces between the characters you want to split"))); GtkDialog *dialog = GTK_DIALOG(gtk_dialog_new_with_buttons(__("Karaoke|Split Karaoke Part"), app.ui.window, GTK_DIALOG_MODAL, GTK_STOCK_OK, 1, NULL)); GtkEntry *entry = GTK_ENTRY(gtk_entry_new()); char *text; gtk_entry_set_text(entry, event->GetText()); g_signal_connect(G_OBJECT(entry), "key-press-event", G_CALLBACK(gui_main_karaoke_split_entry_cb), dialog); gtk_box_pack_start(GTK_BOX(dialog->vbox), GTK_WIDGET(label), FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(dialog->vbox), GTK_WIDGET(entry), FALSE, TRUE, 0); gtk_widget_show_all(GTK_WIDGET(dialog)); gui_main_disable(); gtk_dialog_run(dialog); text = kry_strdup(string_ignore_whitespce((char *) gtk_entry_get_text(entry))); gui_main_karaoke_split_word(text); gui_main_enable(); gui_main_focus(); gtk_widget_destroy(GTK_WIDGET(dialog)); } void gui_main_karaoke_fill_list() { gboolean line_mode = (app.ui.karaoke_mode == KARAOKE_MODE_LINE); kryList *parts = new kryList(); char *text = gui_text_editor_get_text(app.ui.text_editor); long start = kry_marker_get_value(app.ui.marker_event_start); long end = kry_marker_get_value(app.ui.marker_event_end); long time_offset = start; int total_duration; total_duration = end - start; kry_waveform_group_disable_draw(app.ui.waveform_group); kry_waveform_group_marker_remove_all(app.ui.waveform_group); kry_waveform_group_marker_add(app.ui.waveform_group, app.ui.marker_current); kry_waveform_group_region_remove_all(app.ui.waveform_group); marker_karaoke_start = KRY_MARKER(kry_marker_new(MARKER_KARAOKE, 10)); marker_karaoke_end = KRY_MARKER(kry_marker_new(MARKER_KARAOKE, 10)); marker_hidden_start = NULL; marker_hidden_end = NULL; kry_waveform_group_marker_add(app.ui.waveform_group, marker_karaoke_start); kry_waveform_group_marker_add(app.ui.waveform_group, marker_karaoke_end); kry_waveform_group_marker_set_active_start(app.ui.waveform_group, marker_karaoke_start); kry_waveform_group_marker_set_active_end(app.ui.waveform_group, marker_karaoke_end); app.ui.marker_active_start = marker_karaoke_start; app.ui.marker_active_end = marker_karaoke_end; g_signal_connect(marker_karaoke_start, "value-changed", G_CALLBACK(gui_main_marker_changed_cb), NULL); g_signal_connect(marker_karaoke_end, "value-changed", G_CALLBACK(gui_main_marker_changed_cb), NULL); kry_waveform_group_region_add_new(app.ui.waveform_group, marker_karaoke_start, marker_karaoke_end, WAVEFORM_COLOR_SELECTION_HIGHLIGHT); kryEventKaraokeText *event_start = NULL, *event_end = NULL; krySSAKaraokeParser parser(text, parts, &event_start, &event_end); kry_free(text); for(kryEventKaraokeText *event = event_start; event; event = event->GetEventNext()) { if(event->GetEventPrev() && !event->GetIsSilence() && !event->GetEventPrev()->GetIsSilence()) gui_main_karaoke_add_silence_before(parts, event); } for(kryEventKaraokeText *event = event_start; event; event = event->GetEventNext()) { /*if(event->GetDuration() == -1) num_chars += strlen(event->GetText()); else total_duration -= event->GetDuration();*/ gui_main_karaoke_event_init(event); //if(!event->GetPartTime()) //{ // kryEventKaraokeTime *time = gui_main_karaoke_create_empty_time_part(event); // int index = parts->IndexOf(event); // parts->Insert(time, index); //} } // calculate the duration of the parts and create the UI for each part for(kryEventKaraokeText *event = event_start; event; event = event->GetEventNext()) { int duration; /*if(event->GetDuration() == -1) { if(event->GetEventNext()) event->SetDuration((int) ((strlen(event->GetText()) / (double) num_chars) * total_duration)); else event->SetDuration(end - time_offset); if(event->GetDuration() % 10 != 0) event->SetDuration(event->GetDuration() - event->GetDuration() % 10); }*/ if(event->GetDuration() != -1) event->SetIsTimed(TRUE); duration = event->GetDuration(); if(!line_mode && !event->GetIsSilence()) { gtk_layout_put(app.ui.karaoke_container, ((kryEventKaraokeTextBox *) event)->GetBox(), -1000, -1000); } kry_marker_set_value(event->GetMarkerStart(), time_offset); kry_marker_set_value(event->GetMarkerEnd(), time_offset + duration); if(event->GetDuration() != -1) time_offset += event->GetDuration(); } kry_waveform_group_enable_draw(app.ui.waveform_group); app.ui.karaoke_parts = parts; app.ui.karaoke_start = event_start; app.ui.karaoke_end = event_end; app.ui.karaoke_mode = (line_mode ? KARAOKE_MODE_LINE : KARAOKE_MODE_BOX); if(line_mode) { gui_event_list_fill_from_list_karaoke(app.ui.event_list, app.ui.karaoke_parts); } else { if(event_start->GetIsSilence()) gui_karaoke_set_selected_event(event_start->GetEventNext()); else gui_karaoke_set_selected_event(event_start); gtk_widget_show_all(GTK_WIDGET(app.ui.karaoke_container)); gui_main_karaoke_reflow(NULL); } gui_main_focus_on_wave(); } void gui_main_karaoke_mode_on(gpointer callback_data, guint callback_action, GtkWidget *menu_item) { kryEvent *event = NULL; GtkTreeModel *model; GtkTreeSelection *selection = gui_event_list_get_selection(app.ui.event_list); GList *sel_items = gtk_tree_selection_get_selected_rows(selection, &model); if(sel_items) { GtkTreeIter iter; GtkTreePath *path = (GtkTreePath *) sel_items->data; gtk_tree_model_get_iter(model, &iter, path); gtk_tree_model_get(model, &iter, PTR_COLUMN, &event, -1); } g_list_foreach(sel_items, (GFunc) gtk_tree_path_free, NULL); g_list_free(sel_items); long start = kry_marker_get_value(app.ui.marker_event_start); long end = kry_marker_get_value(app.ui.marker_event_end); if(start == -1 || end == -1 || !app.ui.sound_info || !event || event->GetType() != kryEvent::EVENT_DIALOG) return; marker_karaoke_added = FALSE; app.ui.karaoke_parent_event = event; karaoke_region_list = KRY_REGION_FIXED_LIST(kry_region_fixed_list_new()); kry_waveform_group_region_fixed_list_set(app.ui.waveform_group, karaoke_region_list); char *text = gui_text_editor_get_text(app.ui.text_editor); if(!strcmp(string_ignore_whitespce(text), "")) { kry_free(text); return; } kry_free(text); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.event.me), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.sync.me), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.grab_times), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.play_from_start_marker), FALSE); //gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.play_previous_row), FALSE); //gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.play_current_row), FALSE); //gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.play_next_row), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.advance_selection), FALSE); gtk_widget_hide(GTK_WIDGET(app.ui.karaoke_vbox_switch)); gtk_widget_show_all(GTK_WIDGET(app.ui.karaoke_vbox_toolbar)); // box mode if(callback_action == 0) { app.ui.karaoke_mode = KARAOKE_MODE_BOX; gtk_widget_hide(gui_text_editor_get_widget(app.ui.text_editor)); gtk_widget_show_all(GTK_WIDGET(app.ui.hbox_karaoke)); gtk_widget_show(app.ui.karaoke_toolbar_split); while(gtk_events_pending()) gtk_main_iteration(); } else { app.ui.karaoke_mode = KARAOKE_MODE_LINE; gtk_widget_hide(app.ui.karaoke_toolbar_split); gtk_widget_hide(gui_text_editor_get_syntax_highlight_controls(app.ui.text_editor)); gui_main_set_ui_mode(UI_MODE_KARAOKE); } gui_main_karaoke_fill_list(); gui_event_list_disable_selection_event(app.ui.event_list); gtk_tree_selection_set_mode(gui_event_list_get_selection(app.ui.event_list), GTK_SELECTION_BROWSE); gui_event_list_enable_selection_event(app.ui.event_list); gui_main_karaoke_enable_menus(); gui_main_focus_on_wave(); } void gui_karaoke_events_empty() { GList *ptr = gtk_container_get_children(GTK_CONTAINER(app.ui.karaoke_container)); for(; ptr; ptr = ptr->next) gtk_container_remove(GTK_CONTAINER(app.ui.karaoke_container), GTK_WIDGET(ptr->data)); kryListIterator iter; kry_waveform_group_marker_remove_all(app.ui.waveform_group); kry_waveform_group_region_remove_all(app.ui.waveform_group); kry_waveform_group_marker_add(app.ui.waveform_group, app.ui.marker_current); kryListIterator iter_event; app.ui.karaoke_parts->GetIterator(&iter_event); while(kryEvent *event_general = iter_event.GetNext()) { if(event_general->GetType() != kryEvent::EVENT_KARAOKE_TEXT) continue; kryEventKaraokeText *event = (kryEventKaraokeText *) event_general; delete event; } delete app.ui.karaoke_parts; app.ui.karaoke_parent_event = NULL; app.ui.karaoke_selection = NULL; app.ui.karaoke_parts = NULL; app.ui.karaoke_start = NULL; app.ui.karaoke_end = NULL; app.ui.marker_active_start = app.ui.marker_event_start; app.ui.marker_active_end = app.ui.marker_event_end; } void gui_main_karaoke_off() { GtkTreeIter iter_sel; gboolean line_mode = (app.ui.karaoke_mode == KARAOKE_MODE_LINE); if(line_mode) { gui_event_list_fill_from_list_detailed(app.ui.event_list, &app.script->GetEventList()); char *pathstr = kry_strdup_printf(KRY_LOC "%d", app.ui.karaoke_parent_event->GetIndex()); GtkTreePath *path = gtk_tree_path_new_from_string(pathstr); gtk_tree_model_get_iter(GTK_TREE_MODEL(gui_event_list_get_store(app.ui.event_list)), &iter_sel, path); gtk_tree_path_free(path); kry_free(pathstr); } gui_karaoke_events_empty(); app.ui.karaoke_mode = KARAOKE_MODE_OFF; if(line_mode) { char *text = gui_text_editor_get_text(app.ui.text_editor); GtkTreeSelection *selection = gui_event_list_get_selection(app.ui.event_list); gtk_tree_selection_select_iter(selection, &iter_sel); gui_text_editor_set_text(app.ui.text_editor, text); kry_free(text); } gtk_widget_hide(GTK_WIDGET(app.ui.hbox_karaoke)); gtk_widget_show_all(gui_text_editor_get_widget(app.ui.text_editor)); app.ui.marker_active_start = app.ui.marker_event_start; app.ui.marker_active_end = app.ui.marker_event_end; kry_waveform_group_marker_add(app.ui.waveform_group, app.ui.marker_event_start); kry_waveform_group_marker_add(app.ui.waveform_group, app.ui.marker_event_end); kry_waveform_group_region_add_new(app.ui.waveform_group, app.ui.marker_event_start, app.ui.marker_event_end, WAVEFORM_COLOR_SELECTION_HIGHLIGHT); kry_waveform_group_marker_set_active_start(app.ui.waveform_group, app.ui.marker_event_start); kry_waveform_group_marker_set_active_end(app.ui.waveform_group, app.ui.marker_event_end); g_signal_emit_by_name(app.ui.marker_event_start, "value-changed", kry_marker_get_value(app.ui.marker_event_start)); g_signal_emit_by_name(app.ui.marker_event_end, "value-changed", kry_marker_get_value(app.ui.marker_event_end)); if(line_mode) gui_main_set_ui_mode(app.script->GetType() == KRY_FORMAT_SSA ? UI_MODE_SSA : UI_MODE_ASS); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.event.me), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.sync.me), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.grab_times), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.play_from_start_marker), TRUE); //gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.play_previous_row), TRUE); //gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.play_current_row), TRUE); //gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.play_next_row), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.audio.advance_selection), TRUE); gtk_widget_show(GTK_WIDGET(gui_text_editor_get_syntax_highlight_controls(app.ui.text_editor))); gtk_widget_show(GTK_WIDGET(app.ui.karaoke_vbox_switch)); gtk_widget_hide(GTK_WIDGET(app.ui.karaoke_vbox_toolbar)); gui_main_karaoke_disable_menus(); gtk_tree_selection_set_mode(gui_event_list_get_selection(app.ui.event_list), GTK_SELECTION_MULTIPLE); } char *gui_main_karaoke_get_type_string(kryEventKaraokeText *event) { if(event->GetKaraokeType() == KARAOKE_HIGHLIGHT) return "\\k"; else if(event->GetKaraokeType() == KARAOKE_FILL_K) return "\\K"; else if(event->GetKaraokeType() == KARAOKE_FILL_KF) return "\\kf"; else if(event->GetKaraokeType() == KARAOKE_OUTLINE) return "\\ko"; return "\\k"; } enum karaoke_type gui_main_karaoke_get_type(char *str) { if(!strcmp(str, "k") || !strcmp(str, "\\k")) return KARAOKE_HIGHLIGHT; else if(!strcmp(str, "kf") || !strcmp(str, "\\kf")) return KARAOKE_FILL_KF; else if(!strcmp(str, "K") || !strcmp(str, "\\K")) return KARAOKE_FILL_K; else if(!strcmp(str, "ko") || !strcmp(str, "\\ko")) return KARAOKE_OUTLINE; return KARAOKE_HIGHLIGHT; } void gui_main_karaoke_mode_off_cb(GtkWidget *widget, gboolean exit_karaoke) { //char *text = gui_main_text_get_text(); int length = 0; GList *reconstruct = NULL; char *new_str; int i = 0; kryListIterator iter; app.ui.karaoke_parts->GetIterator(&iter); // reconstructive surgery while(kryEvent *event_general = iter.GetNext()) { if(event_general->GetType() != kryEvent::EVENT_KARAOKE_TIME) { reconstruct = g_list_append(reconstruct, kry_strdup(event_general->GetText())); length += strlen(event_general->GetText()); continue; } kryEventKaraokeTime *event = (kryEventKaraokeTime *) event_general; if(event->GetEventText()->GetIsSilence() && event->GetEventText()->GetDuration() == 0 && event->GetParamLength() == -1) continue; char *type_str = gui_main_karaoke_get_type_string(event->GetEventText()); char *str; if(event->GetParamLength() == -1) { str = kry_strdup_printf(KRY_LOC "{%s%d}", type_str, event->GetEventText()->GetDuration() / 10); } else { kryString strObj(event->GetText()); char *str_before = kry_strdup(strObj.Mid(0, event->GetParamOffset()).GetBuffer()); str = kry_strdup_printf(KRY_LOC "%s%d", type_str, event->GetEventText()->GetDuration() / 10); char *str_after = kry_strdup(strObj.Mid(event->GetParamOffset() + event->GetParamLength()).GetBuffer()); char *str_final = kry_strdup_printf(KRY_LOC "%s%s%s", str_before, str, str_after); event->SetText(str_final); event->SetParamLength(strlen(str)); kry_free(str_before); kry_free(str); kry_free(str_after); str = kry_strdup(str_final); } length += strlen(str); reconstruct = g_list_append(reconstruct, str); } new_str = (char *) kry_malloc(length + 1); for(GList *ptr = reconstruct; ptr; ptr = ptr->next) { strcpy(new_str + i, (const char *) ptr->data); i += strlen((const char *) ptr->data); kry_free(ptr->data); } new_str[i] = 0; if(exit_karaoke) { gui_text_editor_set_text(app.ui.text_editor, new_str); gui_main_karaoke_off(); gui_main_focus_on_wave(); return; } if(app.ui.karaoke_mode != KARAOKE_MODE_OFF) { kryEvent *event = NULL; if(app.ui.karaoke_mode == KARAOKE_MODE_LINE) { event = app.ui.karaoke_parent_event; GtkTreeIter iter; gui_main_event_select(1, &iter, FALSE, FALSE); } else if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) { GtkTreeModel *model; GtkTreeSelection *selection = gui_event_list_get_selection(app.ui.event_list); GList *selected = gtk_tree_selection_get_selected_rows(selection, &model); if(!selected) return; GtkTreeIter treeiter; GtkTreePath *path = (GtkTreePath *) selected->data; gtk_tree_model_get_iter(model, &treeiter, path); gtk_tree_model_get(model, &treeiter, PTR_COLUMN, &event, -1); kryEventKaraokeText *event_next = app.ui.karaoke_selection->GetEventNext(); if(event_next && event_next->GetIsSilence()) event_next = event_next->GetEventNext(); if(event_next) gui_karaoke_set_selected_event(event_next); g_list_foreach(selected, (GFunc) gtk_tree_path_free, NULL); g_list_free(selected); } if(strcmp(event->GetText(), new_str)) app.script->SetModifiedFlag(TRUE); event->SetText(new_str); event->SetTime(kry_marker_get_value(app.ui.marker_event_start), kry_marker_get_value(app.ui.marker_event_end)); if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) gui_event_list_update_line(app.ui.event_list, event); } kry_free(new_str); //kry_free(text); } void gui_main_karaoke_disable_menus() { /*gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.box_mode), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.script_mode), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.save_changes), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.turn_off), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.split_part), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.previous_part), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.next_part), FALSE);*/ } void gui_main_karaoke_enable_menus() { /*gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.box_mode), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.script_mode), FALSE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.save_changes), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.turn_off), TRUE); if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.split_part), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.previous_part), TRUE); gtk_widget_set_sensitive(GTK_WIDGET(app.ui.menu.karaoke.next_part), TRUE);*/ } void gui_main_karaoke_prev_part_cb(gpointer callback_data, guint callback_action, GtkWidget *menu_item) { if(!app.ui.karaoke_selection->GetEventPrev()) return; if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) { gui_main_karaoke_part_clicked_cb(NULL, NULL, app.ui.karaoke_selection->GetEventPrev()); } else { GtkTreeIter iter; gui_main_event_select(-1, &iter, FALSE, FALSE); } } void gui_main_karaoke_next_part_cb(gpointer callback_data, guint callback_action, GtkWidget *menu_item) { if(!app.ui.karaoke_selection->GetEventNext()) return; if(app.ui.karaoke_mode == KARAOKE_MODE_BOX) { gui_main_karaoke_part_clicked_cb(NULL, NULL, app.ui.karaoke_selection->GetEventNext()); } else { GtkTreeIter iter; gui_main_event_select(1, &iter, FALSE, FALSE); } }