2
my $ID = q$Id: lyricue,v 1.403 2010/08/09 05:01:05 cjdebenh Exp $;
8
# Documentation for lyricue that is displayed by perldoc
18
lyricue [-v|-l] [-b] [-r] [-w I<server>] [-d[q]] [-s I<server>]
22
This application is used to edit/display song lyrics on a second screen/projector for use at singing events such as church services.
34
Turn on debugging mode. Prints out debugging information.
35
Use -dq to enable SQL debugging as well
39
List available songs. Outputs a list of songs in HTML format
43
Turn off background changing ability. Speeds program load
47
Set server to connect to for Db and screen
51
Set server to connect to for MySQL
55
Do not maximize window on startup
59
Import song list from a file
65
All configuration is done by editing the configuration section in the program
69
Perl 5.6 or later, DBI::MySQL, Gtk2-Perl, MySQL database, Clutter-perl, Gstreamer
73
lyricue_server, lyricue_remote
77
Chris Debenham <chris@adebenham.com>
81
This program is released under the GPL (http://www.gnu.org/copyleft/gpl.html)
85
Lyric_interface Version 3.2.1-1
95
# Loads required modules, sets some global variables,
96
# and other global things
108
use IO::Socket::INET;
110
die "The gtk2-perl bindings could not be initialized; we need them to run!\n"
111
unless (Gtk2->init_check);
114
use Gtk2::Gdk::Keysyms;
118
use File::Temp qw/tempdir/;
119
use File::MimeInfo qw/globs/;
121
eval { require Locale::gettext };
124
print STDERR "Gettext not available, english text only\n";
130
import Locale::gettext;
132
#my $old_locale = setlocale(LC_ALL);
133
#setlocale(LC_ALL,"sv_SE.UTF-8");
134
textdomain('lyricue');
136
bind_textdomain_codeset('lyricue', "UTF-8");
138
binmode(STDOUT, ":utf8");
139
binmode(STDERR, ":utf8");
142
# Site Configuration. You should only have to
149
if ($^O eq 'MSWin32') {
150
$globals->{'etcdir'} = "etc/lyricue/";
151
$globals->{'basedir'} = ".lyricue/";
152
$globals->{'sharedir'} = "";
154
$globals->{'etcdir'} = "/etc/lyricue/";
155
$globals->{'basedir'} = Glib::get_user_data_dir . "/lyricue/";
156
$globals->{'oldbasedir'} = $ENV{'HOME'} . "/.lyricue/";
157
$globals->{'sharedir'} = "/usr/share/lyricue/";
161
# You shouldn't have to change anything after this line
164
# convenience variables for true and false
165
use constant FALSE => 0;
166
use constant TRUE => 1;
168
$globals->{'version'} = "3.2.1-1";
169
$globals->{'accessfile'} = $globals->{'etcdir'} . "access.conf";
170
$globals->{'defaultconf'} = $globals->{'etcdir'} . "default.conf";
171
$globals->{'configfile'} = $globals->{'basedir'} . "config2";
172
$globals->{'gladefile'} = $globals->{'sharedir'} . "lyricue.glade";
174
$globals->{'host'} = "localhost";
175
$globals->{'mysqlhost'} = "";
176
$globals->{'lyricdb'} = "lyricDb";
177
$globals->{'bibledb'} = "";
178
$globals->{'biblename'} = "";
179
$globals->{'category'} = "";
180
$globals->{'access'} = "";
181
$globals->{'usesword'} = TRUE;
182
$globals->{'mediadb'} = "mediaDb";
183
$globals->{'sortby'} = "title";
184
$globals->{'bg_previews'} = TRUE;
185
if ($^O eq 'MSWin32') {
186
$globals->{'diatheke'} = "";
188
$globals->{'diatheke'} = `which diatheke`;
189
chomp $globals->{'diatheke'};
191
$globals->{'unoconv'} = `which unoconv`;
192
chomp $globals->{'unoconv'};
193
$globals->{'convert'} = `which convert`;
194
chomp $globals->{'convert'};
195
$globals->{'video-thumbnailer'} = `which totem-video-thumbnailer`;
196
if ($globals->{'video-thumbnailer'} eq "") {
197
$globals->{'video-thumbnailer'} = `which totem-gstreamer-thumbnailer`;
199
if ($globals->{'video-thumbnailer'} eq "") {
200
$globals->{'video-thumbnailer'} = `which totem-video-thumbnailer`;
202
chomp $globals->{'video-thumbnailer'};
203
$globals->{'lyricue_server'} = `which lyricue_display`;
204
if ($globals->{'lyricue_server'} eq "") {
205
$globals->{'lyricue_server'} = `which lyricue_server`;
207
chomp $globals->{'lyricue_server'};
209
$globals->{'server_port'} = "2346"; #port used for lyric server
210
$globals->{'preview_port'} = "2347"; #port used for preview
211
$globals->{'miniview_port'} = "2348"; #port used for miniview
212
$globals->{'editview_port'} = "2349"; #port used for editview
213
$globals->{'update_timer'} = FALSE;
214
$globals->{'nav_update_timer'} = FALSE;
215
$globals->{'timer'} = FALSE;
216
$globals->{'debugging'} = FALSE;
217
$globals->{'spell'} = TRUE;
218
$globals->{'trayicon'} = TRUE;
219
$globals->{'preview_pid'} = FALSE;
220
$globals->{'miniview_pid'} = FALSE;
221
$globals->{'hovering_over_link'} = FALSE;
222
$globals->{'db_adminuser'} = "";
223
$globals->{'current_item'} = -1;
224
$globals->{'icon_width'} = 96;
225
$globals->{'icon_height'} = 72;
226
$globals->{'thumb_width'} = 128;
227
$globals->{'thumb_height'} = 96;
228
$globals->{'firstrun'} = FALSE;
231
eval { require Gtk2::Spell };
233
print STDERR "Gtk-Spell not available, spell checking turned off\n";
234
$globals->{'spell'} = FALSE;
238
eval { require Gtk2::TrayIcon };
240
print STDERR "Gtk-Trayicon not available, Tray icon turned off\n";
241
$globals->{'trayicon'} = FALSE;
243
import Gtk2::TrayIcon;
245
if ($globals->{'diatheke'} eq "") {
246
$globals->{'diatheke'} = "true";
250
use constant DEFAULT => 0;
251
use constant NOTRANS => 1;
252
use constant FADE => 2;
253
use constant SLIDE_TEXT => 3;
254
use constant ROTATE_TEXT => 4;
256
# Transition directions
257
use constant NONE => 0;
258
use constant WAIT => 2**0;
259
use constant UP => 2**1;
260
use constant DOWN => 2**2;
261
use constant RIGHT => 2**3;
262
use constant LEFT => 2**4;
263
use constant X_AXIS => 2**5;
264
use constant Y_AXIS => 2**6;
265
use constant Z_AXIS => 2**7;
266
use constant NUM_TRANS => 8;
275
my ($lyricDbh, $mediaDbh, $bibleDbh);
278
$errorcodes->{'lyricdbopen'} = fromutf(
280
"I'm sorry but I could not open the lyric database.\nPlease confirm that Lyricue is installed correctly and MySQL is running"
283
$errorcodes->{'bibledbopen'} = fromutf(
285
"I'm sorry but I could not open the bible database.\nPlease confirm that Lyricue is installed correctly and the current bible database exists.\nThe requested database was named "
288
$errorcodes->{'mediadbopen'} = fromutf(
290
"I'm sorry but I could not open the media database.\nPlease confirm that Lyricue is installed correctly and MySQL is running"
293
$errorcodes->{'sqlprepare'} =
294
fromutf(gettext("Unable to prepare query.\nHas mysql died?"));
295
$errorcodes->{'sqlexecute'} =
296
fromutf(gettext("Unable to execute query.\nHas mysql died?"));
297
$errorcodes->{'socketopen'} = fromutf(
299
"Sorry, I was unable to listen on the network.\nPlease make sure I am not already running"
302
$errorcodes->{'erroropen'} = fromutf(gettext("Could not open "));
303
$errorcodes->{'fileopenread'} = fromutf(
305
"Unable to read the file, are you sure it exists?\nThe file asked for was "
308
$errorcodes->{'fileopenwrite'} = fromutf(
310
"Unable to write to the file, you may not have sufficent permissions.\nPlease check the permissions for "
313
$errorcodes->{'usage'} = fromutf(
315
"\nUsage: lyricue <-v|-l> <-b> <-k> <-d> <-s>\n\n"
316
. "\t-v: Prints Lyricue version information & exits\n"
317
. "\t-l: Outputs song list in HTML & exits\n"
318
. "\t-b: Loads Lyricue without background previews\n"
319
. "\t-s: Specify the host on which the lyric server is located\n"
320
. "\t-r: Specify the host on which the mysql server is located\n"
321
. "\t-d: Prints debugging messages\n"
322
. "\t-w: Don't maximize on startup\n"
323
. "\t-i: Import songlist from file\n\n"
327
$errorcodes->{'nobible'} =
329
gettext("No bible has been selected\n" . "Please select one from the menu")
332
# Widgets affected by access controls
335
"buttonMainAdd", "buttonMainEdit", "add_song1", "edit_song1",
340
my @delete_items = ("delete_song1");
343
my @display_items = (
344
"previous_page1", "next_page1",
345
"display_now1", "blank_display1",
346
"buttonMainPrev", "buttonMainNext",
347
"buttonMainPoint", "buttonMainBlank",
348
"notebookRight", "buttonQuickShow",
349
"buttonMainClear", "clear_text1"
353
my @playlist_items = (
354
"buttonAddToPlaylist", "playlist1",
355
"vboxMainRight", "buttonMainImage",
356
"buttonMainVerse", "buttonMainSublist"
360
my @admin_items = ("user_administration1");
364
#****** lyricue/main_code
366
# main_code - main code section, not in subroutine
370
# Figure out where to go
378
foreach (0 .. (@ARGV - 1)) {
379
if ($ARGV[$_] eq "-v") {
380
print "Lyric Interface version " . $globals->{'version'} . "\n";
382
} elsif ($ARGV[$_] eq "-l") {
384
} elsif ($ARGV[$_] eq "-b") {
385
$globals->{'bg_previews'} = FALSE;
386
} elsif ($ARGV[$_] eq "-d") {
387
$globals->{'debugging'} = 2;
388
} elsif ($ARGV[$_] eq "-dq") {
389
$globals->{'debugging'} = 2;
390
} elsif ($ARGV[$_] eq "-sqlite") {
391
$globals->{'force_sqlite'} = TRUE;
392
} elsif ($ARGV[$_] eq "-w") {
393
$globals->{'run_windowed'} = TRUE;
394
} elsif ($ARGV[$_] eq "-s") {
395
$globals->{'host'} = $ARGV[$_ + 1];
397
} elsif ($ARGV[$_] eq "-r") {
398
$globals->{'mysqlhost'} = $ARGV[$_ + 1];
400
} elsif ($ARGV[$_] eq "-i") {
401
import_song_from_file($ARGV[$_ + 1]);
403
} elsif ($ARGV[$_] eq "") {
407
print $errorcodes->{'usage'};
413
# Set mysql host if not already set
414
if ($globals->{'mysqlhost'} eq "") {
415
$globals->{'mysqlhost'} = $globals->{'host'};
419
my ($query, $row, $sth, $rv);
424
# Check if user ~/.local/share/lyricue directory exists, otherwire create
425
if (-e $globals->{'basedir'}) {
426
if (!-d $globals->{'basedir'}) {
428
"Old ~/.local/share/lyricue existed but was not a directory, moving to ~/.local/share/lyricue.orig\n";
429
rename $globals->{'basedir'}, $globals->{'basedir'} . ".orig";
430
mkdir $globals->{'basedir'}, 0777;
433
if (-e $globals->{'oldbasedir'}) {
434
my $movexml = Gtk2::GladeXML->new($globals->{'gladefile'},
435
'dialogConfirm', 'lyricue');
436
$movexml->signal_autoconnect_from_package('');
437
$movexml->get_widget('labelDelete')->set_text(
440
"The directory used to hold configuration files has changed\n"
441
. "It is now ~/.local/share/lyricue\n"
442
. "If you do not wish to do this press Cancel and Lyricue will exit"
446
my $confirm = $movexml->get_widget('dialogConfirm')->run();
447
if ($confirm eq "ok") {
448
debug("Migrating lyricue configuration");
449
system("mkdir -p " . $globals->{'basedir'});
451
. $globals->{'oldbasedir'} . "/* "
452
. $globals->{'basedir'});
453
close_dialog($movexml->get_widget('dialogConfirm'));
455
print STDERR "Exiting as we are not migrating configuration";
459
system("mkdir -p " . $globals->{'basedir'});
464
my $logname = $globals->{'basedir'} . "/frontend.log";
465
rename($logname, $logname . ".old")
466
or system("mv", $logname, $logname . ".old");
467
open(LOG, ">" . $logname);
468
binmode LOG, ":utf8";
469
debug("Lyric Interface version " . $globals->{'version'} . "\n" . $ID);
471
Gtk2::GladeXML->new($globals->{'gladefile'}, 'windowMain', 'lyricue');
472
$widgets->{'main'}->signal_autoconnect_from_package('');
474
# Load the config file
475
if (-d $globals->{'basedir'}) {
476
if (!-e $globals->{'configfile'}) {
477
debug("Creating new configuration");
479
"cp " . $globals->{'defaultconf'} . " " . $globals->{'configfile'});
480
$config = load_config();
481
$globals->{'firstrun'} = TRUE;
484
$globals->{'firstrun'} = FALSE;
486
debug("Loading config and access");
487
$config = load_config();
489
$globals->{'access'} = load_access();
491
# Open lyricDB, bibleDB and mediaDb
496
if (defined $config->{'DefBible'} && ($config->{'DefBible'} ne "")) {
497
my @tmpbible = split(/;/, $config->{'DefBible'}, 2);
498
$globals->{'biblename'} = $tmpbible[1];
499
@tmpbible = split(/:/, $tmpbible[0], 2);
500
do_change_bible($tmpbible[1], $tmpbible[0]);
504
if ($globals->{'trayicon'}) {
505
debug("Creating Tray icons");
507
my $trayicon ('trayClear', 'trayDown', 'trayUp', 'trayRight', 'trayLeft')
510
eval { $tray = Gtk2::TrayIcon->new("Lyricue-" . $trayicon); };
512
debug("Unable to load system tray");
515
Gtk2::GladeXML->new($globals->{'gladefile'}, $trayicon,
517
$trayxml->signal_autoconnect_from_package('');
518
$tray->add($trayxml->get_widget($trayicon));
523
$0 = "Lyricue Interface";
525
$globals->{'thumbnail_factory'} = Gnome2::ThumbnailFactory->new('normal');
527
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data} = -1;
530
# Don't let them cancel out of the playlist chooser yet
531
$widgets->{'main'}->get_widget('toolbuttonPlayCancel')->hide;
533
# Setup background tasks
534
$globals->{'tracker_timer'} = Glib::Timeout->add(1000, \&check_tracker);
535
$globals->{'clean_idle'} = Glib::Idle->add(\&clean_database);
539
# Should never get here
544
#****f* lyricue/close_main
550
# Callback function to close the window
554
# Closes the interface
562
unlink $globals->{'configfile'} . ".bak";
563
open(CONFIG, "$globals->{'configfile'}")
564
|| display_fatal($errorcodes->{'fileopenread'}, $! . "\nSQL: " . $query);
566
binmode(CONFIG, ":utf8");
573
rename($globals->{'configfile'}, $globals->{'configfile'} . ".bak");
574
open(CONFIG, ">$globals->{'configfile'}")
575
|| display_fatal($errorcodes->{'fileopenwrite'}, $! . "\nSQL: " . $query);
576
binmode(CONFIG, ":utf8");
577
print CONFIG $config;
578
print CONFIG save_state();
581
$lyricDbh->disconnect;
582
if (!$globals->{'usesword'}) {
583
$bibleDbh->disconnect;
585
$mediaDbh->disconnect;
587
if ($globals->{'preview_pid'}) {
588
debug("Killing $globals->{'preview_pid'}");
589
kill 9, $globals->{'preview_pid'};
591
if ($globals->{'miniview_pid'}) {
592
debug("Killing $globals->{'miniview_pid'}");
593
kill 9, $globals->{'miniview_pid'};
602
#****f* lyricue/update_playlist
606
# update_playlist($selectedid)
608
# Clear the playlist area and redisplay with updated info
610
# $selectedid - Currently selected item
615
sub update_playlist {
616
my ($selectedid) = @_;
617
debug("Updating playlist");
618
if (!defined $selectedid) {
620
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
622
my ($m, $i) = $selection->get_selected;
624
$selectedid = $m->get($i, 2);
630
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
633
my $model = $widgets->{'main'}->get_widget('treePlaylist')->get_model();
635
$widgets->{'main'}->get_widget('treePlaylist')
636
->map_expanded_rows(\&save_expanded, \$expanded);
640
# Column 1 -> Visible text
642
# Column 3 -> playorder
643
# Column 4 -> transition
645
Gtk2::TreeStore->new('Glib::String', 'Glib::String', 'Glib::String',
647
$widgets->{'main'}->get_widget('treePlaylist')->set_model($model);
648
my $column = Gtk2::TreeViewColumn->new_with_attributes(
650
Gtk2::CellRendererText->new,
654
$widgets->{'main'}->get_widget('treePlaylist')->append_column($column);
656
$widgets->{'main'}->get_widget('treePlaylist')->set_model($model);
658
add_playlist($playlist, undef, $model, $selectedid, \$expanded);
659
$globals->{'current_item'} = 0;
664
#****f* lyricue/add_playlist
666
# add_playlist - Add a playlist to the playlist area
668
# add_playlist ($playlist, $iter, $model, $selectedid, $expanded)
670
# Add a playlist to the playlist area
672
# $playlist - Playlist to add
673
# $iter - Where to add it in the playlist area
674
# $model - The playlist tree model
675
# $selectedid - The currently selected item
676
# $expanded - A lookup of all items saying which are expanded
682
my ($playlist, $iter, $model, $selectedid, $expanded) = @_;
683
debug("Add playlist " . $playlist);
685
"SELECT * FROM playlist WHERE playlist="
687
. " ORDER BY playorder";
690
my $sth = $lyricDbh->prepare($query)
691
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
692
my $rv = $sth->execute
693
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
694
while (my $row = $sth->fetchrow_hashref()) {
697
if ($row->{'type'} eq "back") {
698
my $query2 = "SELECT description FROM media WHERE id=\""
699
. $row->{'data'} . "\"";
702
my $sth2 = $mediaDbh->prepare($query2)
703
|| display_fatal($errorcodes->{'sqlprepare'},
704
$! . "\nSQL: " . $query2);
705
my $rv2 = $sth2->execute
706
|| display_fatal($errorcodes->{'sqlexecute'},
707
$! . "\nSQL: " . $query2);
708
my $row2 = $sth2->fetchrow_hashref();
709
$title = "Background : " . $row2->{'description'};
710
} elsif ($row->{'type'} eq "file") {
712
if (/^(.*)\/(.*?)$/) {
715
if ($dir =~ /^\/var\/tmp\/lyricue-/) {
716
$filename =~ s/\..*?$//g;
717
$filename =~ s/_/ /g;
718
$title = "Presentation: " . $filename;
719
} elsif ($dir =~ /^dvd:/) {
720
if ($filename =~ / /) {
721
$filename =~ s/ / from /;
723
$title = "DVD Title: " . $filename;
725
$title = "File: " . $filename . " in " . $dir;
728
$title = "File: " . $row->{'data'};
730
} elsif ($row->{'type'} eq "imag") {
731
my ($type, $id) = split /;/, $row->{'data'};
736
if ($type eq "dir") {
737
$id =~ s/^$config->{'ImageDirectory'}\///;
738
$title = "Image: " . $id;
741
"SELECT description FROM media WHERE id=\"" . $id . "\"";
744
my $sth2 = $mediaDbh->prepare($query2)
745
|| display_fatal($errorcodes->{'sqlprepare'},
746
$! . "\nSQL: " . $query2);
747
my $rv2 = $sth2->execute
748
|| display_fatal($errorcodes->{'sqlexecute'},
749
$! . "\nSQL: " . $query2);
750
my $row2 = $sth2->fetchrow_hashref();
751
$title = "Image: " . $row2->{'description'};
753
} elsif ($row->{'type'} eq "vers") {
754
$title = "Verses " . $row->{'data'};
755
} elsif ($row->{'type'} eq "song") {
756
my $query2 = "SELECT pagetitle, lyrics FROM page WHERE pageid="
760
my $sth2 = $lyricDbh->prepare($query2)
761
|| display_fatal($errorcodes->{'sqlprepare'},
762
$! . "\nSQL: " . $query);
763
my $rv2 = $sth2->execute
764
|| display_fatal($errorcodes->{'sqlexecute'},
765
$! . "\nSQL: " . $query);
766
my $row2 = $sth2->fetchrow_hashref();
767
my $lyrics = $row2->{'lyrics'};
768
if ($globals->{'invert'}) {
769
my @lyricl = split(/\n/, $lyrics);
770
$title = $lyricl[@lyricl - 1];
772
($title, undef) = split(/\n/, $lyrics);
774
if (defined $row2->{'pagetitle'} && ($row2->{'pagetitle'} ne '')) {
775
$title = "<b>" . $row2->{'pagetitle'} . "</b>\n" . $title;
780
} elsif ($row->{'type'} eq "play" | $row->{'type'} eq "sub") {
782
my $query2 = "SELECT * FROM playlists WHERE id=" . $row->{'data'};
785
my $sth2 = $lyricDbh->prepare($query2)
786
|| display_fatal($errorcodes->{'sqlprepare'},
787
$! . "\nSQL: " . $query);
788
my $rv2 = $sth2->execute
789
|| display_fatal($errorcodes->{'sqlexecute'},
790
$! . "\nSQL: " . $query);
791
my $row2 = $sth2->fetchrow_hashref();
793
$title = $row2->{'title'};
795
if ($row2->{'ref'} && $row2->{'ref'} != 0) {
797
"SELECT songnum FROM lyricMain WHERE id=" . $row2->{'ref'};
800
$sth2 = $lyricDbh->prepare($query2)
801
|| display_fatal($errorcodes->{'sqlprepare'},
802
$! . "\nSQL: " . $query2);
803
$rv2 = $sth2->execute
804
|| display_fatal($errorcodes->{'sqlexecute'},
805
$! . "\nSQL: " . $query2);
806
$row2 = $sth2->fetchrow_hashref();
807
if ($row2->{'songnum'} != 0) {
808
$title = $row2->{'songnum'} . " - " . $title;
812
$title = "Unknown type";
815
# Add image name to playlist item title
817
"SELECT * FROM associations WHERE playlist=" . $row->{'playorder'};
820
my $sth3 = $lyricDbh->prepare($query3)
821
|| display_fatal($errorcodes->{'sqlprepare'},
822
$! . "\nSQL: " . $query3);
823
my $rv3 = $sth3->execute
824
|| display_fatal($errorcodes->{'sqlexecute'},
825
$! . "\nSQL: " . $query3);
827
while (my $row3 = $sth3->fetchrow_hashref()) {
828
$imagename = $row3->{'imagename'};
831
my $playorder = $row->{'playorder'};
832
my $newiter = $model->append($iter);
833
$title =~ s/&/&/g;
838
2 => $row->{'playorder'},
839
3 => $row->{'transition'}
842
# Set sub-item if image associated
845
my ($type, $id) = split /;/, $imagename;
848
"SELECT description FROM media WHERE id=\"" . $id . "\"";
851
my $sth2 = $mediaDbh->prepare($query2)
852
|| display_fatal($errorcodes->{'sqlprepare'},
853
$! . "\nSQL: " . $query2);
854
my $rv2 = $sth2->execute
855
|| display_fatal($errorcodes->{'sqlexecute'},
856
$! . "\nSQL: " . $query2);
857
my $row2 = $sth2->fetchrow_hashref();
858
my $imgiter = $model->append($newiter);
861
0 => "* Background: " . $row2->{'description'},
863
2 => $row->{'playorder'},
864
3 => $row->{'transition'}
867
my $imgiter = $model->append($newiter);
868
$id =~ s/^$config->{'BGDirectory'}//g;
871
0 => "* Background: " . $id,
873
2 => $row->{'playorder'},
874
3 => $row->{'transition'}
879
# Set sub-item if transition associated
880
if (($row->{'transition'} >> (NUM_TRANS*2)) != 0) {
881
my $transiter = $model->append($newiter);
884
0 => "* Page Transition Set",
886
2 => $row->{'playorder'},
887
3 => $row->{'transition'}
891
# Add sublists/playlists
892
if ($row->{'type'} eq "play" | $row->{'type'} eq "sub") {
893
add_playlist($row->{'data'}, $newiter, $model, $selectedid,
897
if ($$expanded->{$playorder}) {
898
$widgets->{'main'}->get_widget('treePlaylist')
899
->expand_to_path($model->get_path($newiter));
902
# Select what was selected and expand its parent
903
if (defined $selectedid && $row->{'playorder'} == $selectedid) {
904
debug("Selecting $selectedid");
905
my $path = $model->get_path($newiter);
906
my $pathstring = $path->to_string();
907
$pathstring =~ s/^(.*):(.*?)$/$1/g;
909
$widgets->{'main'}->get_widget('treePlaylist')
911
Gtk2::TreePath->new_from_string($pathstring));
913
$widgets->{'main'}->get_widget('treePlaylist')
914
->get_selection->select_iter($newiter);
921
#****f* lyricue/save_expanded
925
# save_expanded($tree, $path, $expanded)
927
# Save the expanded state of the treeview item
929
# $tree - Treeview to save state of
930
# $part - Item to check
931
# $expanded - state lookup
933
# $expanded is updated
937
debug("Save expanded");
938
my ($tree, $path, $expanded) = @_;
939
my $iter = $tree->get_model->get_iter($path);
940
$$expanded->{$tree->get_model->get($iter, 2)} = TRUE;
946
#****f* lyricue/change_sort_order
950
# change_sort_order (undef,$column)
952
# Change the order by which the available songs are displayed
955
# $column - which column to order by
957
# Calls update_available to redisplay available songs
960
sub change_sort_order {
961
debug("change sort order");
962
my (undef, $column) = @_;
964
$globals->{'sortby'} = "book";
965
} elsif ($column == 2) {
966
$globals->{'sortby'} = "songnum";
967
} elsif ($column == 3) {
968
$globals->{'sortby'} = "id";
969
} elsif ($column == 4) {
970
$globals->{'sortby'} = "book,songnum,title";
971
} elsif ($column == 5) {
972
$globals->{'sortby'} = "book,title";
974
$globals->{'sortby'} = "title";
976
debug("Changing sort order to " . $globals->{'sortby'});
982
#****f* lyricue/update_available
986
# update_available ()
988
# Update the list of available songs, limited by keyword and sorted by orderby
990
# updated list of available songs
993
sub update_available {
994
debug("update available");
995
reset_timer($globals->{'update_timer'});
998
Gtk2::ListStore->new('Glib::String', 'Glib::String', 'Glib::Uint',
1002
$widgets->{'main'}->get_widget('treeAvailable')->{user_data}
1003
&& ($widgets->{'main'}->get_widget('treeAvailable')->{user_data} eq
1007
$widgets->{'main'}->get_widget('treeAvailable')->{data} = ();
1009
$widgets->{'main'}->get_widget('treeAvailable')->{user_data} = "load";
1011
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Title")),
1012
Gtk2::CellRendererText->new, text => 0);
1014
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Book")),
1015
Gtk2::CellRendererText->new, text => 1);
1016
my $column3 = Gtk2::TreeViewColumn->new_with_attributes(
1017
fromutf(gettext("Song Number")),
1018
Gtk2::CellRendererText->new, text => 2);
1019
$column1->set_resizable(TRUE);
1020
$column2->set_resizable(TRUE);
1021
$column3->set_resizable(TRUE);
1022
$widgets->{'main'}->get_widget('treeAvailable')
1023
->append_column($column1);
1024
$widgets->{'main'}->get_widget('treeAvailable')
1025
->append_column($column2);
1026
$widgets->{'main'}->get_widget('treeAvailable')
1027
->append_column($column3);
1028
$column1->signal_connect("clicked", "change_sort_order", 0);
1029
$column2->signal_connect("clicked", "change_sort_order", 1);
1030
$column3->signal_connect("clicked", "change_sort_order", 2);
1032
my $songname = $widgets->{'main'}->get_widget('entrySearch')->get_text();
1035
if (($config->{'SpecialSong'}) ne "" && ($songname eq "")) {
1037
"SELECT id,title,songnum,book FROM lyricMain WHERE title LIKE \"%"
1038
. $config->{'SpecialSong'} . "%\"";
1040
$sth = $lyricDbh->prepare($query)
1041
|| display_fatal($errorcodes->{'sqlprepare'},
1042
$! . "\nSQL: " . $query);
1044
|| display_fatal($errorcodes->{'sqlexecute'},
1045
$! . "\nSQL: " . $query);
1046
$row = $sth->fetchrow_hashref();
1047
my $iter = $store->append;
1049
$iter, 0, fromutf($row->{'title'}), 1,
1050
fromutf($row->{'book'}), 2, $row->{'songnum'}, 3,
1053
$special_id = $row->{'id'};
1056
$query = "SELECT id,title,songnum,book FROM lyricMain WHERE id > 0";
1058
if (defined $special_id && ($special_id > 0)) {
1059
$query .= " AND id != " . $special_id;
1062
# Add search term if applicable
1064
# $query .= " AND keywords LIKE \"%" . $keywords . "%\"";
1065
#} elsif ($songname) {
1066
if ($songname =~ /^\d+$/) {
1067
$query .= " AND songnum=" . $songname;
1069
$songname =~ s/[\s,]/%/g;
1070
$query .= " AND title LIKE \"%" . $songname . "%\"";
1074
$query .= " ORDER BY " . $globals->{'sortby'};
1076
$sth = $lyricDbh->prepare($query)
1077
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
1079
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
1081
while ($row = $sth->fetchrow_hashref()) {
1082
my $iter = $store->append;
1084
$iter, 0, fromutf($row->{'title'}), 1,
1085
fromutf($row->{'book'}), 2, $row->{'songnum'}, 3,
1090
if (($songname ne "") && ($config->{'DatabaseType'} eq "mysql")) {
1092
"SELECT id,title,songnum,book,SUBSTRING_INDEX(lyrics,'\n',1) as line FROM page,lyricMain WHERE pagenum=1 AND SUBSTRING_INDEX(lyrics,'\n',1) LIKE \"%"
1094
. "%\" AND page.songid=lyricMain.id AND title != SUBSTRING_INDEX(lyrics,'\n',1) ORDER BY "
1095
. $globals->{'sortby'};
1097
$sth = $lyricDbh->prepare($query)
1098
|| display_fatal($errorcodes->{'sqlprepare'},
1099
$! . "\nSQL: " . $query);
1101
|| display_fatal($errorcodes->{'sqlexecute'},
1102
$! . "\nSQL: " . $query);
1104
while ($row = $sth->fetchrow_hashref()) {
1105
my $iter = $store->append;
1109
fromutf($row->{'line'}) . " (" . fromutf($row->{'title'}) . ")",
1120
$widgets->{'main'}->get_widget('treeAvailable')->set_model($store);
1121
$widgets->{'main'}->get_widget('treeAvailable')
1122
->set_headers_clickable(TRUE);
1123
$widgets->{'main'}->get_widget('treeAvailable')
1124
->get_selection->set_mode('multiple');
1125
debug("Avail updated");
1131
#****f* lyricue/treeAvailable_row_activated
1133
# treeAvailable_row_activated
1135
# treeAvailable_row_activated ($widget, $event)
1137
# Add the currently selected song to the playlist
1139
# $widget - Calling widget
1140
# $event - Calling event
1142
# New song on playlist
1145
sub treeAvailable_row_activated {
1146
my ($widget, $event) = @_;
1147
debug("Song activated from available songs list");
1152
#****f* lyricue/popup_avail_menu
1156
# popup_avail_menu ($widget, $event)
1158
# popup a menu when available songs right-clicked
1160
# $widget - Calling widget
1161
# $event - Calling event
1163
# Displays the right-click menu
1166
sub popup_avail_menu {
1167
my ($widget, $event) = @_;
1168
debug("Button clicked on available songs list");
1169
if ($event->button == 3) {
1170
my $path = $widget->get_path_at_pos($event->x, $event->y);
1171
$widget->get_selection->select_path($path);
1172
debug($path . " path");
1175
if ($globals->{'access'} =~ /e/) {
1177
[fromutf(gettext("/Edit Song")), undef, 'edit_song', 1, '', ''];
1179
if ($globals->{'access'} =~ /d/) {
1182
fromutf(gettext("/Delete Song")),
1183
undef, 'delete_song', 1, '', ''
1189
fromutf(gettext("/Refresh List")),
1190
undef, 'update_available', 1, '', ''
1193
fromutf(gettext("/Order - Songbook -> No.")),
1194
undef, 'change_sort_order', 4, '', ''
1197
fromutf(gettext("/Order - Songbook -> Name.")),
1198
undef, 'change_sort_order', 5, '', ''
1201
if ($globals->{'access'} =~ /p/) {
1205
fromutf(gettext("/Add to Playlist")),
1206
undef, 'add_to_playlist', 1, '', ''
1211
Gtk2::ItemFactory->new('Gtk2::Menu', "<availpopup>", undef);
1212
$factory->create_items(1, @items);
1213
$factory->popup($event->x_root, $event->y_root, $event->button,
1217
my $path = $widget->get_path_at_pos($event->x, $event->y);
1218
if (!defined $path) {
1221
debug("song selected");
1222
my $model = $widgets->{'main'}->get_widget('treeAvailable')->get_model;
1223
my $iter = $model->get_iter($path);
1224
my $songid = $model->get($iter, 3);
1226
"SELECT pageid FROM page WHERE songid="
1228
. " ORDER BY pagenum";
1230
$sth = $lyricDbh->prepare($query)
1231
|| display_fatal($errorcodes->{'sqlprepare'},
1232
$! . "\nSQL: " . $query);
1234
|| display_fatal($errorcodes->{'sqlexecute'},
1235
$! . "\nSQL: " . $query);
1236
my @row = $sth->fetchrow_array();
1238
if (defined $row[0]) {
1239
my $pageid = $row[0];
1240
preview_pageid($pageid);
1246
# Tell calling code that we have not handled this event; pass it on.
1252
#****f* lyricue/popup_play_menu
1256
# popup_play_menu ($event)
1258
# popup a menu when playlist item right-clicked
1260
# $event - the calling event
1262
# Displays the right-click menu
1265
sub popup_play_menu {
1267
debug("Button clicked on playlist window");
1269
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
1271
"SELECT title, data FROM playlist, playlists WHERE playlist.data = playlists.id AND playlist = "
1273
. " AND type = 'sub'";
1275
my $sth = $lyricDbh->prepare($query)
1276
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
1277
my $rv = $sth->execute
1278
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
1281
while ($row = $sth->fetchrow_hashref()) {
1283
$text->{'data'} = $row->{'data'};
1284
$text->{'title'} = $row->{'title'};
1286
my @childid = find_more_children($row->{'data'});
1287
foreach (@childid) {
1288
debug("Child sublist found. ID: " . $_);
1289
my $query2 = "SELECT title FROM playlists WHERE id=" . $_;
1291
my $sth2 = $lyricDbh->prepare($query2)
1292
|| display_fatal($errorcodes->{'sqlprepare'},
1293
$! . "\nSQL: " . $query2);
1294
my $rv2 = $sth2->execute
1295
|| display_fatal($errorcodes->{'sqlexecute'},
1296
$! . "\nSQL: " . $query2);
1297
my $row2 = $sth2->fetchrow_hashref();
1299
$text->{'data'} = $row2->{'data'};
1300
$text->{'title'} = $row2->{'title'};
1306
[fromutf(gettext("/Duplicate Item")), undef, 'copy_item', 1],
1308
fromutf(gettext("/Remove from Playlist")), undef,
1309
'remove_from_playlist', 1
1311
[fromutf(gettext("/Refresh Playlist")), undef, 'update_playlist', 1],
1312
[fromutf(gettext("/Invert Line Display")), undef, 'invert_lines', 1],
1313
[fromutf(gettext("/Loop this playlist item")), undef, 'begin_loop', 1],
1315
fromutf(gettext("/Associate background")), undef,
1316
'prepare_for_association', 1
1319
fromutf(gettext("/Dis-associate background")), undef,
1320
'disassociate_bg', 1
1323
fromutf(gettext("/Move to sublist/Main")), undef,
1324
'move_item_to_sublist', $playlist
1327
foreach (sort { uc($a->{'title'}) cmp uc($b->{'title'}) } @list) {
1328
my $item = fromutf(gettext("/Move to sublist/")) . $_->{'title'};
1329
push @items, [$item, undef, 'move_item_to_sublist', $_->{'data'}],;
1331
my $factory = Gtk2::ItemFactory->new('Gtk2::Menu', '<playpopup>', undef);
1332
$factory->create_items(undef, @items);
1333
$factory->popup($event->x_root, $event->y_root, 0, $event->time);
1338
#****f* lyricue/add_song
1344
# Called which add chosen from menu/buttons
1347
# display add window
1352
debug("Add clicked");
1353
if ($widgets->{'add'} && $widgets->{'add'}->get_widget('windowEditSong')) {
1354
if (!$widgets->{'add'}->get_widget('windowEditSong')->visible) {
1355
$widgets->{'add'}->get_widget('windowEditSong')->destroy;
1361
Gtk2::GladeXML->new($globals->{'gladefile'}, 'windowEditSong', 'lyricue');
1362
$widgets->{'add'}->signal_autoconnect_from_package('');
1364
$widgets->{'add'}->get_widget('buttonEditPreviewServer')
1365
->signal_connect("clicked", "preview_page","SERVER");
1366
$widgets->{'add'}->get_widget('notebookEditPages')->remove_page(0);
1369
$widgets->{'add'}->get_widget('windowEditSong')->{user_data} = 0;
1370
$widgets->{'add'}->get_widget('windowEditSong')->show_all();
1371
$widgets->{'add'}->get_widget('buttonEditRemovePage')->set_sensitive(FALSE);
1372
$widgets->{'add'}->get_widget('remove_page1')->set_sensitive(FALSE);
1377
#****f* lyricue/delete_song
1383
# Confirm if a song is to be deleted
1385
# calls create_dialog_delete to confirm deletion
1389
debug("Delete song selected");
1391
$widgets->{'main'}->get_widget('treeAvailable')->get_selection;
1392
my $modelTree = $widgets->{'main'}->get_widget('treeAvailable')->get_model;
1393
my @sel = $selection->get_selected_rows;
1394
my $deletexml = Gtk2::GladeXML->new($globals->{'gladefile'},
1395
'dialogSelectSongs', 'lyricue');
1396
$deletexml->signal_autoconnect_from_package('');
1397
$deletexml->get_widget('labelSelectSongs')->set_text(gettext("Are you sure you wish to delete "));
1398
my $model = Gtk2::ListStore->new(
1399
'Glib::Boolean', 'Glib::String', 'Glib::String', 'Glib::String',
1400
'Glib::Uint', 'Glib::Uint'
1402
my $renderer = Gtk2::CellRendererToggle->new;
1403
$renderer->signal_connect(
1405
my ($cell, $path_str, $model) = @_;
1406
my $path = Gtk2::TreePath->new_from_string($path_str);
1408
my $iter = $model->get_iter($path);
1409
my ($toggle_item) = $model->get($iter, $column);
1411
debug('setting ' . $path_str . ' to ' . $toggle_item);
1414
$model->set($iter, $column, $toggle_item);
1419
Gtk2::TreeViewColumn->new_with_attributes("", $renderer, active => 0);
1421
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Title")),
1422
Gtk2::CellRendererText->new, text => 1);
1424
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Artist")),
1425
Gtk2::CellRendererText->new, text => 2);
1427
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Book")),
1428
Gtk2::CellRendererText->new, text => 3);
1430
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Song Number")),
1431
Gtk2::CellRendererText->new, text => 4);
1432
$column1->set_resizable(TRUE);
1433
$column2->set_resizable(TRUE);
1434
$column3->set_resizable(TRUE);
1435
$column4->set_resizable(TRUE);
1436
$column5->set_resizable(TRUE);
1437
$deletexml->get_widget('treeSongImport')
1438
->append_column($column1);
1439
$deletexml->get_widget('treeSongImport')
1440
->append_column($column2);
1441
$deletexml->get_widget('treeSongImport')
1442
->append_column($column3);
1443
$deletexml->get_widget('treeSongImport')
1444
->append_column($column4);
1445
$deletexml->get_widget('treeSongImport')
1446
->append_column($column5);
1447
foreach my $path (@sel) {
1448
my $iter = $modelTree->get_iter($path);
1449
my $songid = $modelTree->get($iter, 3);
1450
if (!($modelTree->get($iter, 1) eq $config->{'SpecialSong'})) {
1451
$query = "SELECT title,songnum,book,artist FROM lyricMain WHERE id="
1454
$sth = $lyricDbh->prepare($query)
1455
|| display_fatal($errorcodes->{'sqlprepare'},
1456
$! . "\nSQL: " . $query);
1458
|| display_fatal($errorcodes->{'sqlexecute'},
1459
$! . "\nSQL: " . $query);
1460
$row = $sth->fetchrow_hashref();
1462
my $newiter = $model->append;
1467
2, $row->{'artist'},
1469
4, $row->{'songnum'},
1474
$deletexml->get_widget('treeSongImport')->set_model($model);
1475
$deletexml->get_widget('treeSongImport')->set_headers_clickable(TRUE);
1477
$deletexml->get_widget('dialogSelectSongs')->run();
1478
if ($confirm == 1) {
1479
$model->foreach(\&do_delete_song);
1481
close_dialog($deletexml->get_widget('dialogSelectSongs'));
1487
#****f* lyricue/do_delete_song
1491
# do_delete_song ($songid)
1493
# Do the actual deletion of a song including from the playlist
1495
# $songid - Id of song to be deleted
1500
sub do_delete_song {
1501
my ($store, $path, $iter) = @_;
1502
my ($query, $sth, $rv);
1503
if ($store->get($iter,0) == FALSE) {
1506
my $songid = $store->get($iter,5);
1507
debug("do delete song $songid");
1509
start_transaction();
1510
$query = "DELETE FROM lyricMain WHERE id=" . $songid;
1512
$sth = $lyricDbh->prepare($query)
1513
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
1515
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
1517
$query = "DELETE FROM page WHERE songid=" . $songid;
1519
$sth = $lyricDbh->prepare($query)
1520
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
1522
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
1525
"SELECT playorder FROM playlist,page WHERE playlist.data=page.pageid AND playlist.type=\"song\" AND page.songid="
1528
$sth = $lyricDbh->prepare($query)
1529
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
1531
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
1534
while (my @row = $sth->fetchrow_array()) {
1536
my $query2 = "DELETE FROM playlist WHERE playorder=" . $row[0];
1538
my $sth2 = $lyricDbh->prepare($query2)
1539
|| display_fatal($errorcodes->{'sqlprepare'},
1540
$! . "\nSQL: " . $query2);
1541
my $rv2 = $sth2->execute
1542
|| display_fatal($errorcodes->{'sqlexecute'},
1543
$! . "\nSQL: " . $query2);
1547
if ($disable == 1) {
1549
#Cancel any loop timers
1550
#Continuing to loop over a modified playlists due to
1551
#removed items represents a possible crash risk - better safe
1554
reset_timer($globals->{'timer'});
1563
#****f* lyricue/do_save_song
1569
# Save the song to the DB
1572
# One more song in the DB
1576
my ($query, $sth, $page, $songid);
1577
debug("do save song");
1578
my $newitem = FALSE;
1579
$songid = $widgets->{'add'}->get_widget('windowEditSong')->{user_data};
1581
$widgets->{'add'}->get_widget('notebookEditPages')->get_n_pages;
1583
start_transaction();
1586
# Remove extra pages
1587
debug("Song number: " . $songid);
1589
"DELETE FROM page WHERE songid="
1594
$sth = $lyricDbh->prepare($query)
1595
|| display_fatal($errorcodes->{'sqlprepare'},
1596
$! . "\nSQL: " . $query);
1598
|| display_fatal($errorcodes->{'sqlexecute'},
1599
$! . "\nSQL: " . $query);
1602
"DELETE playlist FROM playlist LEFT JOIN page ON playlist.data=page.pageid WHERE page.songid="
1604
. " AND page.pagenum > "
1607
$sth = $lyricDbh->prepare($query)
1608
|| display_fatal($errorcodes->{'sqlprepare'},
1609
$! . "\nSQL: " . $query);
1611
|| display_fatal($errorcodes->{'sqlexecute'},
1612
$! . "\nSQL: " . $query);
1614
# Update lyricMain with new info
1615
$query = "UPDATE lyricMain SET title="
1616
. quote($widgets->{'add'}->get_widget('entryEditName')->get_text());
1617
$query .= ", songnum="
1618
. quote($widgets->{'add'}->get_widget('entryEditNumber')->get_text());
1620
. quote($widgets->{'add'}->get_widget('entryEditBook')->get_text());
1621
$query .= ", artist="
1622
. quote($widgets->{'add'}->get_widget('entryEditArtist')->get_text());
1626
$widgets->{'add'}->get_widget('entryEditCopyright')->get_text());
1628
if (!$widgets->{'add'}->get_widget('checkEditAudit')->get_active()) {
1629
$noaudit = "NOAUDIT ";
1631
$query .= ", keywords="
1635
. $widgets->{'add'}->get_widget('entryEditKeywords')
1639
$query .= " WHERE id=" . $songid;
1641
$sth = $lyricDbh->prepare($query)
1642
|| display_fatal($errorcodes->{'sqlprepare'},
1643
$! . "\nSQL: " . $query);
1645
|| display_fatal($errorcodes->{'sqlexecute'},
1646
$! . "\nSQL: " . $query);
1650
$query = "SELECT MAX(id)+1 FROM lyricMain WHERE id < 2000000";
1652
$sth = $lyricDbh->prepare($query)
1653
|| display_fatal($errorcodes->{'sqlprepare'},
1654
$! . "\nSQL: " . $query);
1656
|| display_fatal($errorcodes->{'sqlexecute'},
1657
$! . "\nSQL: " . $query);
1658
my @row = $sth->fetchrow_array;
1660
if ((! defined $songid) || ($songid < 1)) {
1663
debug("Song number: " . $songid);
1667
"INSERT INTO lyricMain ( id, title, songnum, book, artist, keywords, copyright, entered, written ) VALUES ( "
1671
toutf($widgets->{'add'}->get_widget('entryEditName')->get_text()))
1675
toutf($widgets->{'add'}->get_widget('entryEditNumber')->get_text()))
1679
toutf($widgets->{'add'}->get_widget('entryEditBook')->get_text()))
1683
toutf($widgets->{'add'}->get_widget('entryEditArtist')->get_text()))
1687
$widgets->{'add'}->get_widget('entryEditKeywords')->get_text()
1692
$widgets->{'add'}->get_widget('entryEditCopyright')->get_text()
1694
) . ", NOW(), NOW() )";
1696
$sth = $lyricDbh->prepare($query)
1697
|| display_fatal($errorcodes->{'sqlprepare'},
1698
$! . "\nSQL: " . $query);
1700
|| display_fatal($errorcodes->{'sqlexecute'},
1701
$! . "\nSQL: " . $query);
1703
foreach my $pagenum (1 .. $numpages) {
1705
$widgets->{'add'}->get_widget('notebookEditPages')
1706
->get_nth_page($pagenum - 1);
1708
$widgets->{'add'}->get_widget('notebookEditPages')
1709
->get_tab_label($page)->get_children->get_text;
1710
my $text = fromutf(gettext("Page "));
1712
$lyricDbh->quote(get_buffer_text($page->get_children->get_buffer));
1713
if ($title =~ /^$text/) {
1714
$text = $lyricDbh->quote("");
1716
$text = $lyricDbh->quote($title);
1721
"SELECT pageid FROM page WHERE songid="
1726
$sth = $lyricDbh->prepare($query)
1727
|| display_fatal($errorcodes->{'sqlprepare'},
1728
$! . "\nSQL: " . $query);
1729
debug("Page Edit : " . $pagenum . "|" . $title);
1730
$rv = $sth->execute || display_fatal($errorcodes->{'sqlexecute'},
1731
$! . "\nSQL: " . $query);
1732
my @row = $sth->fetchrow_array();
1733
if (defined $row[0]) {
1735
"UPDATE page SET lyrics="
1741
debug("Page Edit : " . $pagenum . "|" . $title);
1744
if ($pagequery eq "") {
1746
"INSERT INTO page (songid,pagenum,pagetitle,lyrics) VALUES ("
1751
debug("Page Add : " . $pagenum . "|" . $title);
1754
$sth = $lyricDbh->prepare($pagequery)
1755
|| display_fatal($errorcodes->{'sqlprepare'},
1756
$! . "\nSQL: " . $pagequery);
1757
$sth->execute || display_fatal($errorcodes->{'sqlexecute'},
1758
$! . "\nSQL: " . $pagequery);
1766
#****f* lyricue/save_song
1772
# Save the song, close the add window and update the available songs
1775
# Calls a few others to do anything
1787
#****f* lyricue/add_page
1796
# Adds a page to the song edit screen
1800
debug("Add page clicked");
1802
# Find free hash number
1804
while (exists $pageOrder{$hashnum}) {
1809
$widgets->{'add'}->get_widget('notebookEditPages')->get_current_page + 1;
1812
# Construct a GtkScrolledWindow 'scrollAPage'
1813
$widgets->{'scrollAPage'}{$hashnum} = Gtk2::ScrolledWindow->new;
1814
$widgets->{'scrollAPage'}{$hashnum}->set_policy('always', 'always');
1815
$widgets->{'scrollAPage'}{$hashnum}->show;
1818
# Construct a GtkText 'textAPage'
1819
$widgets->{'textAPage'}{$hashnum} = Gtk2::TextView->new;
1820
$widgets->{'textAPageB'}{$hashnum} = Gtk2::TextBuffer->new(undef);
1821
$widgets->{'textAPage'}{$hashnum}
1822
->set_buffer($widgets->{'textAPageB'}{$hashnum});
1823
$widgets->{'textAPage'}{$hashnum}->set_editable(TRUE);
1824
$widgets->{'textAPage'}{$hashnum}->set_cursor_visible(TRUE);
1825
$widgets->{'scrollAPage'}{$hashnum}->add($widgets->{'textAPage'}{$hashnum});
1826
$widgets->{'textAPage'}{$hashnum}->show;
1829
# Construct a GtkLabel 'labelAPage'
1830
$widgets->{'labelAPage'}{$hashnum} =
1831
new Gtk2::Label(fromutf(gettext('Page') . " 1"));
1832
$widgets->{'labelAPage'}{$hashnum}->set_justify('center');
1833
$widgets->{'labelAPage'}{$hashnum}->set_line_wrap(0);
1834
$widgets->{'labelAPage'}{$hashnum}->show;
1835
$widgets->{'labelAPage'}{$hashnum}->set_alignment(0.5, 0.5);
1837
# And a event box so you can change it
1838
$widgets->{'eventAPage'}{$hashnum} = Gtk2::EventBox->new;
1839
$widgets->{'eventAPage'}{$hashnum}->{user_data} = $hashnum;
1840
$widgets->{'eventAPage'}{$hashnum}->add($widgets->{'labelAPage'}{$hashnum});
1841
$widgets->{'eventAPage'}{$hashnum}->set_above_child(FALSE);
1842
$widgets->{'eventAPage'}{$hashnum}->set_visible_window(FALSE);
1843
$widgets->{'eventAPage'}{$hashnum}
1844
->signal_connect('button-press-event', 'update_pagename');
1846
$pageOrder{$hashnum} = $pagenum;
1847
$widgets->{'add'}->get_widget('notebookEditPages')
1848
->insert_page($widgets->{'scrollAPage'}{$hashnum},
1849
$widgets->{'eventAPage'}{$hashnum}, $pagenum);
1850
$widgets->{'add'}->get_widget('notebookEditPages')
1851
->set_tab_reorderable($widgets->{'scrollAPage'}{$hashnum}, TRUE);
1852
renumber_pages($pagenum, $hashnum);
1853
$widgets->{'add'}->get_widget('notebookEditPages')
1854
->set_current_page($pagenum);
1855
$widgets->{'add'}->get_widget('notebookEditPages')->show_all();
1856
$widgets->{'add'}->get_widget('buttonEditRemovePage')->set_sensitive(TRUE);
1857
$widgets->{'add'}->get_widget('remove_page1')->set_sensitive(TRUE);
1864
#****f* lyricue/update_pagename
1868
# update_pagename ()
1870
# Update the page name if double-clicked
1873
sub update_pagename {
1874
my ($widget, $event) = @_;
1875
if ($event->type eq '2button-press') {
1876
debug("Changing page name");
1877
my $hashnum = $widget->{user_data};
1878
my $entry = Gtk2::Entry->new;
1879
$entry->{user_data} = $hashnum;
1880
$entry->set_text($widgets->{'labelAPage'}{$hashnum}->get_label);
1881
$entry->signal_connect('activate', 'do_update_pagename');
1882
$widgets->{'add'}->get_widget('notebookEditPages')
1883
->set_tab_label($widgets->{'scrollAPage'}{$hashnum}, $entry);
1889
#****f* lyricue/do_update_pagename
1891
# do_update_pagename
1893
# do_update_pagename ()
1899
sub do_update_pagename {
1900
my ($widget, $event) = @_;
1901
debug("Apply pagename change");
1902
my $text = $widget->get_text;
1903
my $hashnum = $widget->{user_data};
1904
$widgets->{'labelAPage'}{$hashnum}->set_label($text);
1905
$widgets->{'add'}->get_widget('notebookEditPages')->set_tab_label(
1906
$widgets->{'scrollAPage'}{$hashnum},
1907
$widgets->{'eventAPage'}{$hashnum}
1913
#****f* lyricue/renumber_pages
1917
# renumber_pages ($pagenum, $newitem)
1919
# Re-number the pages in a edited song
1921
# $pagenum - The page number added/deleted
1922
# $newitem - The new item added
1924
# Re-ordered page list
1927
sub renumber_pages {
1928
my ($pagenum, $newitem) = @_;
1929
debug("renumber pages");
1933
foreach $i (keys(%pageOrder)) {
1934
debug("$i:$pageOrder{$i}|");
1935
my $page = $pageOrder{$i};
1936
if ($page == $pagenum) {
1937
if ($i == $newitem) {
1943
} elsif ($page > $pagenum) {
1946
debug("$i:$pageOrder{$i}");
1947
my $text = fromutf(gettext("Page"));
1948
if ($widgets->{'labelAPage'}{$i}->get_text =~ /^$text/) {
1949
$widgets->{'labelAPage'}{$i}
1950
->set_text($text . " " . $pageOrder{$i});
1952
$widgets->{'labelAPage'}{$i}->show();
1958
#****f* lyricue/remove_page
1964
# Remove a page from the song being edited
1971
debug("Remove page clicked");
1975
$widgets->{'add'}->get_widget('notebookEditPages')->get_current_page + 1;
1979
my $text = fromutf(gettext("Page "));
1980
foreach $i (keys(%pageOrder)) {
1982
debug("-$pagenum:$i:$pageOrder{$i}:");
1983
if ($pageOrder{$i} < $pagenum) {
1984
$newpageOrder{$i} = $pageOrder{$i};
1985
if ($widgets->{'labelAPage'}{$i}->get_text =~ /^$text/) {
1986
$widgets->{'labelAPage'}{$i}
1987
->set_text(fromutf(gettext("Page ")) . $newpageOrder{$i});
1989
debug("$newpageOrder{$i}");
1990
} elsif ($pageOrder{$i} == $pagenum) {
1991
$widgets->{'add'}->get_widget('notebookEditPages')
1992
->remove_page($pagenum - 1);
1994
} elsif ($pageOrder{$i} > $pagenum) {
1995
$newpageOrder{$i} = $pageOrder{$i} - 1;
1996
debug("$newpageOrder{$i}");
1997
if ($widgets->{'labelAPage'}{$i}->get_text =~ /^$text/) {
1998
$widgets->{'labelAPage'}{$i}
1999
->set_text(fromutf(gettext("Page ")) . $newpageOrder{$i});
2003
%pageOrder = %newpageOrder;
2005
$widgets->{'add'}->get_widget('buttonEditRemovePage')
2006
->set_sensitive(FALSE);
2007
$widgets->{'add'}->get_widget('remove_page1')->set_sensitive(FALSE);
2013
#****f* lyricue/close_add_window
2017
# close_add_window ()
2019
# Close the add window
2025
sub close_add_window {
2026
debug("Close add window");
2028
$widgets->{'add'}->get_widget('windowEditSong')->destroy();
2029
undef $widgets->{'add'};
2034
#****f* lyricue/close_dialog
2038
# close_dialog ($widget)
2040
# Close the calling widgets toplevel window
2042
# $widget - Calling widget
2049
debug("Close dialog: " . $widget->get_name);
2051
$widget->get_toplevel->destroy;
2057
#****f* lyricue/edit_song
2066
# Calls create_window_add to edit the chosen song
2071
debug("Edit clicked");
2073
$widgets->{'main'}->get_widget('treeAvailable')->get_selection;
2074
my @sel = $selection->get_selected_rows;
2075
my $model = $widgets->{'main'}->get_widget('treeAvailable')->get_model;
2076
my $iter = $model->get_iter($sel[0]);
2079
my $songid = $model->get($iter, 3);
2080
if ( $widgets->{'add'}
2081
&& $widgets->{'add'}->get_widget('windowEditSong'))
2083
if (!$widgets->{'add'}->get_widget('windowEditSong')->visible) {
2084
$widgets->{'add'}->get_widget('windowEditSong')->destroy;
2086
$widgets->{'add'} = Gtk2::GladeXML->new($globals->{'gladefile'},
2087
'windowEditSong', 'lyricue');
2088
$widgets->{'add'}->signal_autoconnect_from_package('');
2090
$widgets->{'add'}->get_widget('buttonEditPreviewServer')
2091
->signal_connect("clicked", "preview_page", "SERVER");
2093
update_songinfo($songid);
2096
$widgets->{'add'} = Gtk2::GladeXML->new($globals->{'gladefile'},
2097
'windowEditSong', 'lyricue');
2098
$widgets->{'add'}->signal_autoconnect_from_package('');
2099
$widgets->{'add'}->get_widget('buttonEditPreviewServer')
2100
->signal_connect("clicked", "preview_page", "SERVER");
2103
$widgets->{'add'}->get_widget('notebookEditPages')->remove_page(0);
2104
$widgets->{'add'}->get_widget('windowEditSong')->show();
2105
update_songinfo($songid);
2112
#****f* lyricue/do_add_verse
2116
# do_add_verse ($widget)
2118
# Add the chosen reading
2120
# $widget - Calling widget
2122
# Verse added to playlist
2127
debug("Add the chosen reading");
2129
debug($globals->{'verses'} . "-" . $globals->{'verseEnd'});
2131
my $book = $widget->get_toplevel->{user_data};
2132
$book =~ s/ -.*$//g;
2133
my $chapter = $widget->get_toplevel->{user_data};
2134
$chapter =~ s/^.*- //g;
2135
insert_verse($book, $chapter, $globals->{'verses'}, $globals->{'verseEnd'});
2136
close_dialog($widget);
2141
#****f* lyricue/insert_verse
2145
# insert_verse ( $book, $chapter, $start, $end)
2147
# Add the passed verse to the playlist
2151
# $start - Start verse
2154
# Closes the interface
2157
my ($book, $chapter, $start, $end) = @_;
2158
debug("insert verse");
2160
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
2161
if ($main_playlist == -1) {
2165
$book . ":" . $chapter . ":" . $start . "-" . $chapter . ":" . $end;
2168
my ($sth, $rv, $row, $playorder, $playlist);
2170
# Find next playlist entry
2171
my $query = "SELECT MAX(playorder) FROM playlist";
2173
$sth = $lyricDbh->prepare($query)
2174
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2176
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2178
if ($row = $sth->fetchrow_hashref()) {
2179
if ($row->{'MAX(playorder)'}) {
2180
$playorder = $row->{'MAX(playorder)'} + 1;
2188
# Find next playlists entry
2189
$query = "SELECT MAX(id) FROM playlists";
2191
$sth = $lyricDbh->prepare($query)
2192
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2194
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2195
$row = $sth->fetchrow_hashref();
2196
$playlist = $row->{'MAX(id)'} + 1;
2198
# Add verse to main playlist
2200
"INSERT INTO playlist (playorder,playlist,type,data) VALUES ("
2206
$sth = $lyricDbh->prepare($query)
2207
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2210
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2213
# Add entry to playlists table
2215
"INSERT INTO playlists (id,title) VALUES ("
2216
. $playlist . ", \""
2217
. toutf($verse) . "\")";
2219
$sth = $lyricDbh->prepare($query)
2220
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2223
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2225
# Get current settings
2226
update_display("status", "", "");
2232
my $maxv = get_max_verse($book, $chapter, $minv, $end);
2234
"INSERT INTO playlist (playlist,playorder,type,data) VALUES ("
2242
my $sth2 = $lyricDbh->prepare($query)
2243
|| display_fatal($errorcodes->{'sqlprepare'},
2244
$! . "\nSQL: " . $query);
2246
my $rv2 = $sth2->execute
2247
|| display_fatal($errorcodes->{'sqlexecute'},
2248
$! . "\nSQL: " . $query);
2249
if ($maxv >= $end) {
2260
#****f* lyricue/import_song
2266
# Import a song into the add song dialog
2269
# A dialog to open song to import
2273
debug("import song");
2274
my $filexml = Gtk2::GladeXML->new($globals->{'gladefile'},
2275
'dialogFileChooser', 'lyricue');
2276
$filexml->signal_autoconnect_from_package('');
2277
$filexml->get_widget('buttonFileOK')
2278
->signal_connect("clicked", "do_import_song", $filexml);
2279
$filexml->get_widget('dialogFileChooser')->show_all();
2284
#****f* lyricue/do_import_song
2288
# do_import_song ($widget, $filexml)
2290
# Actually import the song into the add song dialog
2292
# $widget - Calling widget
2293
# $filexml - Dialog containing selected filename
2295
# Filled in add song dialog
2298
sub do_import_song {
2299
my ($widget, $filexml) = @_;
2300
debug("do import song");
2301
my $filename = $filexml->get_widget('dialogFileChooser')->get_filename;
2302
my $lcfilename = lc($filename);
2304
if (($lcfilename =~ /xmlz$/) || ($lcfilename =~ /xml$/)) {
2305
import_song_xml($filename);
2306
} elsif ($lcfilename =~ /txt$/) {
2307
import_song_text($filename);
2308
} elsif ($lcfilename =~ /sng$/) {
2309
import_song_songbeamer($filename);
2310
} elsif ($lcfilename =~ /usr$/) {
2311
import_song_songselect($filename);
2312
} elsif ($lcfilename =~ /opw$/) {
2313
import_song_opw($filename);
2314
} elsif ($lcfilename =~ /html$/) {
2315
import_song_html($filename);
2318
close_dialog($widget);
2323
#****f* lyricue/import_song_text
2327
# import_song_text ()
2329
# Import a song which was stored as a text file
2331
# $filename - File to import
2333
# Closes the interface
2335
sub import_song_text {
2336
my ($filename) = @_;
2337
debug("import text song");
2339
my ($artist, $name, $keywords, $number, $book, $copyright) = "";
2341
open(SONG, $filename) || return;
2342
binmode SONG, ":encoding(utf8)";
2350
$widgets->{'add'}->get_widget('entryEditName')->set_text($name);
2352
} elsif (/^Book:/) {
2359
$widgets->{'add'}->get_widget('entryEditBook')->set_text($book);
2361
} elsif (/^Number:/) {
2366
$number =~ s/^.*://g;
2367
$number =~ s/^ *//g;
2368
$widgets->{'add'}->get_widget('entryEditNumber')
2369
->set_text($number);
2371
} elsif (/^Artist:/) {
2378
$widgets->{'add'}->get_widget('entryEditArtist')
2379
->set_text($artist);
2381
$artist = "\n" . $_;
2382
$widgets->{'add'}->get_widget('entryEditArtist')
2383
->append_text($artist);
2385
} elsif (/^Keywords:/) {
2390
$keywords =~ s/^.*://g;
2391
$keywords =~ s/^ *//g;
2392
$widgets->{'add'}->get_widget('entryEditKeywords')
2393
->set_text($keywords);
2395
} elsif (/^Copyright/) {
2400
$copyright =~ s/^.*://g;
2401
$copyright =~ s/^ *//g;
2402
$widgets->{'add'}->get_widget('entryEditCopyright')
2403
->set_text($copyright);
2407
$hashnum = add_page();
2410
my $iter = $widgets->{'textAPageB'}{$hashnum}->get_end_iter();
2411
$widgets->{'textAPageB'}{$hashnum}->insert($iter, $_);
2419
#****f* lyricue/import_song_xml
2423
# import_song_xml ($filename)
2425
# Import a song which was stored as an xml file
2427
# $filename - File to import
2429
# Closes the interface
2431
sub import_song_xml {
2432
my ($filename) = @_;
2433
debug("import xml song");
2436
if ($filename =~ /[zZ]$/) {
2437
open my $fh, "gzip -dc \"" . $filename . "\" |";
2438
$xml = XMLin($fh, ForceArray => ['page'], SuppressEmpty => '');
2441
$xml = XMLin($filename, ForceArray => ['page'], SuppressEmpty => '');
2443
$widgets->{'add'}->get_widget('entryEditName')
2444
->set_text($xml->{'song'}->{'name'});
2445
$widgets->{'add'}->get_widget('entryEditBook')
2446
->set_text($xml->{'song'}->{'book'});
2447
$widgets->{'add'}->get_widget('entryEditNumber')
2448
->set_text($xml->{'song'}->{'number'});
2449
$widgets->{'add'}->get_widget('entryEditArtist')
2450
->set_text($xml->{'song'}->{'artist'});
2451
$widgets->{'add'}->get_widget('entryEditKeywords')
2452
->set_text($xml->{'song'}->{'keywords'});
2453
$widgets->{'add'}->get_widget('entryEditCopyright')
2454
->set_text($xml->{'song'}->{'copyright'});
2455
my $pages = $xml->{'song'}->{'page'};
2456
my $firstpage = TRUE;
2462
$widgets->{'textAPageB'}{0}->set_text($_);
2464
my $hashnum = add_page();
2465
$widgets->{'textAPageB'}{$hashnum}->set_text($_);
2472
#****f* lyricue/import_song_songbeamer
2474
# import_song_songbeamer
2476
# import_song_songbeamer ($filename)
2478
# Import a song from Songbeamer format
2480
# $filename - Filename of .sng file to import
2482
# Filled in add song dialog
2485
sub import_song_songbeamer {
2486
my ($filename) = @_;
2487
debug("import songbeamer song");
2489
my ($artist, $name, $number, $book, $copyright, $firstpage) = "";
2491
open(SONG, $filename) || return;
2497
$name =~ s/^#.*=//g;
2500
$widgets->{'add'}->get_widget('entryEditName')->set_text($name);
2502
} elsif (/^#Songbook=/) {
2507
$book =~ s/^#.*=//g;
2509
$book =~ s/\/.*$//g;
2511
$widgets->{'add'}->get_widget('entryEditBook')->set_text($book);
2516
$number =~ s/^#.*=[^\/]*\///g;
2517
$number =~ s/^ *//g;
2519
$widgets->{'add'}->get_widget('entryEditNumber')
2520
->set_text($number);
2522
} elsif (/^#Author=/) {
2530
$widgets->{'add'}->get_widget('entryEditArtist')
2531
->set_text($artist);
2533
$artist = ", " . $_;
2534
$widgets->{'add'}->get_widget('entryEditArtist')
2535
->append_text($artist);
2537
} elsif (/^#Melody=/) {
2545
$widgets->{'add'}->get_widget('entryEditArtist')
2546
->set_text($artist);
2548
$artist = ", " . $_;
2549
$widgets->{'add'}->get_widget('entryEditArtist')
2550
->append_text($artist);
2552
} elsif (/^#\(c\)=/) {
2557
$copyright =~ s/^#.*=//g;
2558
$copyright =~ s/^ *//g;
2559
$copyright =~ s/\r//g;
2560
$widgets->{'add'}->get_widget('entryEditCopyright')
2561
->set_text($copyright);
2563
} elsif (/^#/) { # many functions in SongBeamer are unknown to Lyricue
2564
debug("unknown operator");
2566
if ($firstpage) { #no new page in the first run
2568
$hashnum = add_page();
2574
my $iter = $widgets->{'textAPageB'}{$hashnum}->get_end_iter();
2575
$widgets->{'textAPageB'}{$hashnum}->insert($iter, $_);
2583
#****f* lyricue/update_songinfo
2587
# update_songinfo ($songid)
2589
# Fill in the add song dialog with the chosen songs details/lyrics
2591
# $songid - Id of song to edit
2593
# Filled in add song dialog
2596
sub update_songinfo {
2598
debug("Edit clicked");
2599
my ($sth, $query, $hashnum);
2602
$widgets->{'add'}->get_widget('windowEditSong')->{user_data} = $songid;
2604
"SELECT lyrics,pagetitle FROM page WHERE songid=\""
2606
. "\" ORDER BY pagenum";
2608
$sth = $lyricDbh->prepare($query)
2609
|| display_fatal($errorcodes->{'sqlprepare'},
2610
$! . "\nSQL: " . $query);
2612
|| display_fatal($errorcodes->{'sqlexecute'},
2613
$! . "\nSQL: " . $query);
2615
while ($row = $sth->fetchrow_hashref()) {
2616
$hashnum = add_page();
2617
$widgets->{'textAPageB'}{$hashnum}
2618
->set_text(fromutf($row->{'lyrics'}));
2619
if ($row->{'pagetitle'} ne "") {
2620
$widgets->{'labelAPage'}{$hashnum}
2621
->set_text(fromutf($row->{'pagetitle'}));
2626
"SELECT title,songnum,book,artist,keywords,copyright from lyricMain WHERE id="
2629
$sth = $lyricDbh->prepare($query)
2630
|| display_fatal($errorcodes->{'sqlprepare'},
2631
$! . "\nSQL: " . $query);
2633
|| display_fatal($errorcodes->{'sqlexecute'},
2634
$! . "\nSQL: " . $query);
2635
if ($row = $sth->fetchrow_hashref()) {
2636
$widgets->{'add'}->get_widget('entryEditName')
2637
->set_text(fromutf($row->{'title'}));
2638
$widgets->{'add'}->get_widget('entryEditBook')
2639
->set_text(fromutf($row->{'book'}));
2640
$widgets->{'add'}->get_widget('entryEditNumber')
2641
->set_text(fromutf($row->{'songnum'}));
2642
$widgets->{'add'}->get_widget('entryEditArtist')
2643
->set_text(fromutf($row->{'artist'}));
2644
if ($row->{'keywords'} =~ /^NOAUDIT /) {
2645
$row->{'keywords'} =~ s/^NOAUDIT //g;
2646
$widgets->{'add'}->get_widget('checkEditAudit')
2647
->set_active(FALSE);
2649
$widgets->{'add'}->get_widget('checkEditAudit')
2652
$widgets->{'add'}->get_widget('entryEditKeywords')
2653
->set_text(fromutf($row->{'keywords'}));
2654
$widgets->{'add'}->get_widget('entryEditCopyright')
2655
->set_text(fromutf($row->{'copyright'}));
2657
$widgets->{'add'}->get_widget('notebookEditPages')->set_current_page(0);
2663
#****f* lyricue/add_to_playlist
2667
# add_to_playlist ()
2669
# Add the chosen songs to the playlist
2671
# More songs in the playlist
2674
sub add_to_playlist {
2675
debug("Add to playlist clicked");
2677
$widgets->{'main'}->get_widget('treeAvailable')->get_selection;
2678
my $model = $widgets->{'main'}->get_widget('treeAvailable')->get_model;
2679
my @sel = $selection->get_selected_rows;
2680
foreach my $path (@sel) {
2681
add_single_song($model->get($model->get_iter($path), 3));
2689
#****f* lyricue/add_single_song
2693
# add_single_song ($availableSelection)
2695
# Add a single song to the playlist
2696
# Optionally audit this addition
2698
# $availableSelection - Song id to add to the playlist
2700
# One more song in the playlist
2703
sub add_single_song {
2704
my ($availableSelection) = @_;
2705
debug("add single song");
2707
# Drop out if no playlist selected
2708
if ($widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data} ==
2715
my $query = "SELECT MAX(playorder) FROM playlist";
2716
$sth = $lyricDbh->prepare($query)
2717
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2719
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2720
if ($row = $sth->fetchrow_hashref()) {
2721
if ($row->{'MAX(playorder)'}) {
2722
$playorder = $row->{'MAX(playorder)'} + 1;
2730
# Find next playlists entry
2731
$query = "SELECT MAX(id) FROM playlists";
2733
$sth = $lyricDbh->prepare($query)
2734
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2736
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2737
$row = $sth->fetchrow_hashref();
2738
my $playlist = $row->{'MAX(id)'} + 1;
2741
"INSERT INTO playlist (playorder, playlist, data,type) VALUES ("
2743
. $widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data}
2748
$sth = $lyricDbh->prepare($query)
2749
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2751
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2756
"SELECT title,pageid,keywords FROM lyricMain, page WHERE songid=id AND id="
2757
. $availableSelection
2758
. " ORDER BY pagenum";
2760
$sth = $lyricDbh->prepare($query)
2761
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2763
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2765
while ($row = $sth->fetchrow_hashref()) {
2768
my $keywords = $row->{'keywords'};
2769
if ($keywords =~ /^NOAUDIT /) {
2772
$title = $row->{'title'};
2775
"INSERT INTO playlist (playorder, playlist, data,type) VALUES ("
2781
my $sth2 = $lyricDbh->prepare($query2)
2782
|| display_fatal($errorcodes->{'sqlprepare'},
2783
$! . "\nSQL: " . $query2);
2784
my $rv2 = $sth2->execute
2785
|| display_fatal($errorcodes->{'sqlexecute'},
2786
$! . "\nSQL: " . $query2);
2789
# Add playlists entry
2791
"INSERT INTO playlists (id,title,ref) VALUES ("
2794
. $availableSelection . ")";
2795
$sth = $lyricDbh->prepare($query)
2796
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2798
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2800
# audit this addition
2801
# currently always runs due to problem with passing in widgets
2802
debug("Audit: $config->{'Audit'}");
2803
if ($config->{'Audit'} && $audit) {
2804
$query = "SELECT MAX(id)+1 FROM audit";
2806
$sth = $lyricDbh->prepare($query)
2807
|| display_fatal($errorcodes->{'sqlprepare'},
2808
$! . "\nSQL: " . $query);
2810
|| display_fatal($errorcodes->{'sqlexecute'},
2811
$! . "\nSQL: " . $query);
2812
my @row = $sth->fetchrow_array;
2813
if (!defined $row[0]) {
2817
"INSERT INTO audit (id,songid,playdate) VALUES("
2819
. $availableSelection
2821
debug("Auditing with: " . $query);
2822
$sth = $lyricDbh->prepare($query)
2823
|| display_fatal($errorcodes->{'sqlprepare'},
2824
$! . "\nSQL: " . $query);
2826
|| display_fatal($errorcodes->{'sqlexecute'},
2827
$! . "\nSQL: " . $query);
2833
#****f* lyricue/remove_from_playlist
2835
# remove_from_playlist
2837
# remove_from_playlist ()
2839
# Remove selected songs from the playlist
2841
# Less songs in the playlist
2844
sub remove_from_playlist {
2845
debug("remove from playlist");
2847
#Cancel any loop timers
2848
#Continuing to loop over possibly removed playlist
2849
#items represents a major crash risk - better safe
2852
reset_timer($globals->{'timer'});
2855
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
2856
debug("Remove from playlist clicked");
2857
my ($model, $iter) = $selection->get_selected;
2859
remove_single_item($model->get($iter, 2));
2866
#****f* lyricue/remove_single_item
2868
# remove_single_item
2870
# remove_single_item ($item)
2872
# Remove a single song from the playlist
2874
# $item - Playlist Id to remove
2876
# One less song on the playlist
2879
sub remove_single_item {
2881
debug("Deleting $item from playlist");
2882
reset_timer($globals->{'timer'});
2883
my $query = "SELECT type,data FROM playlist WHERE playorder=" . $item;
2885
my $sth = $lyricDbh->prepare($query)
2886
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2887
my $rv = $sth->execute
2888
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2889
my @row = $sth->fetchrow_array;
2891
if ($row[0] eq "play" | $row[0] eq "sub") {
2892
$query = "SELECT playorder FROM playlist WHERE playlist=" . $row[1];
2894
$sth = $lyricDbh->prepare($query)
2895
|| display_fatal($errorcodes->{'sqlprepare'},
2896
$! . "\nSQL: " . $query);
2898
|| display_fatal($errorcodes->{'sqlexecute'},
2899
$! . "\nSQL: " . $query);
2900
while (my @row2 = $sth->fetchrow_array) {
2901
remove_single_item($row2[0]);
2904
$query = "DELETE FROM playlist WHERE playlist=" . $row[1];
2906
$sth = $lyricDbh->prepare($query)
2907
|| display_fatal($errorcodes->{'sqlprepare'},
2908
$! . "\nSQL: " . $query);
2910
|| display_fatal($errorcodes->{'sqlexecute'},
2911
$! . "\nSQL: " . $query);
2913
$query = "DELETE FROM playlists WHERE id=" . $row[1];
2915
$sth = $lyricDbh->prepare($query)
2916
|| display_fatal($errorcodes->{'sqlprepare'},
2917
$! . "\nSQL: " . $query);
2919
|| display_fatal($errorcodes->{'sqlexecute'},
2920
$! . "\nSQL: " . $query);
2923
$query = "DELETE FROM playlist WHERE playorder=" . $item;
2925
$sth = $lyricDbh->prepare($query)
2926
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2928
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2930
$query = "DELETE FROM associations WHERE playlist=" . $item;
2932
$sth = $lyricDbh->prepare($query)
2933
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
2935
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
2937
if (($row[0] eq "file") && ($row[1] =~ /^\/var\/tmp\/lyricue-/)) {
2939
# Removing temporary file
2940
my $command = "rm " . $row[1];
2942
$dir =~ s/^(\/var\/tmp\/lyricue-.*\/).*$/$1/g;
2944
# Check if used elsewhere
2946
"SELECT playorder FROM playlist WHERE data=\"" . $row[1] . "\"";
2948
$sth = $lyricDbh->prepare($query)
2949
|| display_fatal($errorcodes->{'sqlprepare'},
2950
$! . "\nSQL: " . $query);
2952
|| display_fatal($errorcodes->{'sqlexecute'},
2953
$! . "\nSQL: " . $query);
2954
if (@row = $sth->fetchrow_array) {
2955
debug("Temporary file used elsewhere - not removing");
2961
# Check if directory empty
2962
my $ret = opendir DIR, $dir;
2965
foreach (sort readdir(DIR)) {
2971
debug("Empty directory - removing");
2972
$command = "rmdir " . $dir;
2982
#****f* lyricue/clear_playlist
2986
# clear_playlist ($widget)
2988
# Clear the playlist
2990
# $widget - Calling widget
2992
# No songs in playlist
2995
sub clear_playlist {
2997
debug("Clear playlist");
2998
reset_timer($globals->{'timer'});
3000
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogConfirm', 'lyricue');
3001
$deletexml->signal_autoconnect_from_package('');
3003
fromutf(gettext("Are you sure you wish to clear the current playlist?"));
3004
$deletexml->get_widget('labelDelete')->set_text($labelText);
3005
$deletexml->get_widget('dialogConfirm')
3006
->set_title(fromutf(gettext("Confirm Clear Playlist")));
3007
my $confirm = $deletexml->get_widget('dialogConfirm')->run();
3009
if ($confirm eq "ok") {
3011
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
3014
"SELECT playorder FROM playlist WHERE playlist=" . $main_playlist;
3015
$sth = $lyricDbh->prepare($query)
3016
|| display_fatal($errorcodes->{'sqlprepare'},
3017
$! . "\nSQL: " . $query);
3019
|| display_fatal($errorcodes->{'sqlexecute'},
3020
$! . "\nSQL: " . $query);
3021
while (my @row = $sth->fetchrow_array()) {
3022
remove_single_item($row[0]);
3026
close_dialog($deletexml->get_widget('dialogConfirm'));
3031
#****f* lyricue/display_song
3035
# display_song (undef, $event)
3037
# Display a song if double-clicked, or popup menu if right-clicked
3039
# $event - Calling event
3041
# Updated display or right-click menu is popped-up
3045
my ($widget, $path,, $column) = @_;
3046
debug("display song");
3047
reset_timer($globals->{'timer'});
3049
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
3050
my ($model, $iter) = $selection->get_selected;
3052
update_display("display", $model->get($iter, 2), "");
3057
sub treePlaylist_cursor_changed {
3059
debug("preview playlist item");
3061
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
3062
my ($model, $iter) = $selection->get_selected;
3064
my $transition = $model->get($iter, 3);
3066
# Set the transition values
3067
my $out_direction = mod($transition, 2**NUM_TRANS);
3068
$transition = $transition >> NUM_TRANS;
3069
my $in_direction = mod($transition, 2**NUM_TRANS);
3070
my $effect = $transition >> NUM_TRANS;
3071
if ($effect == NOTRANS ) {
3072
$widgets->{'main'}->get_widget('radioTransNone')->set_active(TRUE);
3073
} elsif ($effect == FADE) {
3074
$widgets->{'main'}->get_widget('radioTransFade')->set_active(TRUE);
3075
} elsif ($effect == SLIDE_TEXT) {
3076
$widgets->{'main'}->get_widget('radioTransSlide')->set_active(TRUE);
3077
} elsif ($effect == ROTATE_TEXT) {
3078
$widgets->{'main'}->get_widget('radioTransRotate')
3081
$widgets->{'main'}->get_widget('radioTransDefault')->set_active(TRUE);
3084
if ($in_direction & UP) { $indir .= "Up" }
3085
if ($in_direction & DOWN) { $indir .= "Down" }
3086
if ($in_direction & LEFT) { $indir .= "Left" }
3087
if ($in_direction & RIGHT) { $indir .= "Right" }
3088
if ($indir eq "") { $indir = "None" }
3089
$widgets->{'main'}->get_widget("toggleIn" . $indir)->set_active(TRUE);
3090
$widgets->{'main'}->get_widget("toggleRotX")
3091
->set_active($in_direction & X_AXIS);
3092
$widgets->{'main'}->get_widget("toggleRotY")
3093
->set_active($in_direction & Y_AXIS);
3094
$widgets->{'main'}->get_widget("toggleRotZ")
3095
->set_active($in_direction & Z_AXIS);
3098
if ($out_direction & UP) { $outdir .= "Up" }
3099
if ($out_direction & DOWN) { $outdir .= "Down" }
3100
if ($out_direction & LEFT) { $outdir .= "Left" }
3101
if ($out_direction & RIGHT) { $outdir .= "Right" }
3102
if ($outdir eq "") { $outdir = "None" }
3103
$widgets->{'main'}->get_widget("toggleOut" . $outdir)->set_active(TRUE);
3106
if ($config->{'DynamicPreview'}) {
3107
preview_playlist_item();
3111
sub on_treePlaylist_button_press_event {
3112
my ($widget, $event) = @_;
3115
if ($event->button == 3) {
3116
popup_play_menu($event);
3124
#****f* lyricue/display_now
3128
# display_now ($widget)
3130
# Display now button clicked
3132
# $widget - Calling widget
3134
# Display updated with currently selected song
3139
debug("Display clicked");
3141
reset_timer($globals->{'timer'});
3144
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
3145
my ($model, $iter) = $selection->get_selected;
3147
update_display("display", $model->get($iter, 2), "");
3153
#****f* lyricue/prev_page
3159
# Display the previous page in the server
3163
# Calls update_display
3167
debug("Prev clicked");
3168
reset_timer($globals->{'timer'});
3169
update_display("display", "prev_page", $config->{'LoopText'});
3174
#****f* lyricue/next_page
3180
# Display the next page in the server
3184
# Calls update_display
3188
debug("Next clicked");
3189
reset_timer($globals->{'timer'});
3190
update_display("display", "next_page", $config->{'LoopText'});
3195
#****f* lyricue/prev_song
3201
# Display the previous song in the server
3205
# Calls update_display
3209
debug("Prev clicked");
3210
reset_timer($globals->{'timer'});
3211
update_display("display", "prev_song", $config->{'LoopText'});
3216
#****f* lyricue/next_song
3222
# Display the next song in the server
3226
# Calls update_display
3230
debug("Next clicked");
3231
reset_timer($globals->{'timer'});
3232
update_display("display", "next_song", $config->{'LoopText'});
3237
#****f* lyricue/blank_page
3247
# Calls update_display
3252
if ($globals->{'ignore_blank'}) {
3253
debug("ignore blank");
3254
$globals->{'ignore_blank'} = FALSE;
3257
debug("Blank page clicked");
3258
reset_timer($globals->{'timer'});
3259
update_display("blank", $config->{'BGImage'}, "");
3264
#****f* lyricue/clear_text
3270
# Clear the server text
3274
# Calls update_display
3279
if ($globals->{'ignore_clear'}) {
3280
$globals->{'ignore_clear'} = FALSE;
3281
debug("ignore clear");
3284
debug("Clear text clicked");
3285
reset_timer($globals->{'timer'});
3286
update_display("blank", "", "");
3291
#****f* lyricue/next_point
3297
# Display the next point in the server
3301
# Calls update_display
3305
debug("Next point clicked");
3306
reset_timer($globals->{'timer'});
3307
update_display("next_point", "", "");
3312
#****f* lyricue/preview_page
3316
# preview_page ($widget)
3318
# Preview a page in the server
3320
# $widget - Calling widget
3322
# Calls update_display
3326
my ($widget, $type) = @_;
3327
debug("preview page $type");
3328
reset_timer($globals->{'timer'});
3331
$widgets->{'add'}->get_widget('notebookEditPages')->get_current_page() +
3333
my $current_hash = 1;
3334
debug($current_page . " page ");
3335
my $label = $widgets->{'labelAPage'};
3336
foreach (keys %$label) {
3337
if ($widgets->{'labelAPage'}{$_}->get_text() eq
3338
fromutf(gettext("Page ")) . $current_page)
3343
debug($current_hash . " hash");
3345
#join all the strings together so update display will accept them, removing
3346
#any newlines or semicolons that would upset the split on the other end.
3348
$widgets->{'add'}->get_widget('entryEditName')->get_text()
3350
. $widgets->{'add'}->get_widget('entryEditArtist')->get_text()
3352
. $widgets->{'add'}->get_widget('entryEditCopyright')->get_text()
3354
$titledata =~ s/:/#SEMI#/g;
3355
my $songtext = get_buffer_text($widgets->{'textAPageB'}{$current_hash});
3356
$songtext =~ s/\n/#BREAK#/g;
3357
$songtext =~ s/:/#SEMI#/g;
3358
if ($type eq "SERVER") {
3359
update_display("preview", $titledata, $songtext);
3361
preview_display("preview", $titledata, $songtext, "EDIT");
3367
#****f* lyricue/preview_pageid
3371
# preview_pageid ($pageid)
3373
# Preview a pageid in the server
3375
# $widget - Calling widget
3377
# Calls update_display
3380
sub preview_pageid {
3382
debug("preview pageid");
3383
reset_timer($globals->{'timer'});
3385
my $query = "SELECT lyrics, pagetitle FROM page WHERE pageid=" . $pageid;
3387
$sth = $lyricDbh->prepare($query)
3388
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
3390
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
3391
$row = $sth->fetchrow_hashref();
3394
#join all the strings together so update display will accept them, removing
3395
#any newlines or semicolons that would upset the split on the other end.
3396
my $songtext = ($row->{'lyrics'});
3397
my $pagetitle = ($row->{'pagetitle'});
3398
$songtext =~ s/\n/#BREAK#/g;
3399
$songtext =~ s/:/#SEMI#/g;
3400
$pagetitle =~ s/\n/#BREAK#/g;
3401
$pagetitle =~ s/:/#SEMI#/g;
3403
preview_display("preview", $pagetitle, $songtext, "MINI");
3409
#****f* lyricue/add_verse
3413
# add_verse ($widget)
3417
# $widget - Calling widget
3419
# Calls create_dialogBook
3423
debug("Add verse clicked");
3425
if ((!defined $globals->{'bibledb'}) || ($globals->{'bibledb'} eq "")) {
3426
display_message($errorcodes->{'nobible'});
3429
Gtk2::GladeXML->new($globals->{'gladefile'}, 'windowBook', 'lyricue');
3430
$bookxml->signal_autoconnect_from_package('');
3431
$bookxml->get_widget('windowBook')->show;
3437
#****f* lyricue/add_image_pl
3443
# Add an image to the playlist
3446
# New item on playlist
3450
debug("Add image to playlist clicked");
3451
my $widget = $widgets->{'main'}->get_widget('iconviewImage');
3453
my @list = $widget->get_selected_items;
3454
if (defined $list[0]) {
3455
my $model = $widget->get_model;
3456
my $iter = $model->get_iter($list[0]);
3457
$selected = $model->get($iter, 2);
3459
if ($selected ne "") {
3461
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
3462
if ($playlist != -1) {
3463
add_image_item($playlist, $selected);
3471
#****f* lyricue/add_image
3477
# Load the image dialog
3480
# dialogImage loaded
3484
debug("Add image clicked");
3486
$widgets->{'image'} =
3487
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogImage', 'lyricue');
3488
$widgets->{'image'}->signal_autoconnect_from_package('');
3489
$widgets->{'image'}->get_widget('buttonImageAdd')
3490
->signal_connect('clicked', 'import_image');
3491
$widgets->{'image'}->get_widget('dialogImage')->show;
3493
if ($widgets->{'image'}->get_widget('treeImage')->{user_data}
3494
&& ($widgets->{'image'}->get_widget('treeImage')->{user_data} eq "load")
3497
$widgets->{'image'}->get_widget('treeImage')->{data} = ();
3499
$widgets->{'image'}->get_widget('treeImage')->{user_data} = "load";
3500
my $renderer = Gtk2::CellRendererText->new;
3501
$renderer->set("editable", TRUE);
3502
$renderer->signal_connect("edited", "rename_media");
3504
Gtk2::TreeViewColumn->new_with_attributes("Filename", $renderer,
3506
$widgets->{'image'}->get_widget('treeImage')->append_column($column);
3507
$widgets->{'image'}->get_widget('treeImage')
3508
->get_selection->set_mode('multiple');
3509
$widgets->{'image'}->get_widget('buttonImageOK')
3510
->signal_connect('clicked', "do_add_image");
3513
# Fill sublists dropbox
3514
my $menu = Gtk2::Menu->new();
3515
$widgets->{'image'}->get_widget('optionImageSublist')->set_menu($menu);
3517
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
3519
"SELECT title, data FROM playlist, playlists WHERE playlist.data = playlists.id AND playlist = "
3521
. " AND type = 'sub'";
3523
my $sth = $lyricDbh->prepare($query)
3524
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
3525
my $rv = $sth->execute
3526
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
3527
my $item = Gtk2::MenuItem->new_with_label("Main");
3528
$item->{'user_data'} = $playlist;
3530
$menu->append($item);
3533
while ($row = $sth->fetchrow_hashref()) {
3534
my $item = Gtk2::MenuItem->new_with_label($row->{'title'});
3535
$item->{'user_data'} = $row->{'data'};
3537
$menu->append($item);
3538
my @childid = find_more_children($row->{'data'});
3539
foreach (@childid) {
3540
debug("Child sublist found. ID: " . $_);
3541
my $query2 = "SELECT title FROM playlists WHERE id=" . $_;
3543
my $sth2 = $lyricDbh->prepare($query2)
3544
|| display_fatal($errorcodes->{'sqlprepare'},
3545
$! . "\nSQL: " . $query2);
3546
my $rv2 = $sth2->execute
3547
|| display_fatal($errorcodes->{'sqlexecute'},
3548
$! . "\nSQL: " . $query2);
3549
my $row2 = $sth2->fetchrow_hashref();
3550
my $item = Gtk2::MenuItem->new_with_label($row2->{'title'});
3551
$item->{'user_data'} = $row2->{'data'};
3553
$menu->append($item);
3556
$widgets->{'image'}->get_widget('optionImageSublist')->set_history(0);
3558
update_imagedir("img", "");
3563
#****f* lyricue/update_imagedir
3567
# update_imagedir($type, $data)
3569
# Update the view of an category
3571
# $type - 'img' or 'bg'
3572
# $data - Category/type to load
3574
# Updated list of images
3577
sub update_imagedir {
3578
my ($type, $data) = @_;
3579
my ($access, $category);
3580
debug("update image directory");
3582
if ($type eq "bg") {
3583
$main = $config->{'SpecialBack'};
3585
$main = $config->{'SpecialImage'};
3590
($access, $category) = split /;/, $data;
3591
if (!defined $category) {
3592
$category = $access;
3596
debug("changing to $access;$category");
3598
# display sorted list
3600
# Update categories list
3601
$widgets->{'image'}->get_widget('optionImageCategory')->{'user_data'} =
3603
$widgets->{'image'}->get_widget('treeImage')->{'user_data'} = $data;
3605
$widgets->{'image'}->get_widget('optionImageCategory')->get_history();
3606
my $menu = Gtk2::Menu->new();
3607
$widgets->{'image'}->get_widget('optionImageCategory')->set_menu($menu);
3608
my $item = Gtk2::MenuItem->new_with_label($main);
3610
$item->{user_data} = $main;
3611
$menu->append($item);
3614
"SELECT DISTINCT category FROM media WHERE type=\""
3616
. "\" AND category != \""
3618
. "\" ORDER BY category";
3620
$sth = $mediaDbh->prepare($query)
3621
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
3623
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
3625
while ($row = $sth->fetchrow_hashref()) {
3626
my $item = Gtk2::MenuItem->new_with_label($row->{'category'});
3627
$item->{user_data} = "db;" . $row->{'category'};
3629
$menu->append($item);
3633
# Add categories from directories
3635
if ($type eq "bg") {
3636
$dirname = $config->{'BGDirectory'};
3638
$dirname = $config->{'ImageDirectory'};
3641
my $ret = opendir DIR, $dirname;
3643
foreach $file (sort readdir(DIR)) {
3644
if (!($file =~ /^\./) && (-d $dirname . "/" . $file)) {
3645
my $item = Gtk2::MenuItem->new_with_label($file);
3646
$item->{user_data} = "dir;" . $file;
3648
$menu->append($item);
3654
$widgets->{'image'}->get_widget('optionImageCategory')
3655
->set_history($history);
3656
my $store = Gtk2::ListStore->new('Glib::String', 'Glib::String');
3659
if ($access eq "dir") {
3661
if ($type eq "bg") {
3662
$dirname = $config->{'BGDirectory'} . "/" . $category;
3664
$dirname = $config->{'ImageDirectory'} . "/" . $category;
3666
my $ret = opendir DIR, $dirname;
3669
foreach $file (sort readdir(DIR)) {
3670
if (!($file =~ /^\./)) {
3671
$iter = $store->append;
3672
$store->set($iter, 0, $file, 1,
3673
"dir;" . $dirname . "/" . $file);
3679
if ($access eq "db") {
3681
# update list of available images
3683
"SELECT * FROM media WHERE category LIKE \""
3687
. "\" ORDER BY description";
3689
$sth = $mediaDbh->prepare($query)
3690
|| display_fatal($errorcodes->{'sqlprepare'},
3691
$! . "\nSQL: " . $query);
3693
|| display_fatal($errorcodes->{'sqlexecute'},
3694
$! . "\nSQL: " . $query);
3695
while ($row = $sth->fetchrow_hashref()) {
3696
$iter = $store->append;
3697
$store->set($iter, 0, $row->{'description'}, 1,
3698
"db;" . $row->{'id'});
3701
$widgets->{'image'}->get_widget('treeImage')->set_model($store);
3702
$widgets->{'image'}->get_widget('entryImageFontColour')
3703
->set_text("Default");
3704
$widgets->{'image'}->get_widget('colorbuttonFontColour')
3705
->set_color(Gtk2::Gdk::Color->parse($config->{'Colour'}));
3706
$widgets->{'image'}->get_widget('entryImageShadowColour')
3707
->set_text("Default");
3708
$widgets->{'image'}->get_widget('colorbuttonShadowColour')
3709
->set_color(Gtk2::Gdk::Color->parse($config->{'ShadowColour'}));
3714
#****f* lyricue/change_image_category
3716
# change_image_category
3718
# change_image_category()
3720
# change image category
3725
sub change_image_category {
3726
debug("change image category");
3728
$widgets->{'image'}->get_widget('optionImageCategory')
3729
->get_menu->get_active->{user_data};
3730
if (defined $category) {
3731
if ($widgets->{'image'}->get_widget('treeImage')->{user_data} ne
3735
$widgets->{'image'}->get_widget('optionImageCategory')
3745
#****f* lyricue/update_display
3749
# update_display ($command, $primary, $secondary)
3751
# Open a connection the the server and send a command. Status is returned
3753
# $command - Command to send
3754
# $primary - First parameter to send
3755
# $secondary - Second parameter to send
3760
sub update_display {
3761
my ($command, $primary, $secondary) = @_;
3762
debug("update display");
3763
my $biblechanged = "";
3765
if ($globals->{'access'} !~ /s/) {
3772
if (!defined($secondary)) {
3775
if (!defined($primary)) {
3778
$primary =~ s/:/#SEMI#/g;
3779
$secondary =~ s/:/#SEMI#/g;
3780
debug("Command: " . $command . ":" . $primary . ":" . $secondary);
3782
my $server = IO::Socket::INET->new(
3784
PeerAddr => $globals->{'host'},
3785
PeerPort => $globals->{'server_port'}
3790
#binmode $server, ":utf8";
3791
print $server toutf(
3792
$command . ":" . $primary . ":" . $secondary . "\n");
3793
if (defined(my $status = <$server>)) {
3794
$status = fromutf($status);
3796
if ($status =~ /^pl:/) {
3797
my @line = split(/:/, $status);
3798
$status = fromutf(gettext("Displaying "));
3799
if ($line[1] eq "v") {
3800
$status = fromutf(gettext(" verses "));
3802
$status = fromutf(gettext(" page ")) . $line[3];
3803
$widgets->{'main'}->get_widget('treePlaylist')
3804
->select_item($line[2]);
3806
$widgets->{'main'}->get_widget('statusPlaylist')
3808
} elsif ($status =~ /^Status,/) {
3809
my @line = split(/,/, $status);
3811
my @item = split(/:/, $_);
3812
if ($item[0] eq "W") {
3813
$config->{'Width'} = $item[1];
3814
} elsif ($item[0] eq "H") {
3815
$config->{'Height'} = $item[1];
3816
} elsif ($item[0] eq "F") {
3817
$config->{'Main'} = $item[1];
3818
} elsif ($item[0] eq "B") {
3819
if ($item[1] ne $globals->{'biblename'}) {
3820
$biblechanged = $item[1];
3825
$widgets->{'main'}->get_widget('statusPlaylist')
3832
if ($biblechanged ne "") {
3833
if (defined $bibleMenu->{$biblechanged}) {
3834
$bibleMenu->{$biblechanged}->set_active(TRUE);
3842
#****f* lyricue/preview_playlist_item
3844
# preview_playlist_item
3846
# preview_playlist_item()
3848
# Preview a playlist item
3855
sub preview_playlist_item {
3856
debug("Previewing a playlist item...");
3859
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
3860
my ($model, $iter) = $selection->get_selected;
3863
preview_display("display", $model->get($iter, 2), undef, "MINI");
3869
#****f* lyricue/preview_display
3873
# preview_display ()
3875
# 1. Start new server instance for preview windows (if required)
3876
# 2. Issues commands to the preview server
3882
sub preview_display {
3883
my ($command, $primary, $secondary, $mode) = @_;
3884
debug("Preview display $mode");
3885
if (!$config->{'DynamicPreview'} && $mode eq "MINI") {
3889
if ($mode eq "MINI") {
3890
$port = $globals->{'preview_port'};
3891
} elsif ($mode eq "EDIT") {
3892
$port = $globals->{'editview_port'};
3896
if (!defined($secondary)) {
3899
if (!defined($primary)) {
3902
$primary =~ s/:/#SEMI#/g;
3903
$secondary =~ s/:/#SEMI#/g;
3905
"Preview command: " . $command . ":" . $primary . ":" . $secondary);
3908
my $server = IO::Socket::INET->new(
3910
PeerAddr => "localhost",
3915
print $server toutf($command . ":"
3917
. $secondary . "\n");
3921
#tcp/ip socket failure so server must be not running yet!
3922
debug("Preview not running?");
3923
if (defined $widgets->{'preview'}) {
3924
$widgets->{'main'}->get_widget('framePreview')->remove($widgets->{'preview'});
3925
undef $widgets->{'preview'};
3934
#****f* lyricue/open_dialogColour
3938
# open_dialogColour($widget, $event, $item)
3940
# Load a new dialog to select a colour
3942
# $widget - Calling widget
3943
# $event - how we where called
3944
# $item - What we want to set the colour for
3949
sub open_dialogColour {
3950
my ($widget, $event, $item) = @_;
3951
debug("Opening Colour dialog");
3952
debug("open_dialogColour: item=" . $item);
3953
debug("open_dialogColour: widget=" . $widget->get_name());
3955
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogColour', 'lyricue');
3956
$colourxml->signal_autoconnect_from_package('');
3957
$colourxml->get_widget('dialogColour')
3959
fromutf(gettext("Select ")) . $item . fromutf(gettext(" Colour")));
3960
$colourxml->get_widget('dialogColour')->{'user_data'} = $item;
3962
if ($item eq "Font") {
3963
$colourxml->get_widget('colourSelect')->set_current_color(
3964
Gtk2::Gdk::Color->parse(
3965
$widgets->{'prefs'}->get_widget('entryPrefColour')->get_text()
3969
if ($item eq "Shadow") {
3970
$colourxml->get_widget('colourSelect')->set_current_color(
3971
Gtk2::Gdk::Color->parse(
3972
$widgets->{'prefs'}->get_widget('entryPrefShadowColour')
3977
if ($item eq "ImageFont") {
3979
#$colourxml->get_widget('colourSelect')->set_current_color(Gtk2::Gdk::Color->parse($widgets->{'image'}->get_widget('entryImageFontColour')->get_text()));
3980
$colourxml->get_widget('colourSelect')
3981
->set_current_color($widget->get_color());
3983
if ($item eq "ImageShadow") {
3985
#$colourxml->get_widget('colourSelect')->set_current_color(Gtk2::Gdk::Color->parse($widgets->{'image'}->get_widget('entryImageShadowColour')->get_text()));
3986
$colourxml->get_widget('colourSelect')
3987
->set_current_color($widget->get_color());
3989
$colourxml->get_widget('buttonColourOK')
3990
->signal_connect("clicked", "change_font_colour", $colourxml);
3991
$colourxml->get_widget('buttonColourCancel')
3992
->signal_connect("clicked", "close_dialog");
3993
my $response = $colourxml->get_widget('dialogColour')->run();
3998
#****f* lyricue/open_dialogFont
4002
# open_dialogFont ($widget, $event, $font)
4004
# Load a new dialog to select a colour
4006
# $widget - Calling widget
4007
# $event - how we where called
4008
# $font - What we want to set the colour for
4013
sub open_dialogFont {
4014
my ($widget, $event, $font) = @_;
4015
debug("Opening Font dialog");
4016
$widgets->{'font'} =
4017
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogFont', 'lyricue');
4018
$widgets->{'font'}->signal_autoconnect_from_package('');
4019
my $fontname = $config->{$font};
4020
$widgets->{'font'}->get_widget('selectFont')->set_font_name($fontname);
4021
$widgets->{'font'}->get_widget('buttonFontOK')
4022
->signal_connect("clicked", "apply_font", $font);
4023
$widgets->{'font'}->get_widget('dialogFont')->show;
4029
#****f* lyricue/change_font_colour
4031
# change_font_colour
4033
# change_font_colour ($widget, $colourxml)
4035
# Change the font colour
4037
# $widget - Calling widget
4038
# $colourxml - The Colour dialog
4040
# Updated config file and server
4043
sub change_font_colour {
4044
my ($widget, $colourxml) = @_;
4045
debug("Change font colour");
4046
my $item = $colourxml->get_widget('dialogColour')->{'user_data'};
4047
my $colour = $colourxml->get_widget('colourSelect')->get_current_color();
4049
sprintf("#%2.2x", ($colour->red / 256))
4050
. sprintf("%2.2x", ($colour->green / 256))
4051
. sprintf("%2.2x", ($colour->blue / 256));
4053
debug("change_font_colour: item=" . $item);
4054
if ($item eq "Shadow") {
4055
$widgets->{'prefs'}->get_widget('entryPrefShadowColour')
4056
->set_text($color2);
4057
$widgets->{'prefs'}->get_widget('entryPrefShadowColour')
4058
->set_text($color2);
4059
} elsif ($item eq "Font") {
4060
$widgets->{'prefs'}->get_widget('entryPrefColour')->set_text($color2);
4061
} elsif ($item eq "ImageShadow") {
4062
$widgets->{'image'}->get_widget('entryImageShadowColour')
4063
->set_text($color2);
4064
$widgets->{'image'}->get_widget('colorbuttonShadowColour')
4065
->set_color(Gtk2::Gdk::Color->parse($color2));
4066
change_colour_media();
4067
} elsif ($item eq "ImageFont") {
4068
$widgets->{'image'}->get_widget('entryImageFontColour')
4069
->set_text($color2);
4070
$widgets->{'image'}->get_widget('colorbuttonFontColour')
4071
->set_color(Gtk2::Gdk::Color->parse($color2));
4072
change_colour_media();
4074
close_dialog($widget);
4079
#****f* lyricue/apply_font
4085
# Apply font changes to the config file and server
4088
# Updated file and server
4092
my ($widget, $type) = @_;
4093
debug("Applying font: "
4094
. $widgets->{'font'}->get_widget('selectFont')->get_font_name);
4095
$widgets->{'prefs'}->get_widget('entryPref' . $type)
4096
->set_text($widgets->{'font'}->get_widget('selectFont')->get_font_name);
4097
close_dialog($widget);
4102
#****f* lyricue/changeVerseStatus
4106
# changeVerseStatus ($widget, $section, $row, $col, $rows, $max)
4108
# Make sure you can't choose multiple values for start or finish
4110
# $widget - Calling widget
4112
# $max - Maximum value
4114
# Only one value chosen in start or finish area
4117
sub changeVerseStatus {
4118
my ($widget, $event, $max) = @_;
4120
#debug("Change verse status");
4122
my $number = $widget->get_label;
4123
if (defined($event->type)) {
4126
if ($event->type eq 'button-press') {
4127
if ( ($globals->{'verseEnd'} == 0)
4128
&& ($globals->{'verseStart'} != 0))
4130
if ($number < $globals->{'verseStart'}) {
4131
$globals->{'verseEnd'} = $globals->{'verseStart'};
4132
$globals->{'verseStart'} = $number;
4134
$globals->{'verseEnd'} = $number;
4137
. $globals->{'verseStart'} . ","
4138
. $globals->{'verseEnd'});
4139
$begin = $globals->{'verseStart'};
4140
$end = $globals->{'verseEnd'};
4142
debug("Start " . $globals->{'verseStart'});
4143
$globals->{'verseStart'} = $number;
4144
$globals->{'verseEnd'} = 0;
4145
$begin = $globals->{'verseStart'};
4146
$end = $globals->{'verseStart'};
4149
$widgets->{'main'}->get_widget('entryNavVerse')->get_text();
4152
$verse = $book . ":" . $begin . "-" . $end;
4153
$widgets->{'main'}->get_widget('entryNavVerse')->set_text($verse);
4154
} elsif ($event->type eq 'enter-notify') {
4156
if ((defined $globals->{'verseStart'})
4157
&& ($globals->{'verseStart'} != 0)
4158
&& ($globals->{'verseEnd'} == 0))
4160
if ($number < $globals->{'verseStart'}) {
4162
$end = $globals->{'verseStart'};
4164
$begin = $globals->{'verseStart'};
4170
foreach my $num (1 .. $max) {
4171
my $button = "button" . ($num - 1);
4172
if (($num >= $begin) && ($num <= $end)) {
4173
$widgets->{'bibleBrowser'}{$button}->set_active(TRUE);
4175
$widgets->{'bibleBrowser'}{$button}->set_active(FALSE);
4186
#****f* lyricue/change_preview
4190
# change_preview ($widget)
4192
# Change the preview in the image dialog
4194
# $widget - Calling widget
4199
sub change_preview {
4200
debug("Changing Preview");
4201
my $selection = $widgets->{'image'}->get_widget('treeImage')->get_selection;
4202
my @selecteditems = $selection->get_selected_rows();
4203
if ($selecteditems[0]) {
4205
# Find what has changed
4206
my $newsel = $selecteditems[0];
4208
$widgets->{'image'}->get_widget('treeImage')
4209
->get_model->get_iter($newsel);
4211
$widgets->{'image'}->get_widget('treeImage')
4212
->get_model->get($iter, 1);
4213
my ($type, $id) = split /;/, $data;
4215
foreach $tmp (@selecteditems) {
4217
$widgets->{'image'}->get_widget('treeImage')
4218
->get_model->get_iter($tmp);
4220
$widgets->{'image'}->get_widget('treeImage')
4221
->get_model->get($iter2, 1);
4222
if (!defined $selectedimages{$data2}) {
4224
($type, $id) = split /;/, $data;
4227
%selectedimages = ();
4228
foreach $tmp (@selecteditems) {
4230
$widgets->{'image'}->get_widget('treeImage')
4231
->get_model->get_iter($tmp);
4233
$widgets->{'image'}->get_widget('treeImage')
4234
->get_model->get($iter2, 1);
4235
$selectedimages{$id2} = TRUE;
4238
if ($globals->{'bg_previews'}) {
4239
debug("sub change_preview: create_pixbuf");
4240
my $scaled = create_pixbuf($data, 480, 360);
4243
if ($type eq "db") {
4245
"SELECT textcolour, shadowcolour FROM media WHERE id=\""
4249
"SELECT textcolour, shadowcolour FROM media WHERE format=\"file\" AND category=\"" . $id . "\"";
4252
my $sth = $mediaDbh->prepare($query)
4253
|| display_fatal($errorcodes->{'sqlprepare'},
4254
$! . "\nSQL: " . $query);
4255
my $rv = $sth->execute
4256
|| display_fatal($errorcodes->{'sqlexecute'},
4257
$! . "\nSQL: " . $query);
4258
$row = $sth->fetchrow_hashref();
4260
$widgets->{'image'}->get_widget('buttonImageDelete')
4261
->set_sensitive(TRUE);
4262
$widgets->{'image'}->get_widget('buttonImageChange')
4263
->set_sensitive(TRUE);
4264
$widgets->{'image'}->get_widget('hboxImageColour')
4267
$row->{'textcolour'} = "Default";
4268
$row->{'shadowcolour'} = "Default";
4271
# $widgets->{'image'}->get_widget('buttonImageDelete')
4272
# ->set_sensitive(FALSE);
4273
# $widgets->{'image'}->get_widget('buttonImageChange')
4274
# ->set_sensitive(FALSE);
4275
# $widgets->{'image'}->get_widget('hboxImageColour')->hide;
4279
if ( ($row->{'textcolour'} ne "")
4280
&& ($row->{'textcolour'} ne "NULL")
4281
&& ($row->{'textcolour'} ne "Default"))
4283
$widgets->{'image'}->get_widget('entryImageFontColour')
4284
->set_text($row->{'textcolour'});
4285
$widgets->{'image'}->get_widget('colorbuttonFontColour')
4287
Gtk2::Gdk::Color->parse($row->{'textcolour'}));
4288
$fg_span="<span color=\"".$row->{'textcolour'}."\">";
4290
$widgets->{'image'}->get_widget('entryImageFontColour')
4291
->set_text("Default");
4292
$widgets->{'image'}->get_widget('colorbuttonFontColour')
4293
->set_color(Gtk2::Gdk::Color->parse($config->{'Colour'}));
4294
$fg_span="<span color=\"".$config->{'Colour'}."\">";
4296
if ( ($row->{'shadowcolour'} ne "")
4297
&& ($row->{'shadowcolour'} ne "NULL")
4298
&& ($row->{'shadowcolour'} ne "Default"))
4300
$widgets->{'image'}->get_widget('entryImageShadowColour')
4301
->set_text($row->{'shadowcolour'});
4302
$widgets->{'image'}->get_widget('colorbuttonShadowColour')
4304
Gtk2::Gdk::Color->parse($row->{'shadowcolour'}));
4305
$bg_span="<span color=\"".$row->{'shadowcolour'}."\">";
4307
$widgets->{'image'}->get_widget('entryImageShadowColour')
4308
->set_text("Default");
4309
$widgets->{'image'}->get_widget('colorbuttonShadowColour')
4311
Gtk2::Gdk::Color->parse($config->{'ShadowColour'}));
4312
$bg_span="<span color=\"".$config->{'ShadowColour'}."\">";
4314
# Add text overlay to $scaled
4315
my $pixmap = $scaled->render_pixmap_and_mask(127);
4316
my $pango_layout = $widgets->{'image'}->get_widget('imageImage')->create_pango_layout("");
4317
$pango_layout->set_font_description( Gtk2::Pango::FontDescription->from_string($config->{'Main'}));
4318
my $gc = Gtk2::Gdk::GC->new($pixmap);
4319
$pango_layout->set_markup($bg_span.fromutf(gettext("Song Contents"))."</span>");
4320
my ($text_w, $text_h) = $pango_layout->get_pixel_size();
4321
my $text_x = (480-$text_w)/2;
4322
my $text_y = (360-$text_h)/2;
4323
$pixmap->draw_layout($gc, $text_x+2, $text_y+2, $pango_layout);
4324
$pango_layout->set_markup($fg_span.fromutf(gettext("Song Contents"))."</span>");
4325
$pixmap->draw_layout($gc, $text_x, $text_y, $pango_layout);
4326
$widgets->{'image'}->get_widget('imageImage')
4327
->set_from_pixmap($pixmap,undef);
4328
$widgets->{'image'}->get_widget('imageImage')->{user_data} =
4338
#****f* lyricue/set_default_backdrop
4340
# set_default_backdrop
4342
# set_default_backdrop ($widget)
4344
# Change the default background in the config file
4346
# $widget - Calling widget
4348
# Updated config file
4351
sub set_default_backdrop {
4353
debug("Set default backdrop");
4354
my $image = $widgets->{'image'}->get_widget('imageImage')->{user_data};
4356
my $scaled = create_pixbuf(
4358
$globals->{'icon_width'},
4359
$globals->{'icon_height'}
4362
$widgets->{'prefs'}->get_widget('imagePrefBG')
4363
->set_from_pixbuf($scaled);
4364
$widgets->{'prefs'}->get_widget('imagePrefBG')->{user_data} =
4368
close_dialog($widget);
4373
#****f* lyricue/print_songs
4379
# Print a html formatted list of available songs
4381
# HTML list of songs to standard out
4385
debug("Print html formatted song list");
4387
db_connect($globals->{'lyricdb'}, $errorcodes->{'lyricdbopen'});
4388
my $query = "SELECT COUNT(id) FROM lyricMain WHERE id > 0;";
4389
my $sth = $lyricDbh->prepare($query)
4390
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
4391
my $rv = $sth->execute
4392
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
4393
my @totals = $sth->fetchrow_array();
4396
"SELECT title,book,songnum,artist FROM lyricMain WHERE id > 0 ORDER BY title;";
4397
$sth = $lyricDbh->prepare($query)
4398
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
4400
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
4402
print "<HTML>\n<HEAD><TITLE>Lyricue Song List</TITLE></HEAD>\n";
4403
print "<CENTER><H1>Lyricue Song List</H1></CENTER><BR>\n";
4404
print "<H2>Total number of songs available : <B>"
4407
print "<TABLE WIDTH=100% BORDER=1>\n";
4409
"<TR><TH>Song Name</TH><TH>Song Book</TH><TH>Song Number</TH><TH>Artist</TH></TR>\n";
4412
while (@row = $sth->fetchrow_array()) {
4418
print "<TD>" . $_ . "</TD>";
4422
print "</TABLE>\n</BODY>\n</HTML>\n";
4423
$lyricDbh->disconnect;
4429
#****f* lyricue/backdrop_clicked
4433
# backdrop_clicked ($widget)
4435
# A background has been clicked son change the bg in the server and update the two previews on the main window
4437
# $widget - Calling widget
4442
sub backdrop_clicked {
4443
my ($widget, $event) = @_;
4444
if ($event->type eq 'button-press') {
4447
debug("Backdrop clicked");
4449
my @list = $widget->get_selected_items;
4450
if (defined $list[0]) {
4451
my $model = $widget->get_model;
4452
my $iter = $model->get_iter($list[0]);
4453
$selected = $model->get($iter, 2);
4455
if ($selected eq "") {
4459
#$widget->unselect_all;
4462
associate_bg($selected);
4464
debug("Changing backdrop to " . $selected);
4465
if ($globals->{'bg_previews'}) {
4466
my $prevFile = $selected;
4467
my $scaled = create_pixbuf(
4468
$widgets->{'buttonCurr'}->{user_data},
4469
$globals->{'icon_width'},
4470
$globals->{'icon_height'}
4474
$widgets->{'pixmapPrev'}->set_from_pixbuf($scaled);
4475
$widgets->{'buttonPrev'}->{user_data} =
4476
$widgets->{'buttonCurr'}->{user_data};
4479
$scaled = create_pixbuf(
4481
$globals->{'icon_width'},
4482
$globals->{'icon_height'}
4485
$widgets->{'pixmapCurr'}->set_from_pixbuf($scaled);
4486
$widgets->{'buttonCurr'}->{user_data} = $prevFile;
4488
update_display("backdrop", $prevFile, "");
4489
preview_display("backdrop", $prevFile, "", "MINI");
4496
#****f* lyricue/backdrop_preview_clicked
4498
# backdrop_preview_clicked
4500
# backdrop_preview_clicked($widget)
4502
# Changing backdrop to
4508
sub backdrop_preview_clicked {
4510
my $selected = $widget->{user_data};
4511
debug("Changing backdrop to " . $selected);
4512
if ($globals->{'bg_previews'}) {
4513
my $prevFile = $selected;
4514
my $scaled = create_pixbuf(
4515
$widgets->{'buttonCurr'}->{user_data},
4516
$globals->{'icon_width'},
4517
$globals->{'icon_height'}
4521
$widgets->{'pixmapPrev'}->set_from_pixbuf($scaled);
4522
$widgets->{'buttonPrev'}->{user_data} =
4523
$widgets->{'buttonCurr'}->{user_data};
4526
$scaled = create_pixbuf(
4528
$globals->{'icon_width'},
4529
$globals->{'icon_height'}
4532
$widgets->{'pixmapCurr'}->set_from_pixbuf($scaled);
4533
$widgets->{'buttonCurr'}->{user_data} = $prevFile;
4535
update_display("backdrop", $prevFile, "");
4536
preview_display("backdrop", $prevFile, "", "MINI");
4542
#****f* lyricue/do_add_image
4548
# Add an image to the playlist
4550
# Image added to playlist
4555
debug("do add image");
4556
my $selection = $widgets->{'image'}->get_widget('treeImage')->get_selection;
4557
my @list = $selection->get_selected_rows();
4558
my $model = $widgets->{'image'}->get_widget('treeImage')->get_model();
4560
$widgets->{'image'}->get_widget('optionImageSublist')
4561
->get_menu->get_active->{'user_data'};
4563
my $image = $model->get($model->get_iter($_), 1);
4564
add_image_item($playlist, $image);
4566
close_dialog($widget);
4572
#****f* lyricue/add_image_item
4576
# add_image_item($playlist, $image)
4585
sub add_image_item {
4586
my ($playlist, $image) = @_;
4589
my $query = "SELECT MAX(playorder) FROM playlist";
4591
my $sth = $lyricDbh->prepare($query)
4592
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
4593
my $rv = $sth->execute
4594
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
4596
if ($row = $sth->fetchrow_hashref()) {
4597
if ($row->{'MAX(playorder)'}) {
4598
$playorder = $row->{'MAX(playorder)'} + 1;
4604
"INSERT INTO playlist (playorder, playlist, type, data) VALUES ("
4610
$sth = $lyricDbh->prepare($query)
4611
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
4613
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
4620
#****f* lyricue/show_about
4626
# Open the About dialog
4632
debug("Showing About dialog");
4634
Gtk2::GladeXML->new($globals->{'gladefile'}, 'windowAbout', 'lyricue');
4635
$xml->signal_autoconnect_from_package('');
4636
my $abouttext = $xml->get_widget('labelVersion')->get_text();
4637
$abouttext =~ s/#VERSION#/$globals->{'version'}/g;
4638
$xml->get_widget('labelVersion')->set_text($abouttext);
4639
$xml->get_widget('windowAbout')->show();
4644
#****f* lyricue/choose_playlist
4648
# choose_playlist ( )
4650
# Open a dialog to choose your main playlist
4655
sub choose_playlist {
4656
debug("Choose playlist");
4657
$widgets->{'main'}->get_widget('vboxChoosePlay')->show_all;
4658
$widgets->{'main'}->get_widget('scrollPlaylist')->hide;
4659
$widgets->{'main'}->get_widget('toolbarPlaylist')->hide;
4660
update_cplayclist();
4665
#****f* lyricue/close_playlist_chooser
4667
# close_playlist_chooser
4669
# close_playlist_chooser ( )
4671
# Close the playlist chooser
4674
sub close_playlist_chooser {
4675
debug("Close playlist chooser");
4676
$widgets->{'main'}->get_widget('vboxChoosePlay')->hide;
4677
$widgets->{'main'}->get_widget('scrollPlaylist')->show_all;
4678
$widgets->{'main'}->get_widget('toolbarPlaylist')->show_all;
4683
#****f* lyricue/create_dialog_prefs
4685
# create_dialog_prefs
4687
# create_dialog_prefs()
4689
# Open the preferences dialog
4691
# preferences dialog
4694
sub create_dialog_prefs {
4695
debug("Creating preferences dialog");
4696
$config = load_config();
4697
$widgets->{'prefs'} =
4698
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogPrefs', 'lyricue');
4699
$widgets->{'prefs'}->signal_autoconnect_from_package('');
4700
$widgets->{'prefs'}->get_widget('spinPrefHeight')
4701
->set_value($config->{'Height'});
4702
$widgets->{'prefs'}->get_widget('spinPrefWidth')
4703
->set_value($config->{'Width'});
4704
$widgets->{'prefs'}->get_widget('spinPrefOverscanV')
4705
->set_value($config->{'OverscanV'});
4706
$widgets->{'prefs'}->get_widget('spinPrefOverscanH')
4707
->set_value($config->{'OverscanH'});
4708
$widgets->{'prefs'}->get_widget('checkPrefXinerama')
4709
->set_active($config->{'Xinerama'});
4710
$widgets->{'prefs'}->get_widget('entryPrefWindowOffset')
4711
->set_text($config->{'GeometryOverride'});
4713
if ($config->{'VerticalLocation'}) {
4714
$widgets->{'prefs'}->get_widget('comboPrefVertical')
4715
->prepend_text($config->{'VerticalLocation'});
4717
$widgets->{'prefs'}->get_widget('comboPrefVertical')->set_active(0);
4718
if ($config->{'HorizontalLocation'}) {
4719
$widgets->{'prefs'}->get_widget('comboPrefHorizontal')
4720
->prepend_text($config->{'HorizontalLocation'});
4722
$widgets->{'prefs'}->get_widget('comboPrefHorizontal')->set_active(0);
4723
if ($config->{'Justification'}) {
4724
$widgets->{'prefs'}->get_widget('comboPrefJustification')
4725
->prepend_text($config->{'Justification'});
4727
$widgets->{'prefs'}->get_widget('comboPrefJustification')->set_active(0);
4728
if ($config->{'DefaultTransition'}) {
4729
$widgets->{'prefs'}->get_widget('comboPrefDefTrans')
4730
->prepend_text($config->{'DefaultTransition'});
4732
$widgets->{'prefs'}->get_widget('comboPrefDefTrans')->set_active(0);
4734
$widgets->{'prefs'}->get_widget('entryPrefHeader')
4735
->set_text($config->{'Header'});
4736
$widgets->{'prefs'}->get_widget('entryPrefMain')
4737
->set_text($config->{'Main'});
4738
$widgets->{'prefs'}->get_widget('entryPrefFooter')
4739
->set_text($config->{'Footer'});
4740
$widgets->{'prefs'}->get_widget('entryPrefOSD')->set_text($config->{'OSD'});
4741
$widgets->{'prefs'}->get_widget('entryPrefColour')
4742
->set_text($config->{'Colour'});
4743
$widgets->{'prefs'}->get_widget('entryPrefShadowColour')
4744
->set_text($config->{'ShadowColour'});
4745
$widgets->{'prefs'}->get_widget('spinPrefShadow')
4746
->set_value($config->{'ShadowSize'});
4747
$widgets->{'prefs'}->get_widget('checkPrefLoop')
4748
->set_active($config->{'Loop'});
4749
$widgets->{'prefs'}->get_widget('checkPrefAudit')
4750
->set_active($config->{'Audit'});
4751
$widgets->{'prefs'}->get_widget('checkPrefView')
4752
->set_active($config->{'DynamicPreview'});
4753
$widgets->{'prefs'}->get_widget('checkPrefMiniview')
4754
->set_active($config->{'Miniview'});
4755
my $scaled = create_pixbuf(
4756
$config->{'BGImage'},
4757
$globals->{'icon_width'},
4758
$globals->{'icon_height'}
4762
$widgets->{'prefs'}->get_widget('imagePrefBG')
4763
->set_from_pixbuf($scaled);
4764
$widgets->{'prefs'}->get_widget('imagePrefBG')->{user_data} =
4765
$config->{'BGImage'};
4769
my $bibles = $config->{'Bibles'};
4770
foreach (sort keys %$bibles) {
4771
my $bible = $_ . ":" . $config->{'Bibles'}->{$_};
4775
$widgets->{'prefs'}->get_widget('comboPrefBible')
4776
->set_popdown_strings(@list);
4777
$widgets->{'prefs'}->get_widget('entryPrefBible')
4778
->set_text($config->{'DefBible'});
4779
$widgets->{'prefs'}->get_widget('entryPrefSpecialSong')
4780
->set_text($config->{'SpecialSong'});
4781
$widgets->{'prefs'}->get_widget('entryPrefSpecialImage')
4782
->set_text($config->{'SpecialImage'});
4783
$widgets->{'prefs'}->get_widget('entryPrefSpecialBack')
4784
->set_text($config->{'SpecialBack'});
4785
$config->{'ImageDirectory'} =~ s/^\~/$ENV{'HOME'}/;
4786
$widgets->{'prefs'}->get_widget('filePrefSpecialImagedir')
4787
->set_label($config->{'ImageDirectory'});
4788
$widgets->{'prefs'}->get_widget('filePrefSpecialImagedir')->{'user_data'} =
4790
$config->{'BGDirectory'} =~ s/^\~/$ENV{'HOME'}/;
4791
$widgets->{'prefs'}->get_widget('filePrefSpecialBGdir')
4792
->set_label($config->{'BGDirectory'});
4793
$widgets->{'prefs'}->get_widget('filePrefSpecialBGdir')->{'user_data'} =
4796
if ($config->{'DatabaseType'} eq "mysql") {
4797
$widgets->{'prefs'}->get_widget('radioPrefDBMysql')->set_active(TRUE);
4799
$widgets->{'prefs'}->get_widget('radioPrefDBSqlite')->set_active(TRUE);
4801
$widgets->{'prefs'}->get_widget('entryPrefHeader')
4802
->signal_connect("button_press_event", "open_dialogFont", "Header");
4803
$widgets->{'prefs'}->get_widget('entryPrefMain')
4804
->signal_connect("button_press_event", "open_dialogFont", "Main");
4805
$widgets->{'prefs'}->get_widget('entryPrefFooter')
4806
->signal_connect("button_press_event", "open_dialogFont", "Footer");
4807
$widgets->{'prefs'}->get_widget('entryPrefOSD')
4808
->signal_connect("button_press_event", "open_dialogFont", "OSD");
4809
$widgets->{'prefs'}->get_widget('entryPrefColour')
4810
->signal_connect("button_press_event", "open_dialogColour", "Font");
4811
$widgets->{'prefs'}->get_widget('entryPrefShadowColour')
4812
->signal_connect("button_press_event", "open_dialogColour", "Shadow");
4817
#****f* lyricue/change_windowoffset
4819
# change_windowoffset
4821
# change_windowoffset
4823
# Show window for offset setting
4826
# Application loaded on second head
4830
sub change_windowoffset {
4831
debug ("Showing offset window");
4832
my $offsetxml = Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogWindowOffset', 'lyricue');
4833
$offsetxml->signal_autoconnect_from_package('');
4834
$offsetxml->get_widget('dialogWindowOffset')->parse_geometry($widgets->{'prefs'}->get_widget('entryPrefWindowOffset')->get_text);
4835
my $confirm = $offsetxml->get_widget('dialogWindowOffset')->run();
4836
if ($confirm == 1) {
4837
my ($x, $y)= $offsetxml->get_widget('dialogWindowOffset')->get_position;
4838
$widgets->{'prefs'}->get_widget('entryPrefWindowOffset')->set_text("+".$x."+".$y);
4840
close_dialog($offsetxml->get_widget('dialogWindowOffset'));
4843
#****f* lyricue/change_pref_xinerama
4845
# change_pref_xinerama
4847
# change_pref_xinerama($widget)
4849
# Show/Hide xinerama-specific bits
4851
# $widget - Calling widget
4853
# Stuff shown or hidden
4856
sub change_pref_xinerama {
4858
debug ("Hide/Show xinerama stuff");
4859
foreach my $name ('buttonPrefWindowOffset', 'labelPrefWindowOffset', 'entryPrefWindowOffset') {
4860
if ($widget->get_active) {
4861
$widgets->{'prefs'}->get_widget($name)->show;
4863
$widgets->{'prefs'}->get_widget($name)->hide;
4869
#****f* lyricue/execute_app
4873
# execute_app ($widget, $app)
4875
# Run and application on the second head
4877
# $widget - Calling widget
4878
# $app - Application to run
4880
# Application loaded on second head
4884
my ($widget, $app) = @_;
4886
if ($widget eq "") {
4889
$command = $config->{'App'}[$app];
4890
$command =~ s/^.*?;//g;
4892
debug("Executing app: " . $command);
4893
if ($config->{'Xinerama'}) {
4894
if ($command =~ /;$/) {
4896
system($command . " &");
4898
my $geom = "+" . ($widgets->{'main'}->get_widget('windowMain')->get_screen->get_width - 100) . "+100";
4899
if ($config->{'GeometryOverride'}) {
4900
$geom = $config->{'GeometryOverride'};
4902
system($command. " --geometry " . $geom . " &");
4905
system("DISPLAY=:0.1 " . $command . " &");
4911
#****f* lyricue/quote
4917
# Quote a string for use in db queries
4919
# @_ - String to be quoted
4925
return $lyricDbh->quote(@_);
4930
#****f* lyricue/honourise_song_lyrics
4932
# honourise_song_lyrics
4934
# honourise_song_lyrics ($widget)
4936
# Change lyrics to 'honourise' them by changing 'jesus' to 'Jesus' etc
4938
# $widget - Calling widget
4943
sub honourise_song_lyrics {
4945
my ($tmppage, $page, $numchars, $key);
4948
debug("Start of honourising lyrics...");
4950
foreach $page (keys(%pageOrder)) {
4951
$tmppage = get_buffer_text($widgets->{'textAPageB'}{$page});
4952
debug( "Page contents of page "
4954
. " before honourisation:\n"
4957
# this hash is adapted from bible parsing perl script
4958
# it will correct american spelling in any songs entered
4959
# and will perform the honourise process -
4960
# capitalising holy names and correcting errors like
4961
# "Sons of god" to "sons of God"
4963
"honor" => "honour",
4964
"color" => "colour",
4965
"labor" => "labour",
4966
"neighbor" => "neighbour",
4967
"center" => "centre",
4968
"dialog" => "dialogue",
4970
"humor" => "humour",
4971
"harbor" => "harbour",
4972
"thru" => "through",
4974
"favor" => "favour",
4976
"reaSon" => "reason",
4979
"spirit" => "Spirit",
4982
"emmanuel" => "Emmanuel",
4983
"immanuel" => "Immanuel",
4984
"jehovah" => "Jehovah",
4988
"History" => "history",
4989
"messiah" => "Messiah",
4990
"father" => "Father",
4992
"christ" => "Christ",
4993
"great i am" => "Great I Am",
4994
"hosanna" => "Hosanna",
4995
"yahweh" => "Yahweh"
4998
foreach $key (keys %hash) {
4999
$tmppage =~ s/^$key([ \n])/$hash{$key}$1/g;
5000
$tmppage =~ s/([ \n])$key$/$1$hash{$key}/g;
5001
$tmppage =~ s/([ \n])$key([ \n])/$1$hash{$key}$2/g;
5003
debug( "Page contents of page "
5005
. " after honourisation:\n"
5007
$widgets->{'textAPageB'}{$page}->set_text($tmppage);
5011
debug("End of honourising lyrics...");
5016
#****f* lyricue/select_bible_db
5020
# select_bible_db ($bible_database)
5022
# Change the bible db used by the server
5024
# $bible_database - DB name to change it to
5026
# Verses displayed in chosen bible
5029
sub select_bible_db {
5030
my ($widget, $bibledb) = @_;
5032
if ($widget && ($widget->get_active)) {
5033
debug("Changing bible to $bibledb");
5034
my @line = split(/;/, $bibledb, 2);
5035
do_change_bible($line[0], $line[1]);
5036
if ((!defined $config->{'DefBible'}) || ($config->{'DefBible'} eq "")) {
5037
$config->{'DefBible'} =
5038
$line[1] . ":" . $line[0] . ";" . $widget->get('label');
5039
debug("No default bible set previously, setting to "
5040
. $config->{'DefBible'});
5041
write_config(FALSE);
5048
#****f* lyricue/do_change_bible
5052
# do_change_bible ($type, $bibledb)
5054
# Change currently used bible
5056
# $type - bible type (sword/db)
5057
# $bibledb - Bible name
5059
# Calls update_playlist
5062
sub do_change_bible {
5063
my ($type, $bibledb) = @_;
5064
debug("Change bible");
5065
$globals->{'bibledb'} = $bibledb;
5066
if (!$globals->{'usesword'}) {
5067
$bibleDbh->disconnect;
5069
if ($type eq "db") {
5070
$globals->{'usesword'} = FALSE;
5071
my ($table, $dbname) = split(/@/, $globals->{'bibledb'}, 2);
5072
if ($dbname eq "") {
5075
$globals->{'bibledb'} = $table . "@" . $dbname;
5077
$bibleDbh = db_connect($dbname, $errorcodes->{'bibledbopen'} . $dbname);
5079
$globals->{'usesword'} = TRUE;
5081
update_display("change_to_db", $bibledb, $type);
5082
preview_display("change_to_db", $bibledb, $type, "MINI");
5087
#****f* lyricue/invert_lines
5093
# Change value so that playlist items text shows the last line of each page rather than the first
5096
# Calls update_playlist
5100
debug("Invert line display");
5101
$globals->{'invert'} = !$globals->{'invert'};
5107
#****f* lyricue/export_song
5113
# Show a dialog to choose where to save an exported song to
5115
# File dialog displayed
5119
debug("Export song");
5120
my $filexml = Gtk2::GladeXML->new($globals->{'gladefile'},
5121
'dialogFileChooser', 'lyricue');
5122
$filexml->signal_autoconnect_from_package('');
5123
$filexml->get_widget('buttonFileOK')
5124
->signal_connect("clicked", "complete_export_song", $filexml);
5125
$filexml->get_widget('dialogFileChooser')->show_all();
5130
#****f* lyricue/complete_export_song
5132
# complete_export_song
5134
# complete_export_song ($widget, $filexml)
5136
# Export a song to the chosen filename
5138
# $widget - Calling widget
5139
# $filexml - File dialog
5141
# File containing song
5144
sub complete_export_song {
5145
my ($widget, $filexml) = @_;
5146
my ($tmppage, $page, $numchars, $key);
5147
debug("Exporting song");
5148
my $export = $filexml->get_widget('dialogFileChooser')->get_filename;
5149
close_dialog($widget);
5150
debug(" to file: " . $export);
5152
# Find maximum number of pages
5154
while (exists $pageOrder{$maxpages}) {
5158
#decrement maxpages so export works properly
5159
$maxpages = $maxpages - 1;
5162
foreach $page (sort { $pageOrder{$a} cmp $pageOrder{$b} } keys %pageOrder) {
5163
my $tmppage = get_buffer_text($widgets->{'textAPageB'}{$page});
5165
push @pages, $tmppage;
5168
'name' => [$widgets->{'add'}->get_widget('entryEditName')->get_text()],
5170
[$widgets->{'add'}->get_widget('entryEditNumber')->get_text()],
5171
'book' => [$widgets->{'add'}->get_widget('entryEditBook')->get_text()],
5173
[$widgets->{'add'}->get_widget('entryEditArtist')->get_text()],
5175
[$widgets->{'add'}->get_widget('entryEditKeywords')->get_text()],
5177
[$widgets->{'add'}->get_widget('entryEditCopyright')->get_text()],
5181
my $out = {'song' => [$song]};
5183
my $writer = XML::Simple->new();
5184
open my $fh, ">" . $export . "";
5185
$writer->XMLout($out, OutputFile => $fh, RootName => 'lyricue');
5192
#****f* lyricue/do_adv_search
5198
# Do an advanced search where it searchs lyrics instead of song titles
5200
# List of suitable songs
5205
$widgets->{'search'}->get_widget('entrySearchSongs')->get_text();
5206
if ($search_text ne "") {
5207
debug("Searching for " . $search_text);
5208
my $store = $widgets->{'search'}->get_widget('treeSearch')->get_model();
5212
$store = Gtk2::ListStore->new(
5213
'Glib::String', 'Glib::String',
5214
'Glib::String', 'Glib::String',
5217
$widgets->{'search'}->get_widget('treeSearch')->set_model($store);
5218
my $column = Gtk2::TreeViewColumn->new_with_attributes(
5219
fromutf(gettext("Title")),
5220
Gtk2::CellRendererText->new, text => 0);
5221
$widgets->{'search'}->get_widget('treeSearch')
5222
->append_column($column);
5223
$column = Gtk2::TreeViewColumn->new_with_attributes(
5224
fromutf(gettext("Artist")),
5225
Gtk2::CellRendererText->new, text => 1);
5226
$widgets->{'search'}->get_widget('treeSearch')
5227
->append_column($column);
5228
$column = Gtk2::TreeViewColumn->new_with_attributes(
5229
fromutf(gettext("Book")),
5230
Gtk2::CellRendererText->new, text => 2);
5231
$widgets->{'search'}->get_widget('treeSearch')
5232
->append_column($column);
5233
$column = Gtk2::TreeViewColumn->new_with_attributes(
5234
fromutf(gettext("Song No")),
5235
Gtk2::CellRendererText->new, text => 3);
5236
$widgets->{'search'}->get_widget('treeSearch')
5237
->append_column($column);
5240
"SELECT id,title,songnum,book,artist,count(id) as count FROM lyricMain,page WHERE lyricMain.id=page.songid AND (page.lyrics LIKE \"%"
5242
. "%\" OR title LIKE \"%"
5244
. "%\" OR artist LIKE \"%"
5246
. "%\" OR keywords LIKE \"%"
5248
. "%\") GROUP BY id ORDER BY count DESC";
5250
$sth = $lyricDbh->prepare($query)
5251
|| display_fatal($errorcodes->{'sqlprepare'},
5252
$! . "\nSQL: " . $query);
5254
|| display_fatal($errorcodes->{'sqlexecute'},
5255
$! . "\nSQL: " . $query);
5256
while ($row = $sth->fetchrow_hashref()) {
5257
my $iter = $store->append;
5259
$iter, 0, $row->{'title'}, 1,
5260
$row->{'artist'}, 2, $row->{'book'}, 3,
5261
$row->{'songnum'}, 4, $row->{'id'}
5269
#****f* lyricue/update_adv_search
5273
# update_adv_search ($widget)
5275
# Update list of matching songs
5277
# $widget - Calling widget
5282
sub update_adv_search {
5285
$widgets->{'search'}->get_widget('treeSearch')->get_selection;
5286
my ($model, $iter) = $selection->get_selected;
5288
my $songid = $model->get($iter, 4);
5289
debug("Songid \"" . $songid . "\" selected");
5291
"SELECT lyrics FROM page WHERE songid="
5293
. " ORDER BY pagenum";
5294
$sth = $lyricDbh->prepare($query)
5295
|| display_fatal($errorcodes->{'sqlprepare'},
5296
$! . "\nSQL: " . $query);
5298
|| display_fatal($errorcodes->{'sqlexecute'},
5299
$! . "\nSQL: " . $query);
5302
while ($row = $sth->fetchrow_hashref()) {
5303
$lyrics .= $row->{'lyrics'} . "\n\n";
5305
$widgets->{'search'}->get_widget('textSearch')
5306
->get_buffer->set_text($lyrics);
5312
#****f* lyricue/move_item
5316
# move_item ($direction)
5318
# Move item in the playlist up/down
5320
# $direction - Direction to move item
5322
# Re-ordered playlist
5326
my ($source, $placement, $dest) = @_;
5327
debug("Moving " . $source . " to " . $placement . " " . $dest);
5328
my $query = "SELECT playlist FROM playlist WHERE playorder=" . $source;
5330
my $sth = $lyricDbh->prepare($query)
5331
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5332
my $rv = $sth->execute
5333
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5334
my @playlist = $sth->fetchrow_array;
5336
# Get list of items in this playlist
5338
"SELECT playorder FROM playlist WHERE playlist="
5340
. " ORDER BY playorder";
5342
$sth = $lyricDbh->prepare($query)
5343
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5345
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5347
while (my @row = $sth->fetchrow_array) {
5348
push @items, $row[0];
5353
foreach my $i (0 .. @items - 1) {
5354
debug($i . "-" . $items[$i]);
5355
if ($items[$i] == $source) {
5358
if ($items[$i] == $dest) {
5362
debug($sourceitem . ":" . $destitem);
5364
if ($placement eq "before") {
5366
} elsif ($placement eq "after") {
5369
$dest = $items[$destitem];
5370
debug($source . ":" . $dest);
5372
while ($source != $dest) {
5373
debug("Moving " . $source . " to " . $dest);
5374
if ($source < $dest) {
5375
start_transaction();
5377
renumber_item($source, -1);
5378
renumber_item($items[$sourceitem + 1], $source);
5379
renumber_item(-1, $items[$sourceitem + 1]);
5380
$lyricDbh->commit();
5382
end_transaction($@);
5385
start_transaction();
5387
renumber_item($source, -1);
5388
renumber_item($items[$sourceitem - 1], $source);
5389
renumber_item(-1, $items[$sourceitem - 1]);
5391
end_transaction($@);
5394
$source = $items[$sourceitem];
5396
update_playlist($dest);
5401
#****f* lyricue/move_item_up
5407
# Move item in the playlist up
5409
# Calls move_item to do it
5414
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
5415
my ($model, $iter) = $selection->get_selected;
5417
my $item = $model->get($iter, 2);
5418
move_item($item, 'before', $item);
5424
#****f* lyricue/move_item_down
5430
# Move item in the playlist down
5432
# Calls move_item to do it
5435
sub move_item_down {
5437
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
5438
my ($model, $iter) = $selection->get_selected;
5440
my $item = $model->get($iter, 2);
5441
move_item($item, 'after', $item);
5447
#****f* lyricue/renumber_item
5451
# renumber_item ($before,$after)
5453
# Renumber an item in the playlist
5455
# $before - playlist id to change from
5456
# $after - playlist id to change to
5458
# Renumbered verse in playlist/lyrics
5462
my ($before, $after) = @_;
5463
debug("Renumber item");
5464
my $query = "SELECT * FROM playlist WHERE playorder=" . $before;
5466
$sth = $lyricDbh->prepare($query)
5467
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5469
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5470
$row = $sth->fetchrow_hashref();
5473
"UPDATE playlist SET playorder=" . $after . " WHERE playorder=" . $before;
5475
$sth = $lyricDbh->prepare($query)
5476
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5478
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5481
"UPDATE associations SET playlist="
5483
. " WHERE playlist="
5486
$sth = $lyricDbh->prepare($query)
5487
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5489
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5494
#****f* lyricue/add_copyright_preset
5496
# add_copyright_preset
5498
# add_copyright_preset ($widget, $preset)
5500
# Add preset copyright text from menu to text entry
5502
# $widget - Calling widget
5503
# $preset - preset number to add
5505
# Preset in copyright entry
5508
sub add_copyright_preset {
5509
debug("Add preset");
5510
my ($widget, $preset) = @_;
5511
$widgets->{'add'}->get_widget('entryEditCopyright')
5512
->set_text("Preset:" . $preset);
5517
#****f* lyricue/debug
5523
# Always write to logfile
5524
# Print $text if $globals->{'debugging'} is set
5526
# $text - the text to output
5528
# Text to Logfile and possible STDERR
5535
my ($sec, $min, $hour, undef) = localtime(time);
5537
sprintf("%02d:%02d:%02d|INTERFACE: %s\n", $hour, $min, $sec, $text);
5539
if ($globals->{'debugging'}) {
5548
#****f* lyricue/qdebug
5556
# $text - the text to output
5562
if ($globals->{'debugging'} == 2) {
5569
#****f* lyricue/select_playlist
5573
# select_playlist ($widget)
5575
# Select the main playlist
5577
# $widget - calling widget
5579
# Closed selection dialog
5582
sub select_playlist {
5584
debug("Selecting a main playlist");
5589
$widgets->{'main'}->get_widget('treeChoosePlay')->get_selection;
5591
my ($m, $i) = $selection->get_selected;
5593
$playlist = $m->get($i, 0);
5594
$playlistid = $m->get($i, 1);
5598
if ($playlist eq "") {
5602
$widgets->{'main'}->get_widget('labelCurrentPlaylist')
5603
->set_text($playlist);
5604
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data} =
5607
close_playlist_chooser();
5613
#****f* lyricue/select_playlist_click
5615
# select_playlist_click
5617
# select_playlist_click ($widget, $event)
5619
# Select the main playlist on double-click
5621
# $widget - calling widget
5622
# $event - calling event
5624
# Closed selection dialog
5627
sub select_playlist_click {
5628
my ($widget, $event) = @_;
5629
debug("select_playlist_click");
5630
if ($event->type eq '2button-press') {
5631
select_playlist($widget);
5637
#****f* lyricue/new_playlist
5641
# new_playlist ($widget)
5643
# Create a new playlist
5645
# $widget - Calling widget
5652
debug("Creating a new playlist");
5654
my $newxml = Gtk2::GladeXML->new($globals->{'gladefile'},
5655
'dialogPromptEntry', 'lyricue');
5656
$newxml->signal_autoconnect_from_package('');
5657
$newxml->get_widget('dialogPromptEntry')
5658
->set_title(fromutf(gettext("Create new playlist")));
5659
$newxml->get_widget('labelPromptE')
5660
->set_text(fromutf(gettext("Name of playlist")));
5662
my $response = $newxml->get_widget('dialogPromptEntry')->run();
5663
if ($response eq "ok") {
5664
$playlist = $newxml->get_widget('entryPromptE')->get_text();
5666
close_dialog($newxml->get_widget('dialogPromptEntry'));
5667
if ($playlist eq "") {
5671
my $query = "SELECT MAX(id)+1 FROM playlists";
5672
my $sth = $lyricDbh->prepare($query)
5673
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5674
my $rv = $sth->execute
5675
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5676
my @row = $sth->fetchrow_array();
5678
"INSERT INTO playlists (id,title) VALUES ("
5680
. $playlist . "\")";
5681
$sth = $lyricDbh->prepare($query)
5682
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5684
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5685
$query = "SELECT id FROM playlists WHERE title LIKE \"" . $playlist . "\"";
5686
$sth = $lyricDbh->prepare($query)
5687
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5689
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5690
@row = $sth->fetchrow_array();
5693
$widgets->{'main'}->get_widget('labelCurrentPlaylist')
5694
->set_text($playlist);
5695
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data} =
5698
close_playlist_chooser();
5704
#****f* lyricue/rename_playlist
5708
# rename_playlist ($widget)
5712
# $widget - Calling widget
5716
sub rename_playlist {
5718
debug("Renaming playlist");
5721
$widgets->{'main'}->get_widget('treeChoosePlay')->get_selection;
5723
my ($m, $i) = $selection->get_selected;
5725
$playlist = $m->get($i, 0);
5729
if ($playlist eq "") {
5733
my $query = "SELECT id FROM playlists WHERE title=\"" . $playlist . "\"";
5734
my $sth = $lyricDbh->prepare($query)
5735
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5736
my $rv = $sth->execute
5737
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5738
my @row = $sth->fetchrow_array();
5740
my $renamexml = Gtk2::GladeXML->new($globals->{'gladefile'},
5741
'dialogPromptEntry', 'lyricue');
5742
$renamexml->signal_autoconnect_from_package('');
5743
my $labelText = fromutf(gettext("Renaming ")) . $playlist;
5744
$renamexml->get_widget('dialogPromptEntry')->set_title($labelText);
5745
$renamexml->get_widget('labelPromptE')->set_text($labelText);
5746
$renamexml->get_widget('labelPromptE')->{user_data} = $row[0];
5747
$renamexml->get_widget('entryPromptE')->set_text($playlist);
5748
$renamexml->get_widget('buttonPromptEOK')
5749
->signal_connect("clicked", "do_rename_playlist", $renamexml);
5755
#****f* lyricue/do_rename_playlist
5757
# do_rename_playlist
5759
# do_rename_playlist ($widget, $renamexml)
5763
# $widget - Calling widget
5764
# $renamexml - Dialog widgets
5769
sub do_rename_playlist {
5770
my ($widget, $renamexml) = @_;
5771
debug("Do rename playlist");
5773
"UPDATE playlists SET title=\""
5774
. $renamexml->get_widget('entryPromptE')->get_text
5776
. $renamexml->get_widget('labelPromptE')->{user_data};
5778
my $sth = $lyricDbh->prepare($query)
5779
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5780
my $rv = $sth->execute
5781
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5782
update_cplayclist();
5783
close_dialog($widget);
5788
#****f* lyricue/delete_playlist
5792
# delete_playlist ($widget)
5796
# $widget - Calling widget
5800
sub delete_playlist {
5802
debug("Deleting a playlist");
5806
$widgets->{'main'}->get_widget('treeChoosePlay')->get_selection;
5808
my ($m, $i) = $selection->get_selected;
5810
$playlist = $m->get($i, 1);
5814
if ($playlist eq "") {
5818
my $query = "DELETE FROM playlists WHERE id=" . $playlist;
5820
my $sth = $lyricDbh->prepare($query)
5821
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5822
my $rv = $sth->execute
5823
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5826
"DELETE FROM playlist WHERE data=" . $playlist . " AND type=\"play\"";
5828
$sth = $lyricDbh->prepare($query)
5829
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5831
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5833
$query = "SELECT playorder FROM playlist WHERE playlist=" . $playlist;
5835
$sth = $lyricDbh->prepare($query)
5836
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5838
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5839
while (my @row = $sth->fetchrow_array()) {
5840
remove_single_item($row[0]);
5843
update_cplayclist();
5848
#****f* lyricue/update_cplayclist
5852
# update_cplayclist ($widget)
5856
# $widget - The clist to update
5860
sub update_cplayclist {
5861
my ($selection, $renderer, $column);
5862
debug("Update Choose playlist");
5863
my $store = $widgets->{'main'}->get_widget('treeChoosePlay')->get_model();
5867
$store = Gtk2::ListStore->new('Glib::String', 'Glib::Int');
5868
$widgets->{'main'}->get_widget('treeChoosePlay')->set_model($store);
5869
$renderer = Gtk2::CellRendererText->new;
5871
$widgets->{'main'}->get_widget('treeChoosePlay')->get_selection;
5873
Gtk2::TreeViewColumn->new_with_attributes("Playlist", $renderer,
5875
$widgets->{'main'}->get_widget('treeChoosePlay')
5876
->append_column($column);
5880
"SELECT title,id FROM playlists LEFT JOIN playlist ON playlist.data=playlists.id AND playlist.data NOT LIKE '%-%' AND (type='play' OR type='sub') WHERE data IS NULL AND playlists.id > 0 ORDER BY id";
5882
my $sth = $lyricDbh->prepare($query)
5883
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
5884
my $rv = $sth->execute
5885
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
5887
while (@row = $sth->fetchrow_array()) {
5888
my $iter = $store->append;
5889
$store->set($iter, 0, fromutf($row[0]), 1, $row[1]);
5895
#****f* lyricue/copy_item
5901
# Copy the selected item in the playlist
5903
# Extra item in the playlist
5908
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
5909
my ($model, $iter) = $selection->get_selected;
5911
debug("Duplicate item clicked ");
5913
my $item = $model->get($iter, 2);
5914
my $query = "SELECT * FROM playlist WHERE playorder=" . $item;
5915
my $sth = $lyricDbh->prepare($query)
5916
|| display_fatal($errorcodes->{'sqlprepare'},
5917
$! . "\nSQL: " . $query);
5918
my $rv = $sth->execute
5919
|| display_fatal($errorcodes->{'sqlexecute'},
5920
$! . "\nSQL: " . $query);
5921
my $row = $sth->fetchrow_hashref();
5923
if ($row->{'type'} ne "play") {
5924
my $query = "SELECT MAX(playorder) FROM playlist";
5925
my $sth = $lyricDbh->prepare($query)
5926
|| display_fatal($errorcodes->{'sqlprepare'},
5927
$! . "\nSQL: " . $query);
5928
my $rv = $sth->execute
5929
|| display_fatal($errorcodes->{'sqlexecute'},
5930
$! . "\nSQL: " . $query);
5931
my @row2 = $sth->fetchrow_array();
5935
"INSERT INTO playlist (playorder,playlist,data,type) VALUES ("
5937
. $row->{'playlist'} . ", \""
5940
. $row->{'type'} . "\")";
5942
$sth = $lyricDbh->prepare($query)
5943
|| display_fatal($errorcodes->{'sqlprepare'},
5944
$! . "\nSQL: " . $query);
5946
|| display_fatal($errorcodes->{'sqlexecute'},
5947
$! . "\nSQL: " . $query);
5956
#****f* lyricue/begin_loop
5962
# Initialise the automatic page looping
5968
debug("Initialising a playlist item loop");
5971
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
5972
my ($model, $iter) = $selection->get_selected;
5975
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogLoop', 'lyricue');
5976
$loopxml->signal_autoconnect_from_package('');
5977
$loopxml->get_widget('dialogLoop')->{user_data} = $model->get($iter, 2);
5978
$loopxml->get_widget('buttonLoopOK')
5979
->signal_connect('clicked', "establish_timer", $loopxml);
5985
#****f* lyricue/establish_timer
5989
# establish_timer ($widget, $loopxml)
5991
# Create a new timer
5996
sub establish_timer {
5997
my ($widget, $loopxml) = @_;
5999
reset_timer($globals->{'timer'});
6001
my $seconds = $loopxml->get_widget('spinLoopSeconds')->get_value_as_int();
6003
$loopxml->get_widget('spinLoopMilliseconds')->get_value_as_int();
6005
debug("Seconds = " . $seconds . " ||| Milliseconds = " . $milliseconds);
6007
my $interval = ($seconds * 1000) + $milliseconds;
6008
if ($interval < 50) {
6010
debug("Interval too small - defaulting to 50 milliseconds");
6013
#Find the id of the list we will be looping (could be a playlist, sublist or song)
6014
my $query = "SELECT data FROM playlist WHERE playorder ="
6015
. $loopxml->get_widget('dialogLoop')->{user_data};
6017
my $sth = $lyricDbh->prepare($query)
6018
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
6019
my $rv = $sth->execute
6020
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
6021
my @row = $sth->fetchrow_array();
6022
my $parent = $row[0];
6024
update_display("display", $loopxml->get_widget('dialogLoop')->{user_data},
6027
my @data = ("display", "next_page", "loop;".$parent);
6029
$globals->{'timer'} = Glib::Timeout->add($interval, \&update_loop, \@data);
6030
debug("Set loop advance timer to " . $interval . " milliseconds.");
6031
close_dialog($widget);
6039
#****f* lyricue/update_loop
6043
# update_loop($data)
6053
debug("Loop triggered");
6054
update_display($$data[0], $$data[1], $$data[2]);
6060
#****f* lyricue/load_config
6066
# Loading Preferences
6073
debug("Loading Preferences");
6076
$conf->{'App'}[$appCount++] = gettext("Load Lyricue Display").";lyricue_display";
6077
$conf->{'App'}[$appCount++] = gettext("Close Lyricue Display").";lyricue_remote close";
6078
open(CONFIG, $globals->{'configfile'})
6079
|| display_fatal($errorcodes->{'fileopenread'} . $globals->{'configfile'},
6080
$! . "\nSQL: " . $query);
6081
binmode(CONFIG, ":utf8");
6082
$conf->{'Width'} = 0;
6083
$conf->{'Height'} = 0;
6087
my @line = split(/=/);
6089
$line[0] =~ s/ *$//g;
6092
$line[1] =~ s/ *$//g;
6097
$line[1] =~ s/^ *//g;
6098
if ($line[0] eq "App") {
6100
foreach my $app (gettext("Load Lyricue Display"), gettext("Close Lyricue Display"), "Load Lyricue Display", "Close Lyricue Display") {
6101
if ($line[1] =~ /^$app;/) {
6106
$conf->{'App'}[$appCount++] = $line[1];
6109
$conf->{$line[0]} = $line[1];
6114
$conf->{'BibleCount'} = $bibleCount;
6115
$conf->{'AppCount'} = $appCount;
6116
$conf->{'Bibles'} = get_bibles();
6117
if (!defined $conf->{'HighlightColour'}) {
6118
$conf->{'HighlightColour'} = "yellow";
6120
if (defined $globals->{'force_sqlite'} && ($globals->{'force_sqlite'})) {
6121
$conf->{'DatabaseType'} = "SQLite";
6123
if (!defined $conf->{'TrayIcons'}) {
6124
$conf->{'TrayIcons'} = "1";
6126
if ($conf->{'TrayIcons'} ne "1") {
6127
$globals->{'trayicon'} = FALSE;
6129
if (!defined $conf->{'DatabaseType'}) {
6130
$conf->{'DatabaseType'} = "mysql";
6132
$conf->{'LoopText'} = "";
6133
if (defined $conf->{'Loop'}) {
6134
if ($conf->{'Loop'} eq "1") {
6135
$conf->{'LoopText'} = "loop";
6138
if (!($conf->{'BGImage'} =~ /;/)) {
6139
$conf->{'BGImage'} = "db;" . $conf->{'BGImage'};
6141
if (!($conf->{'ImageDirectory'})) {
6142
$conf->{'ImageDirectory'} =
6143
Glib::get_user_special_dir('pictures') . "/";
6145
if (!($conf->{'BGDirectory'})) {
6146
$conf->{'BGDirectory'} = Glib::get_user_special_dir('pictures') . "/";
6149
if ($conf->{'CentreX'}) {
6150
if ($conf->{'CentreX'}) {
6151
$conf->{'HorizontalLocation'} = "Centre";
6153
$conf->{'HorizontalLocation'} = "Left";
6157
if ($conf->{'CentreY'}) {
6158
if ($conf->{'CentreY'}) {
6159
$conf->{'VerticalLocation'} = "Centre";
6161
$conf->{'VerticalLocation'} = "Top";
6164
if(!defined $conf->{'DefaultTransition'}) {
6165
$conf->{'DefaultTransition'} = "Fade";
6167
if ( (!defined $conf->{'ProjectorHost'})
6168
|| ($globals->{'host'} ne "localhost"))
6170
$conf->{'ProjectorHost'} = $globals->{'host'};
6172
$globals->{'host'} = $conf->{'ProjectorHost'};
6174
if ( (!defined $conf->{'DBHost'})
6175
|| ($globals->{'mysqlhost'} ne "localhost"))
6177
$conf->{'DBHost'} = $globals->{'mysqlhost'};
6179
$globals->{'mysqlhost'} = $conf->{'DBHost'};
6189
#****f* lyricue/save_state
6201
$config->{'FrameLeft'} =
6202
$widgets->{'main'}->get_widget('hpanedMainLeft')->get_position();
6203
$config->{'FrameRight'} =
6204
$widgets->{'main'}->get_widget('hpanedMainRight')->get_position();
6205
my ($width, $height) =
6206
$widgets->{'main'}->get_widget('windowMain')->get_size();
6207
if (defined $widgets->{'main'}->get_widget('vpanedMain')) {
6208
$config->{'FrameMain'} =
6210
$widgets->{'main'}->get_widget('vpanedMain')->get_position());
6216
#****f* lyricue/save_and_close_prefs
6218
# save_and_close_prefs
6220
# save_and_close_prefs()
6222
# Save and close preferences
6227
sub save_and_close_prefs {
6228
debug("Save and close preferences");
6230
$globals->{'configured'} = TRUE;
6231
close_dialog($widgets->{'prefs'}->get_widget('dialogPrefs'));
6236
#****f* lyricue/save_preferences
6240
# save_preferences()
6242
# Saving preferences
6247
sub save_preferences {
6248
debug("Saving preferences");
6250
$widgets->{'prefs'}->get_widget('entryPrefMain')->get_text();
6251
$config->{'Header'} =
6252
$widgets->{'prefs'}->get_widget('entryPrefHeader')->get_text();
6253
$config->{'Footer'} =
6254
$widgets->{'prefs'}->get_widget('entryPrefFooter')->get_text();
6256
$widgets->{'prefs'}->get_widget('entryPrefOSD')->get_text();
6257
$config->{'Colour'} =
6258
$widgets->{'prefs'}->get_widget('entryPrefColour')->get_text();
6259
$config->{'ShadowColour'} =
6260
$widgets->{'prefs'}->get_widget('entryPrefShadowColour')->get_text();
6261
$config->{'ShadowSize'} =
6262
$widgets->{'prefs'}->get_widget('spinPrefShadow')->get_value();
6263
$config->{'Height'} =
6264
$widgets->{'prefs'}->get_widget('spinPrefHeight')->get_value();
6265
$config->{'Width'} =
6266
$widgets->{'prefs'}->get_widget('spinPrefWidth')->get_value();
6267
$config->{'OverscanH'} =
6268
$widgets->{'prefs'}->get_widget('spinPrefOverscanH')->get_value();
6269
$config->{'OverscanV'} =
6270
$widgets->{'prefs'}->get_widget('spinPrefOverscanV')->get_value();
6272
$widgets->{'prefs'}->get_widget('checkPrefLoop')->get_active() ? 1 : 0;
6273
$config->{'Audit'} =
6274
$widgets->{'prefs'}->get_widget('checkPrefAudit')->get_active() ? 1 : 0;
6275
$config->{'DynamicPreview'} =
6276
$widgets->{'prefs'}->get_widget('checkPrefView')->get_active() ? 1 : 0;
6277
$config->{'Miniview'} =
6278
$widgets->{'prefs'}->get_widget('checkPrefMiniview')->get_active()
6281
$config->{'Xinerama'} =
6282
$widgets->{'prefs'}->get_widget('checkPrefXinerama')->get_active()
6285
$config->{'GeometryOverride'} =
6286
$widgets->{'prefs'}->get_widget('entryPrefWindowOffset')->get_text();
6289
foreach my $value ("Top", "Bottom", "Centre") {
6291
fromutf(gettext($value)) eq ucfirst(
6292
$widgets->{'prefs'}->get_widget('comboPrefVertical')
6302
$widgets->{'prefs'}->get_widget('comboPrefVertical')
6303
->get_active_text();
6305
$config->{'VerticalLocation'} = $set;
6308
foreach my $value ("Left", "Right", "Centre") {
6310
fromutf(gettext($value)) eq ucfirst(
6311
$widgets->{'prefs'}->get_widget('comboPrefHorizontal')
6319
fromutf(gettext($value)) eq ucfirst(
6320
$widgets->{'prefs'}->get_widget('comboPrefJustification')
6330
$widgets->{'prefs'}->get_widget('comboPrefHorizontal')
6331
->get_active_text();
6335
$widgets->{'prefs'}->get_widget('comboPrefJustification')
6336
->get_active_text();
6338
$config->{'HorizontalLocation'} = $set;
6339
$config->{'Justification'} = $set2;
6341
foreach my $value ("Fade", "None") {
6343
fromutf(gettext($value)) eq ucfirst(
6344
$widgets->{'prefs'}->get_widget('comboPrefDefTrans')
6354
$widgets->{'prefs'}->get_widget('comboPrefDefTrans')
6355
->get_active_text();
6357
$config->{'DefaultTransition'} = $set;
6359
$config->{'BGImage'} =
6360
$widgets->{'prefs'}->get_widget('imagePrefBG')->{user_data};
6361
$config->{'SpecialSong'} =
6362
$widgets->{'prefs'}->get_widget('entryPrefSpecialSong')->get_text();
6363
$config->{'SpecialImage'} =
6364
$widgets->{'prefs'}->get_widget('entryPrefSpecialImage')->get_text();
6365
$config->{'SpecialBack'} =
6366
$widgets->{'prefs'}->get_widget('entryPrefSpecialBack')->get_text();
6367
$config->{'ImageDirectory'} =
6368
$widgets->{'prefs'}->get_widget('filePrefSpecialImagedir')->get_label();
6369
$config->{'ImageDirectory'} =~ s/^\~/$ENV{'HOME'}/;
6370
$config->{'BGDirectory'} =
6371
$widgets->{'prefs'}->get_widget('filePrefSpecialBGdir')->get_label();
6372
$config->{'BGDirectory'} =~ s/^\~/$ENV{'HOME'}/;
6373
$config->{'TrayIcons'} = $config->{'TrayIcons'};
6375
my $db_changed = FALSE;
6376
if ($widgets->{'prefs'}->get_widget('radioPrefDBMysql')->get_active()) {
6377
if ($config->{'DatabaseType'} ne "mysql") {
6380
$config->{'DatabaseType'} = "mysql";
6382
if ($config->{'DatabaseType'} ne "SQLite") {
6385
$config->{'DatabaseType'} = "SQLite";
6388
$config->{'DefBible'} =
6389
$widgets->{'prefs'}->get_widget('entryPrefBible')->get_text();
6392
write_config(FALSE);
6401
preview_display("reconfig", "", "", "MINI");
6402
update_display("reconfig", "", "");
6403
preview_display("display", "current", "", "MINI");
6404
update_display("display", "current", "");
6409
#****f* lyricue/write_config
6415
# Writing preferences
6422
debug("Writing preferences");
6424
# Backup config table
6425
my $query = "DELETE FROM config_old";
6426
my $sth = $lyricDbh->prepare($query)
6427
|| display_fatal($errorcodes->{'sqlprepare'},
6428
$! . "\nSQL: " . $query);
6429
my $rv = $sth->execute
6430
|| display_fatal($errorcodes->{'sqlexecute'},
6431
$! . "\nSQL: " . $query);
6432
$query = "INSERT config_old SELECT * from config";
6433
$sth = $lyricDbh->prepare($query)
6434
|| display_fatal($errorcodes->{'sqlprepare'},
6435
$! . "\nSQL: " . $query);
6437
|| display_fatal($errorcodes->{'sqlexecute'},
6438
$! . "\nSQL: " . $query);
6439
$query = "DELETE FROM config";
6440
$sth = $lyricDbh->prepare($query)
6441
|| display_fatal($errorcodes->{'sqlprepare'},
6442
$! . "\nSQL: " . $query);
6444
|| display_fatal($errorcodes->{'sqlexecute'},
6445
$! . "\nSQL: " . $query);
6449
unlink $globals->{'configfile'} . ".bak";
6450
rename($globals->{'configfile'}, $globals->{'configfile'} . ".bak");
6452
open(CONFIG, ">$globals->{'configfile'}")
6453
|| display_fatal($errorcodes->{'fileopenwrite'}, $!);
6454
binmode(CONFIG, ":utf8");
6457
foreach (sort keys(%$config)) {
6458
if ((!/^Bible/) && (!/^App/) && (!/^LoopText/)) {
6460
print CONFIG $_ . " = " . $config->{$_} . "\n";
6462
$query = "INSERT INTO config ( config_key, config_value ) VALUES (\"".$_."\", \"".$config->{$_}."\")";
6464
$sth = $lyricDbh->prepare($query)
6465
|| display_fatal($errorcodes->{'sqlprepare'},
6466
$! . "\nSQL: " . $query);
6468
|| display_fatal($errorcodes->{'sqlexecute'},
6469
$! . "\nSQL: " . $query);
6472
foreach (0 .. $config->{'AppCount'} - 1) {
6474
print CONFIG "App = " . $config->{'App'}[$_] . "\n";
6476
$query = "INSERT INTO config ( config_key, config_value ) VALUES ( \"App\", \"".$config->{'App'}[$_]."\")";
6478
$sth = $lyricDbh->prepare($query)
6479
|| display_fatal($errorcodes->{'sqlprepare'},
6480
$! . "\nSQL: " . $query);
6482
|| display_fatal($errorcodes->{'sqlexecute'},
6483
$! . "\nSQL: " . $query);
6487
preview_display("reconfig", "", "", "MINI");
6488
update_display("reconfig", "", "");
6489
update_display("status", "", "");
6495
# Add the filename to the playlist
6498
#****f* lyricue/file_ok_sel
6502
# file_ok_sel($widget, $filexml)
6504
# Add filename to playlist
6512
my ($widget, $filexml) = @_;
6513
debug("Add filename to playlist");
6515
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
6516
my @filenames = $filexml->get_widget('dialogFileChooser')->get_filenames;
6517
foreach (@filenames) {
6518
do_add_file($_, $main_playlist);
6521
close_dialog($widget);
6526
# Add the filename to the playlist
6529
#****f* lyricue/do_add_file
6533
# do_add_file($file, $playlist)
6535
# do_add_file: file=
6543
my ($file, $playlist) = @_;
6544
debug("do_add_file: file=" . $file);
6545
if ($globals->{'unoconv'} ne "") {
6546
if (($file =~ /ppt$/i) || ($file =~ /odp$/i) || ($file =~ /pptx$/)) {
6549
debug("Adding ppt/odp presentation");
6550
my $dialog = Gtk2::MessageDialog->new(
6551
$widgets->{'main'}->get_widget('windowMain'),
6552
'destroy-with-parent', 'info', 'none',
6553
gettext("Importing presentation"));
6554
$dialog->show_all();
6557
$target =~ s/^.*\///g;
6558
$target =~ s/'//g; # fix handling of ' in filename
6560
# Add 'ppt' to end of 'pptx' files so unoconv will handle them
6561
if ($target =~ /pptx$/ ) {
6564
my $tmpdir = tempdir("lyricue-XXXX", DIR => "/var/tmp", CLEANUP => 0);
6566
"cp \"" . $file . "\" \"" . $tmpdir . "/" . $target . "\"";
6575
$globals->{'unoconv'}
6584
my $ret = opendir DIR, $tmpdir;
6586
foreach my $filename (sort readdir(DIR)) {
6587
if (($filename =~ /\.html$/) || ($filename eq $target)) {
6588
unlink $tmpdir . "/" . $filename;
6589
} elsif ($filename =~ /^img.*jpg$/) {
6590
my $count = $filename;
6591
$count =~ s/^.*[^0-9]([0-9]*)\..*$/$1/g;
6593
rename $tmpdir . "/" . $filename,
6594
$tmpdir . "/page_" . $count . ".jpg";
6595
$try = 10; # Don't retry
6601
"rm " . $tmpdir . "/*.html \"" . $tmpdir . "/" . $target . "\"";
6606
do_add_directory($tmpdir, $target);
6611
if ($globals->{'convert'} ne "") {
6612
if (($file =~ /pdf$/)) {
6616
debug("Adding pdf presentation");
6617
my $dialog = Gtk2::MessageDialog->new(
6618
$widgets->{'main'}->get_widget('windowMain'),
6619
'destroy-with-parent', 'info', 'none',
6620
gettext("Importing presentation"));
6621
$dialog->show_all();
6623
$target =~ s/^.*\///g;
6624
$target =~ s/'//g; # fix handling of ' in filename
6625
my $tmpdir = tempdir("lyricue-XXXX", DIR => "/var/tmp", CLEANUP => 0);
6627
$globals->{'convert'} . " \"" . $file . "\" " . $tmpdir . "/temp.jpg";
6631
# Clean up directory
6632
my $ret = opendir DIR, $tmpdir;
6635
foreach my $filename (sort readdir(DIR)) {
6637
if ($filename =~ /^temp.*jpg$/) {
6638
my $count = $filename;
6639
$count =~ s/^.*([0-9]+).*$/$1/g;
6641
rename $tmpdir . "/" . $filename,
6642
$tmpdir . "/page_" . $count . ".jpg";
6647
do_add_directory($tmpdir, $target);
6652
if (($file ne "") && ((-r $file) || ($file =~ /:\/\//))) {
6654
# Find next playorder
6656
my $query = "SELECT MAX(playorder) FROM playlist";
6658
my $sth = $lyricDbh->prepare($query)
6659
|| display_fatal($errorcodes->{'sqlprepare'},
6660
$! . "\nSQL: " . $query);
6661
my $rv = $sth->execute
6662
|| display_fatal($errorcodes->{'sqlexecute'},
6663
$! . "\nSQL: " . $query);
6665
if (@row = $sth->fetchrow_array()) {
6668
$playorder = $row[0] + 1;
6672
# Add item to playlist
6674
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
6676
"INSERT INTO playlist (playorder, playlist, type, data) VALUES ("
6682
$sth = $lyricDbh->prepare($query)
6683
|| display_fatal($errorcodes->{'sqlprepare'},
6684
$! . "\nSQL: " . $query);
6686
|| display_fatal($errorcodes->{'sqlexecute'},
6687
$! . "\nSQL: " . $query);
6693
#****f* lyricue/create_sublist
6699
# Display the 'new sublist' dialog
6705
sub create_sublist {
6707
debug("Create sublist");
6708
create_dialogSublist($widget);
6715
#****f* lyricue/new_sublist_from_xml
6717
# new_sublist_from_xml
6719
# new_sublist_from_xml($widget, $sublistxml)
6728
sub new_sublist_from_xml {
6729
my ($widget, $sublistxml) = @_;
6730
new_sublist($sublistxml->get_widget('entryPromptE')->get_text());
6731
close_dialog($sublistxml->get_widget('dialogPromptEntry'));
6736
#****f* lyricue/new_sublist
6742
# Create sublist entry in database
6745
# Closes sublist dialog
6746
# Adds sublist to current playlist
6747
# Calls update_playlist to refresh playlist
6748
# Returns sublist id
6753
debug("new sublist");
6754
my ($row, $sth, $rv, $parentid);
6756
#Determine the id of the main playlist
6758
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
6760
#Find out the id for the playlists table
6761
my $playlistsid = 1;
6762
$query = "SELECT MAX(id) FROM playlists";
6763
$sth = $lyricDbh->prepare($query)
6764
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
6766
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
6767
if ($row = $sth->fetchrow_hashref()) {
6768
if ($row->{'MAX(id)'}) {
6769
$playlistsid = $row->{'MAX(id)'} + 1;
6773
#Find out the playorder for the playlist table
6775
$query = "SELECT MAX(playorder) FROM playlist";
6776
$sth = $lyricDbh->prepare($query)
6777
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
6779
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
6780
if ($row = $sth->fetchrow_hashref()) {
6781
if ($row->{'MAX(playorder)'}) {
6782
$playorder = $row->{'MAX(playorder)'} + 1;
6786
#create sublist playlist
6788
"INSERT INTO playlists (id, title, ref) VALUES ("
6789
. $playlistsid . " ,'"
6790
. $sublist . "','')";
6791
$sth = $lyricDbh->prepare($query)
6792
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
6794
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
6796
#link sublist to main playlist
6798
"INSERT INTO playlist (playorder,playlist,type,data,transition) VALUES ("
6802
. $playlistsid . " ,0)";
6804
$sth = $lyricDbh->prepare($query)
6805
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
6807
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
6810
return $playlistsid;
6815
#****f* lyricue/move_item_to_sublist
6817
# move_item_to_sublist
6819
# move_item_to_sublist ($item, $sublistid)
6821
# Move a playlist item to become a child of a sublist
6823
# $item - playorder of the item to be moved
6824
# $sublistid - id of the sublist the item is to be a child of
6826
# Alters database entry for playlist item to make sublist its parent
6827
# Calls update_playlist to refresh playlist
6830
sub move_item_to_sublist {
6831
my ($widget, $sublistid) = @_;
6832
debug("move item to sublist");
6834
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
6835
my ($model, $iter) = $selection->get_selected;
6837
my $plitem = $model->get($iter, 2);
6838
debug("Moving item " . $plitem . " to playlist " . $sublistid);
6841
"UPDATE playlist SET playlist = "
6843
. " WHERE playorder = "
6846
my $sth = $lyricDbh->prepare($query)
6847
|| display_fatal($errorcodes->{'sqlprepare'},
6848
$! . "\nSQL: " . $query);
6849
my $rv = $sth->execute
6850
|| display_fatal($errorcodes->{'sqlexecute'},
6851
$! . "\nSQL: " . $query);
6859
#****f* lyricue/find_more_children
6861
# find_more_children
6863
# find_more_children ($parentid)
6865
# Find all the children of a given playlist item
6867
# $parentid - The playlist id of the 'parent'
6869
# Returns an array of playlist ids representing children of the parent
6872
sub find_more_children {
6873
my ($parentid) = @_;
6874
debug("Looking for children");
6878
"SELECT data FROM playlist WHERE playlist = "
6880
. " AND type = 'sub'";
6883
my $sth = $lyricDbh->prepare($query)
6884
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
6885
my $rv = $sth->execute
6886
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
6887
while ($row = $sth->fetchrow_hashref()) {
6888
@kiddies = (@kiddies, $row->{'data'});
6889
@kiddies = (@kiddies, find_more_children($row->{'data'}));
6897
#****f* lyricue/associate_bg
6901
# associate_bg ($imagefile)
6903
# To associate the an background image with a playlist item
6905
# $imagefile - file path & name of image to associate with item
6907
# Stores image name, playlist order pair in db 'associations' table
6911
my ($imagefile) = @_;
6913
debug("Associating bg " . $imagefile . " with " . $ASSOCIATE[0]);
6915
my $query = "DELETE FROM associations WHERE playlist=" . $ASSOCIATE[0];
6916
my $sth = $lyricDbh->prepare($query)
6917
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
6919
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
6922
"INSERT INTO associations (id,playlist,imagename, absoluteparent) VALUES(0, "
6923
. $ASSOCIATE[0] . ", '"
6925
. $ASSOCIATE[1] . ")";
6926
$sth = $lyricDbh->prepare($query)
6927
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
6929
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
6937
#****f* lyricue/prepare_for_association
6939
# prepare_for_association
6941
# prepare_for_association ()
6943
# Set up the ASSOCIATE array
6946
# Updated ASSOCIATE array
6949
sub prepare_for_association {
6951
debug("prepare for association");
6953
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
6954
my ($model, $iter) = $selection->get_selected;
6957
# Change ASSOCIATE array to contain playorder of list item,
6960
$model->get($iter, 2),
6961
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data}
6963
debug("Waiting for an image click in order to associate");
6970
#****f* lyricue/disassociate_bg
6974
# disassociate_bg ()
6976
# To disssociate the current background image from a playlist item
6979
# If an association record exists in db, it is removed.
6982
sub disassociate_bg {
6986
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
6987
my ($model, $iter) = $selection->get_selected;
6989
debug("Disassociating image from " . $model->get($iter, 2));
6991
"DELETE FROM associations WHERE playlist=" . $model->get($iter, 2);
6993
my $sth = $lyricDbh->prepare($query)
6994
|| display_fatal($errorcodes->{'sqlprepare'},
6995
$! . "\nSQL: " . $query);
6997
|| display_fatal($errorcodes->{'sqlexecute'},
6998
$! . "\nSQL: " . $query);
7006
#****f* lyricue/clear_associations
7008
# clear_associations
7010
# clear_associations ()
7012
# Clears all image-playlist item associations linked to current playlist
7015
# Clears the associations table in lyricDb
7018
sub clear_associations {
7020
debug("Disassociating images from all playlist items");
7022
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
7024
my $query = "DELETE FROM associations WHERE absoluteparent=" . $parentid;
7026
my $sth = $lyricDbh->prepare($query)
7027
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
7029
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
7038
#****f* lyricue/init_mainWindow
7044
# Initializing main window
7049
sub init_mainWindow {
7050
debug("Initializing main window");
7052
# Setup file chooser
7054
# Setup bible browser
7055
biblebrowser_init();
7057
# Load bg thumbnails
7058
my $scaled = create_pixbuf(
7059
$config->{'BGImage'},
7060
$globals->{'icon_width'},
7061
$globals->{'icon_height'}
7064
my $pixmap = Gtk2::Image->new_from_pixbuf($scaled);
7065
$widgets->{'pixmapCurr'} = $pixmap;
7066
$widgets->{'buttonCurr'} = new Gtk2::Button();
7067
$widgets->{'buttonCurr'}->add($widgets->{'pixmapCurr'});
7068
$widgets->{'buttonCurr'}->{user_data} = $config->{'BGImage'};
7069
$widgets->{'main'}->get_widget('vboxCurrentBG')
7070
->pack_start($widgets->{'buttonCurr'}, FALSE, FALSE, 0);
7071
$widgets->{'pixmapCurr'}->show();
7072
$widgets->{'buttonCurr'}->show();
7073
$widgets->{'buttonCurr'}
7074
->signal_connect("clicked", "backdrop_preview_clicked");
7076
$scaled = create_pixbuf(
7077
$config->{'BGImage'},
7078
$globals->{'icon_width'},
7079
$globals->{'icon_height'}
7082
my $pixmap = Gtk2::Image->new_from_pixbuf($scaled);
7083
$widgets->{'pixmapPrev'} = $pixmap;
7084
$widgets->{'buttonPrev'} = new Gtk2::Button();
7085
$widgets->{'buttonPrev'}->add($widgets->{'pixmapPrev'});
7086
$widgets->{'buttonPrev'}->{user_data} = $config->{'BGImage'};
7087
$widgets->{'main'}->get_widget('vboxPrevBG')
7088
->pack_start($widgets->{'buttonPrev'}, FALSE, FALSE, 0);
7089
$widgets->{'pixmapPrev'}->show();
7090
$widgets->{'buttonPrev'}->show();
7091
$widgets->{'buttonPrev'}
7092
->signal_connect("clicked", "backdrop_preview_clicked");
7095
# Update list of background/image directories
7099
# Setup Available list and blank playlist
7100
$widgets->{'main'}->get_widget('treeAvailable')->set_enable_search(TRUE);
7101
$widgets->{'main'}->get_widget('treeAvailable')->set_search_column(0);
7103
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data} = 0;
7105
# Update the bible menu
7108
# Update the application menu
7109
my $menutop2 = Gtk2::Menu->new();
7112
foreach (0 .. $config->{'AppCount'} - 1) {
7113
my $app = $config->{'App'}[$_];
7114
$app =~ s/^(.*?);.*$/$1/g;
7116
$appMenu[$_] = Gtk2::MenuItem->new_with_label($app);
7117
$appMenu[$_]->signal_connect("activate", "execute_app", $_);
7119
$menutop2->append($appMenu[$_]);
7121
$widgets->{'main'}->get_widget('applications1')->set_submenu($menutop2);
7124
$widgets->{'main'}->get_widget('treeAvailable')
7125
->drag_source_set(['button1_mask'], ['copy'],
7126
{'target' => "STRING", 'flags' => [], 'info' => 0});
7127
$widgets->{'main'}->get_widget('iconviewBack')
7128
->drag_source_set(['button1_mask'], ['copy'],
7129
{'target' => "STRING", 'flags' => [], 'info' => 0});
7130
$widgets->{'main'}->get_widget('iconviewImage')
7131
->drag_source_set(['button1_mask'], ['copy'],
7132
{'target' => "STRING", 'flags' => [], 'info' => 0});
7133
$widgets->{'main'}->get_widget('treePlaylist')->drag_source_set(
7136
{'target' => "STRING", 'flags' => [], 'info' => 0}
7138
$widgets->{'main'}->get_widget('treePlaylist')->drag_dest_set(
7141
{'target' => "STRING", 'flags' => [], 'info' => 0}
7147
# Show the window finally
7148
$widgets->{'main'}->get_widget('windowMain')->show;
7149
if (!(defined($globals->{'run_windowed'}) && ($globals->{'run_windowed'})))
7151
$widgets->{'main'}->get_widget('windowMain')->maximize;
7156
# Adjust frame sizes
7157
my ($width, $height) =
7158
$widgets->{'main'}->get_widget('windowMain')->get_size();
7159
if ((defined $config->{'FrameRight'}) && ($config->{'FrameRight'} != 0)) {
7160
$widgets->{'main'}->get_widget('hpanedMainRight')
7161
->set_position($config->{'FrameRight'});
7162
$widgets->{'main'}->get_widget('hpanedMainLeft')
7163
->set_position($config->{'FrameLeft'});
7165
if ($globals->{'access'} =~ /p/) {
7166
$widgets->{'main'}->get_widget('hpanedMainLeft')
7167
->set_position($width / 5 * 2);
7168
$widgets->{'main'}->get_widget('hpanedMainRight')
7169
->set_position($width / 5 * 2);
7172
if (defined $widgets->{'main'}->get_widget('vpanedMain')) {
7173
if ((defined $config->{'FrameMain'}) && ($config->{'FrameMain'} != 0)) {
7174
$widgets->{'main'}->get_widget('vpanedMain')
7175
->set_position($height - $config->{'FrameMain'});
7177
$widgets->{'main'}->get_widget('vpanedMain')
7178
->set_position($height - 125);
7182
$globals->{'hand_cursor'} = Gtk2::Gdk::Cursor->new('hand2');
7183
$globals->{'text_cursor'} = Gtk2::Gdk::Cursor->new('xterm');
7188
#****f* lyricue/bgdir_list
7194
# Loading ".$type." directory list
7202
debug("Loading " . $type . " directory list");
7205
my $store = Gtk2::ListStore->new('Glib::String', 'Glib::String');
7206
my $iter = $store->append;
7207
$store->set($iter, 0, fromutf(gettext("Select Category")), 1, "");
7209
my ($combo, $special, $dirname);
7210
if ($type eq "bg") {
7211
$combo = $widgets->{'main'}->get_widget('comboBGDirList');
7212
$special = $config->{'SpecialBack'};
7213
$dirname = $config->{'BGDirectory'};
7215
$combo = $widgets->{'main'}->get_widget('comboImgDirList');
7216
$special = $config->{'SpecialImage'};
7217
$dirname = $config->{'ImageDirectory'};
7219
$combo->set_model($store);
7220
my $renderer = Gtk2::CellRendererText->new;
7221
$combo->pack_start($renderer, TRUE);
7222
$combo->add_attribute($renderer, text => 0);
7223
my @dbcategories = ();
7224
my @dircategories = ();
7225
if ($special ne "") {
7226
my ($type, $id) = split /;/, $special;
7231
$id = "00000" . $id;
7232
if ($type eq "db") {
7233
push @dbcategories, $id;
7235
push @dircategories, $id;
7239
# Add categories from mediaDb
7241
"SELECT DISTINCT category FROM media WHERE type=\""
7243
. "\" AND category !=\""
7245
. "\" ORDER BY category";
7246
my $sth = $mediaDbh->prepare($query)
7247
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
7248
my $rv = $sth->execute
7249
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
7250
while ($row = $sth->fetchrow_hashref()) {
7251
push @dbcategories, $row->{'category'};
7254
foreach $cat (sort @dbcategories) {
7255
$cat =~ s/^00000//g;
7256
debug("Adding image dir button for db-" . $cat);
7257
my $iter = $store->append;
7258
$store->set($iter, 0, $cat, 1, "db");
7262
# Add categories from directories
7264
$dirname =~ s/^\~/$ENV{'HOME'}/;
7265
my $ret = opendir DIR, $dirname;
7267
foreach $file (sort readdir(DIR)) {
7268
if (!($file =~ /^\./) && (-d $dirname . "/" . $file)) {
7269
push @dircategories, $file;
7275
# Add a blank entry for files not in a subdirectory
7276
push @dircategories, "/";
7278
foreach $cat (sort @dircategories) {
7279
$cat =~ s/^00000//g;
7280
debug("Adding image dir button for dir-" . $cat);
7281
my $iter = $store->append;
7282
$store->set($iter, 0, $cat, 1, "dir");
7284
$combo->set_active(0);
7289
#****f* lyricue/bgdir_change
7293
# bgdir_change ($directory)
7295
# Clears background image preview buttions
7296
# Calls imgdir_load to create new buttons
7298
# $category - background image category to load images from
7299
# $type - 'dir' or 'db'
7301
# Updated background preview buttons
7306
my $iter = $widget->get_active_iter;
7307
my ($category, $type) = $widget->get_model->get($iter, 0, 1);
7308
debug( "Changing background source category to "
7312
debug("Destroying old images");
7313
$globals->{'category'} = $category;
7314
imgdir_load($widgets->{'main'}->get_widget('iconviewBack'),
7315
"bg", $category, $type);
7316
debug("Background category change complete");
7320
#****f* lyricue/imgdir_change
7324
# imgdir_change ($directory)
7326
# Clears image preview buttions
7327
# Calls imgdir_load to create new buttons
7329
# $category - image category to load images from
7330
# $type - 'dir' or 'db'
7332
# Updated background preview buttons
7337
my $iter = $widget->get_active_iter;
7338
my ($category, $type) = $widget->get_model->get($iter, 0, 1);
7340
"Changing image source category to " . $category . " of type " . $type);
7341
debug("Destroying old images");
7342
$globals->{'category'} = $category;
7343
imgdir_load($widgets->{'main'}->get_widget('iconviewImage'),
7344
"img", $category, $type);
7345
debug("Image category change complete");
7350
#****f* lyricue/imgdir_load
7354
# imgdir_load ($category)
7356
# Create new preview pixmaps and buttons
7358
# $category - background image category to load images from
7360
# Updated background preview buttons
7364
my ($iconview, $section, $category, $type) = @_;
7367
# update list of available backdrops
7368
debug("Loading new preview images from: " . $type . ";" . $category);
7372
Gtk2::ListStore->new('Glib::String', 'Gtk2::Gdk::Pixbuf', 'Glib::String');
7373
$iconview->set_model($store);
7374
$iconview->set_text_column(0);
7375
$iconview->set_pixbuf_column(1);
7377
if ($type eq "db") {
7379
"SELECT id,description FROM media WHERE category=\""
7381
. "\" AND type=\"bg\" ORDER BY description";
7382
my $sth = $mediaDbh->prepare($query)
7383
|| display_fatal($errorcodes->{'sqlprepare'},
7384
$! . "\nSQL: " . $query);
7385
my $rv = $sth->execute
7386
|| display_fatal($errorcodes->{'sqlexecute'},
7387
$! . "\nSQL: " . $query);
7388
while ($row = $sth->fetchrow_hashref()) {
7391
my $iter = $store->append;
7392
$store->set($iter, 0, $row->{'description'}, 2,
7393
$type . ";" . $row->{'id'});
7397
if ($section eq "bg") {
7398
$dirname = $config->{'BGDirectory'} . "/" . $category;
7400
$dirname = $config->{'ImageDirectory'} . "/" . $category;
7403
my $ret = opendir DIR, $dirname;
7405
foreach $file (sort readdir(DIR)) {
7406
if ((!($file =~ /^\./)) && (!(-d $dirname."/".$file))) {
7408
my $iter = $store->append;
7409
$file = fromutf($file);
7410
$store->set($iter, 0, $file, 2,
7411
$type . ";" . $dirname . "/" . $file);
7412
print $type . ";" . $dirname . "/" . $file . "\n";
7420
$globals->{'thumb_idle'} = Glib::Idle->add(\&imgdir_thumbnails, $iconview);
7425
#****f* lyricue/imgdir_thumbnails
7429
# imgdir_thumbnails ()
7431
# Load thumbnails for imagdir
7438
sub imgdir_thumbnails {
7439
my ($iconview) = @_;
7440
debug("Loading thumbnails");
7441
my $store = $iconview->get_model;
7442
my $iter = $store->get_iter_first;
7443
while (defined $iter) {
7444
my $id = $store->get_value($iter, 2);
7445
my $scaled = create_pixbuf(
7447
$globals->{'icon_width'},
7448
$globals->{'icon_height'}
7451
$store->set($iter, 1, $scaled);
7453
my $nextiter = $store->iter_next($iter);
7461
#****f* lyricue/spell_check
7467
# Use aspell to check spellling for a song
7471
# Dialog listing spelling errors on each page
7477
if ($globals->{'spell'}) {
7478
debug("Running spell checker");
7481
sort { $pageOrder{$a} cmp $pageOrder{$b} }
7485
if (!defined $widgets->{'spellAPage'}{$page}) {
7486
$widgets->{'spellAPage'}{$page} =
7487
Gtk2::Spell->new($widgets->{'textAPage'}{$page});
7496
#****f* lyricue/create_search
7500
# create_search ($topwidgets)
7502
# Create the dialog for advanced search
7504
# $topwidgets - Widgets of main window
7510
debug("Advanced search dialog opened");
7511
$widgets->{'search'} =
7512
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogSearch', 'lyricue');
7513
$widgets->{'search'}->signal_autoconnect_from_package('');
7514
my @target_table = ({'target' => "STRING", 'flags' => [], 'info' => 0},);
7515
$widgets->{'search'}->get_widget('treeSearch')
7516
->drag_source_set(['button1_mask'], ['copy'], @target_table);
7517
$widgets->{'main'}->get_widget('treePlaylist')
7518
->drag_dest_set('all', ['copy'], @target_table);
7519
my $search_text = $widgets->{'main'}->get_widget('entrySearch')->get_text();
7520
$widgets->{'search'}->get_widget('entrySearchSongs')
7521
->set_text($search_text);
7529
#****f* lyricue/add_file
7535
# Open a file dialog
7541
debug("Open a file dialog");
7542
my $filexml = Gtk2::GladeXML->new($globals->{'gladefile'},
7543
'dialogFileChooser', 'lyricue');
7544
$filexml->signal_autoconnect_from_package('');
7545
$filexml->get_widget('dialogFileChooser')
7546
->set_preview_widget(Gtk2::Image->new());
7547
$filexml->get_widget('dialogFileChooser')->set_preview_widget_active(FALSE);
7548
$filexml->get_widget('dialogFileChooser')
7549
->signal_connect("update-preview", "update_file_preview");
7550
$filexml->get_widget('buttonFileOK')
7551
->signal_connect("clicked", "file_ok_sel", $filexml);
7552
$filexml->get_widget('dialogFileChooser')->show_all();
7555
sub update_file_preview {
7557
my $image = $chooser->get_preview_widget;
7558
my $filename = $chooser->get_preview_filename;
7559
if (defined $filename && ($filename ne "")) {
7560
my $pixbuf = create_pixbuf(
7562
$globals->{'thumb_width'},
7563
$globals->{'thumb_height'}
7565
if (defined $pixbuf) {
7566
$image->set_from_pixbuf($pixbuf);
7567
$chooser->set_preview_widget_active(TRUE);
7571
$chooser->set_preview_widget_active(FALSE);
7576
#****f* lyricue/add_directory
7582
# Add a directory to the playlist
7588
debug("Add a directory to the playlist");
7589
my $d = Gtk2::FileChooserDialog->new(
7590
fromutf(gettext("Choose a Directory")),
7591
$widgets->{'main'}->get_widget('windowMain'), 'select-folder',
7592
fromutf(gettext("Cancel")) => "cancel",
7593
fromutf(gettext("OK")) => "accept",
7596
my $response = $d->run();
7597
my $dirname = $d->get_filename();
7598
if ("accept" eq $response) {
7599
debug("Choosing" . $dirname);
7602
do_add_directory($dirname, "");
7607
#****f* lyricue/do_add_directory
7611
# do_add_directory($dirname,$sublist)
7620
sub do_add_directory {
7621
my ($dirname, $sublist) = @_;
7624
opendir DIR, $dirname || return 0;
7625
foreach $file (sort readdir(DIR)) {
7626
my $type = globs($dirname . "/" . $file);
7627
if (($type =~ /^audio/) || ($type =~ /^video/) || ($type =~ /^image/)) {
7628
push @files, $dirname . "/" . $file;
7633
if ($sublist eq "") {
7634
my $sublistxml = Gtk2::GladeXML->new($globals->{'gladefile'},
7635
'dialogPromptEntry', 'lyricue');
7636
$sublistxml->signal_autoconnect_from_package('');
7637
$sublistxml->get_widget('dialogPromptEntry')
7638
->set_title(fromutf(gettext("Create new sublist")));
7639
$sublistxml->get_widget('labelPromptE')
7640
->set_text(fromutf(gettext("Name of sublist")));
7642
my $response = $sublistxml->get_widget('dialogPromptEntry')->run();
7643
if ($response eq "ok") {
7644
$sublist = $sublistxml->get_widget('entryPromptE')->get_text();
7645
close_dialog($sublistxml->get_widget('dialogPromptEntry'));
7647
close_dialog($sublistxml->get_widget('dialogPromptEntry'));
7650
debug("Sublist name: " . $sublist);
7652
my $playlist = new_sublist($sublist);
7654
@files = sort alphanum @files;
7656
foreach $file (@files) {
7657
do_add_file($file, $playlist);
7665
#****f* lyricue/add_background
7669
# add_background($widget)
7677
sub add_background {
7678
debug("add background");
7680
change_bgimage($widget);
7685
#****f* lyricue/change_bgimage
7689
# change_bgimage($widget)
7691
# Change backdrop dialog opened
7697
sub change_bgimage {
7700
debug("Change backdrop dialog opened");
7701
$widgets->{'image'} =
7702
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogImage', 'lyricue');
7703
$widgets->{'image'}->signal_autoconnect_from_package('');
7704
$widgets->{'image'}->get_widget('dialogImage')
7705
->set_title(fromutf(gettext("Choose a Background")));
7706
$widgets->{'image'}->get_widget('buttonImageAdd')
7707
->signal_connect('clicked', 'import_background');
7708
$widgets->{'image'}->get_widget('hboxImageSublist')->hide;
7709
$widgets->{'image'}->get_widget('dialogImage')->show;
7711
if ($widgets->{'image'}->get_widget('treeImage')->{user_data}
7712
&& ($widgets->{'image'}->get_widget('treeImage')->{user_data} eq "load")
7715
$widgets->{'image'}->get_widget('treeImage')->{data} = ();
7717
if ($widget->get_name() eq "buttonPrefBackground") {
7719
$widgets->{'prefs'}->get_widget('imagePrefBG')->{user_data};
7720
$widgets->{'image'}->get_widget('buttonImageOK')
7721
->set_label(fromutf(gettext("Set as Default")));
7722
$widgets->{'image'}->get_widget('buttonImageOK')
7723
->signal_connect('clicked', "set_default_backdrop");
7724
$widgets->{'image'}->get_widget('buttonImageAdd')->hide();
7725
$widgets->{'image'}->get_widget('buttonImageDelete')->hide();
7726
$widgets->{'image'}->get_widget('buttonImageChange')->hide();
7728
$widgets->{'image'}->get_widget('buttonImageCancel')->hide();
7729
$widgets->{'image'}->get_widget('buttonImageOK')
7730
->signal_connect('clicked', "close_dialog");
7731
$widgets->{'image'}->get_widget('hboxImageColour')->show();
7732
$widgets->{'image'}->get_widget('colorbuttonFontColour')
7733
->signal_connect("button_press_event", "open_dialogColour",
7736
#$widgets->{'image'}->get_widget('entryImageFontColour')
7737
#->signal_connect("changed", "change_colour_media");
7738
$widgets->{'image'}->get_widget('colorbuttonShadowColour')
7739
->signal_connect("button_press_event", "open_dialogColour",
7742
#$widgets->{'image'}->get_widget('entryImageShadowColour')
7743
#->signal_connect("changed", "change_colour_media");
7745
$widgets->{'image'}->get_widget('treeImage')->{user_data} = "load";
7746
my $renderer = Gtk2::CellRendererText->new;
7747
$renderer->set("editable", TRUE);
7748
$renderer->signal_connect("edited", "rename_media");
7750
Gtk2::TreeViewColumn->new_with_attributes("Filename", $renderer,
7752
$widgets->{'image'}->get_widget('treeImage')->append_column($column);
7754
update_imagedir("bg", "");
7760
#****f* lyricue/create_dialogSublist
7762
# create_dialogSublist
7764
# create_dialogSublist ($widgets)
7766
# Create the dialog for adding a sublist
7768
# $widgets - Widgets of main window
7773
sub create_dialogSublist {
7774
debug("create sublist dialog");
7775
my $sublistxml = Gtk2::GladeXML->new($globals->{'gladefile'},
7776
'dialogPromptEntry', 'lyricue');
7777
$sublistxml->signal_autoconnect_from_package('');
7778
$sublistxml->get_widget('dialogPromptEntry')
7779
->set_title(fromutf(gettext("Create new sublist")));
7780
$sublistxml->get_widget('labelPromptE')
7781
->set_text(fromutf(gettext("Name of sublist")));
7782
$sublistxml->get_widget('buttonPromptEOK')
7783
->signal_connect("clicked", "new_sublist_from_xml", $sublistxml);
7790
#****f* lyricue/get_buffer_text
7794
# get_buffer_text($widget)
7802
sub get_buffer_text {
7804
return $widget->get_text($widget->get_bounds, FALSE);
7809
#****f* lyricue/on_treeAvailable_drag_data_get
7811
# on_treeAvailable_drag_data_get
7813
# on_treeAvailable_drag_data_get($widget, $context, $data, $info, $time)
7815
# Dragged from available songs
7825
sub on_treeAvailable_drag_data_get {
7826
my ($widget, $context, $data, $info, $time) = @_;
7827
debug("Dragged from available songs");
7828
my $selection = $widget->get_selection;
7829
my @sel = $selection->get_selected_rows;
7830
my $model = $widgets->{'main'}->get_widget('treeAvailable')->get_model;
7831
my $iter = $model->get_iter($sel[0]);
7833
$data->set($data->target, 8, $model->get($iter, 3));
7839
#****f* lyricue/on_iconviewBack_drag_data_get
7841
# on_iconviewBack_drag_data_get
7843
# on_iconviewBack_drag_data_get($widget, $context, $data, $info, $time)
7845
# Dragged from Backgrounds
7855
sub on_iconviewBack_drag_data_get {
7856
my ($widget, $context, $data, $info, $time) = @_;
7857
debug("Dragged from Backgrounds");
7859
my @list = $widget->get_selected_items;
7860
if (defined $list[0]) {
7861
my $model = $widget->get_model;
7862
my $iter = $model->get_iter($list[0]);
7863
$selected = $model->get($iter, 2);
7865
if ($selected ne "") {
7866
$data->set($data->target, 8, "bg:" . $selected);
7872
#****f* lyricue/on_iconviewImage_drag_data_get
7874
# on_iconviewImage_drag_data_get
7876
# on_iconviewImage_drag_data_get($widget, $context, $data, $info, $time)
7878
# Dragged from Images
7888
sub on_iconviewImage_drag_data_get {
7889
my ($widget, $context, $data, $info, $time) = @_;
7890
debug("Dragged from Images");
7892
my @list = $widget->get_selected_items;
7893
if (defined $list[0]) {
7894
my $model = $widget->get_model;
7895
my $iter = $model->get_iter($list[0]);
7896
$selected = $model->get($iter, 2);
7898
if ($selected ne "") {
7899
$data->set($data->target, 8, "img:" . $selected);
7905
#****f* lyricue/on_treeSearch_drag_data_get
7907
# on_treeSearch_drag_data_get
7909
# on_treeSearch_drag_data_get($widget, $context, $data, $info, $time)
7911
# Dragged from advanced search
7921
sub on_treeSearch_drag_data_get {
7922
my ($widget, $context, $data, $info, $time) = @_;
7923
debug("Dragged from advanced search");
7924
my $selection = $widget->get_selection;
7925
my ($model, $iter) = $selection->get_selected;
7927
$data->set($data->target, 8, $model->get($iter, 4));
7933
#****f* lyricue/on_treePlaylist_drag_data_get
7935
# on_treePlaylist_drag_data_get
7937
# on_treePlaylist_drag_data_get($widget, $context, $data, $info, $time)
7939
# Dragged from playlist
7949
sub on_treePlaylist_drag_data_get {
7950
my ($widget, $context, $data, $info, $time) = @_;
7951
debug("Dragged from Playlist");
7952
my $selection = $widget->get_selection;
7953
my ($model, $iter) = $selection->get_selected;
7955
$data->set($data->target, 8, "song:" . $model->get($iter, 2));
7963
#****f* lyricue/on_treePlaylist_drag_data_received
7965
# on_treePlaylist_drag_data_received
7967
# on_treePlaylist_drag_data_received($widget, $context, $x, $y, $data, $info, $time)
7969
# Dropped on playlist
7981
sub on_treePlaylist_drag_data_received {
7982
my ($widget, $context, $x, $y, $data, $info, $time) = @_;
7984
debug("Dropped on playlist");
7986
# Catch duplicate events
7987
if (defined($globals->{'drop_time'}) && ($globals->{'drop_time'} == $time))
7991
$globals->{'drop_time'} = $time;
7993
if (($data->length >= 0) && ($data->format == 8)) {
7994
debug("Received: " . $data->data);
7995
if ($data->data =~ /^file:/i) {
7996
for my $uri (split(/\n/, $data->data)) {
7997
$u1 = URI->new($uri);
7998
debug("received URI: " . $uri);
7999
$file = fromutf("UTF-8", $u1->file);
8000
debug("Recieved file: " . $file);
8002
$widgets->{'main'}->get_widget('labelCurrentPlaylist')
8004
do_add_file($file, $main_playlist);
8007
} elsif ($data->data =~ /^img:/) {
8008
my $selected = $data->data;
8009
$selected =~ s/^img://g;
8011
$widgets->{'main'}->get_widget('labelCurrentPlaylist')
8013
add_image_item($playlist, $selected);
8015
} elsif ($data->data =~ /^bg:/) {
8016
my $selected = fromutf($data->data);
8017
$selected =~ s/^bg://g;
8019
$widgets->{'main'}->get_widget('labelCurrentPlaylist')
8022
($path, $drop) = $widget->get_dest_row_at_pos($x, $y);
8023
debug($path . ":" . $drop);
8024
if ($drop =~ /^into/) {
8025
my $iter = $widget->get_model->get_iter($path);
8026
my $item = $widget->get_model->get($iter, 2);
8027
@ASSOCIATE = ($item, $playlist);
8028
debug($item . ":" . $playlist . ":" . $selected);
8029
associate_bg($selected);
8032
} elsif ($data->data =~ /^song:/) {
8033
my $song = $data->data;
8034
$song =~ s/^song://g;
8035
my ($path, $drop) = $widget->get_dest_row_at_pos($x, $y);
8036
my $iter = $widget->get_model->get_iter($path);
8037
my $item = $widget->get_model->get($iter, 2);
8038
debug($song . " - " . $drop . " - " . $item);
8039
move_item($song, $drop, $item);
8041
if ($data->data != 0) {
8042
add_single_song($data->data);
8046
$context->finish(1, 0, $time);
8049
$context->finish(0, 0, $time);
8054
#****f* lyricue/display_message
8058
# display_message($message, $details)
8067
sub display_message {
8068
my ($message, $details) = @_;
8071
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogError', 'lyricue');
8072
$errorxml->signal_autoconnect_from_package('');
8073
$errorxml->get_widget('labelError')->set_text($message);
8074
if ((!defined $details) || ($details eq "")) {
8075
$errorxml->get_widget('expanderDetails')->hide();
8077
$errorxml->get_widget('labelErrorDetails')->set_text($details);
8079
my $confirm = $errorxml->get_widget('dialogError')->run();
8080
close_dialog($errorxml->get_widget('dialogError'));
8085
#****f* lyricue/display_fatal
8089
# display_fatal($message, $error)
8099
my ($message, $error) = @_;
8100
print STDERR "\n\n-------------\n";
8101
print STDERR "FATAL ERROR!!\n";
8102
print STDERR "-------------\n";
8103
print STDERR "Error description\n";
8104
print STDERR $message . "\n";
8105
print STDERR "------------------\n";
8107
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogError', 'lyricue');
8108
$errorxml->signal_autoconnect_from_package('');
8109
$errorxml->get_widget('labelError')->set_text($message);
8112
$errorxml->get_widget('expanderDetails')->hide();
8114
$errorxml->get_widget('labelErrorDetails')->set_text($error);
8116
my $confirm = $errorxml->get_widget('dialogError')->run();
8117
close_dialog($errorxml->get_widget('dialogError'));
8118
print STDERR "Full error message\n";
8119
print STDERR "------------------\n";
8125
#****f* lyricue/transition_type_changed
8127
# transition_type_changed
8129
# transition_type_changed()
8131
# Change the list of transition options
8135
sub transition_type_changed {
8137
debug("Transition type changed");
8138
my $item = $widget->get_name;
8139
if ($item eq "radioTransFade") {
8140
} elsif ($item eq "radioTransWipe") {
8141
} elsif ($item eq "radioTransSlide") {
8142
if ($widget->get_active) {
8143
$widgets->{'main'}->get_widget('tableTransDir')->show_all();
8145
$widgets->{'main'}->get_widget('tableTransDir')->hide();
8147
} elsif ($item eq "radioTransRotate") {
8148
if ($widget->get_active) {
8149
$widgets->{'main'}->get_widget('tableTransRot')->show_all();
8151
$widgets->{'main'}->get_widget('tableTransRot')->hide();
8156
sub transition_dir_changed {
8158
debug("Direction changed");
8159
if ($widget->get_active == FALSE) {
8163
'UpLeft', 'Up', 'UpRight', 'Left', 'None', 'Right',
8164
'DownLeft', 'Down', 'DownRight'
8166
if ($widget->get_name() =~ /^toggleIn/) {
8168
my $w = "toggleIn" . $_;
8169
if ($widget->get_name eq $w) {
8170
$widgets->{'main'}->get_widget($w)->set_active(TRUE);
8172
$widgets->{'main'}->get_widget($w)->set_active(FALSE);
8175
} elsif ($widget->get_name =~ /^toggleOut/) {
8177
my $w = "toggleOut" . $_;
8178
if ($widget->get_name eq $w) {
8179
$widgets->{'main'}->get_widget($w)->set_active(TRUE);
8181
$widgets->{'main'}->get_widget($w)->set_active(FALSE);
8189
#****f* lyricue/apply_transition_selected
8191
# apply_transition_selected
8193
# apply_transition_selected()
8195
# Apply transition to selected items
8200
sub apply_transition_selected {
8201
debug("Apply transition to selected items");
8202
if ($widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data} ==
8207
my $trans_type = calculate_transition();
8209
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
8211
my @list = $selection->get_selected_rows();
8212
my $model = $widgets->{'main'}->get_widget('treePlaylist')->get_model();
8214
apply_transition($model->get($model->get_iter($_), 2), $trans_type);
8222
#****f* lyricue/apply_transition_playlist
8224
# apply_transition_playlist
8226
# apply_transition_playlist()
8228
# Apply transition to playlist
8233
sub apply_transition_playlist {
8234
debug("Apply transition to playlist");
8236
$widgets->{'main'}->get_widget('labelCurrentPlaylist')->{user_data};
8237
if ($playlist == -1) {
8240
my $trans_type = calculate_transition();
8241
my $query = "SELECT playorder FROM playlist WHERE playlist=" . $playlist;
8243
my $sth = $lyricDbh->prepare($query)
8244
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
8245
my $rv = $sth->execute
8246
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
8247
while (my @row = $sth->fetchrow_array()) {
8248
apply_transition($row[0], $trans_type);
8255
#****f* lyricue/calculate_transition
8257
# calculate_transition
8259
# calculate_transition()
8266
sub calculate_transition {
8267
debug("Calculating transition code");
8268
my $trans_type = DEFAULT;
8269
if ($widgets->{'main'}->get_widget('radioTransNone')->get_active()) {
8270
$trans_type = NOTRANS;
8271
} elsif ($widgets->{'main'}->get_widget('radioTransFade')->get_active()) {
8273
} elsif ($widgets->{'main'}->get_widget('radioTransSlide')->get_active()) {
8274
$trans_type = SLIDE_TEXT;
8275
} elsif ($widgets->{'main'}->get_widget('radioTransRotate')->get_active()) {
8276
$trans_type = ROTATE_TEXT;
8280
'UpLeft', 'Up', 'UpRight', 'Left', 'None', 'Right',
8281
'DownLeft', 'Down', 'DownRight'
8286
if ($widgets->{'main'}->get_widget("toggleIn" . $_)->get_active()) {
8289
if ($widgets->{'main'}->get_widget("toggleOut" . $_)->get_active()) {
8295
$trans_type = $trans_type << NUM_TRANS;
8298
$trans_type = $trans_type + UP;
8300
$trans_type = $trans_type + DOWN;
8303
$trans_type = $trans_type + LEFT;
8305
$trans_type = $trans_type + RIGHT;
8308
if ($widgets->{'main'}->get_widget('toggleRotX')->get_active()) {
8309
$trans_type = $trans_type + X_AXIS;
8311
if ($widgets->{'main'}->get_widget('toggleRotY')->get_active()) {
8312
$trans_type = $trans_type + Y_AXIS;
8314
if ($widgets->{'main'}->get_widget('toggleRotZ')->get_active()) {
8315
$trans_type = $trans_type + Z_AXIS;
8319
$trans_type = $trans_type << NUM_TRANS;
8322
$trans_type = $trans_type + UP;
8324
$trans_type = $trans_type + DOWN;
8327
$trans_type = $trans_type + LEFT;
8329
$trans_type = $trans_type + RIGHT;
8332
if ($widgets->{'main'}->get_widget('toggleRotX')->get_active()) {
8333
$trans_type = $trans_type + X_AXIS;
8335
if ($widgets->{'main'}->get_widget('toggleRotY')->get_active()) {
8336
$trans_type = $trans_type + Y_AXIS;
8338
if ($widgets->{'main'}->get_widget('toggleRotZ')->get_active()) {
8339
$trans_type = $trans_type + Z_AXIS;
8346
#****f* lyricue/apply_transition
8350
# apply_transition($item, $trans_type)
8352
# Applying transition to
8359
sub apply_transition {
8360
my ($item, $trans_type) = @_;
8361
debug("Applying transition to " . $item);
8363
my $query = "SELECT type,data FROM playlist WHERE playorder=" . $item;
8365
my $sth = $lyricDbh->prepare($query)
8366
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
8367
my $rv = $sth->execute
8368
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
8369
my @row = $sth->fetchrow_array();
8370
if ($row[0] eq "play") {
8372
"UPDATE playlist SET transition="
8374
. " WHERE playorder="
8380
"UPDATE playlist SET transition="
8382
. " WHERE playorder="
8386
$sth = $lyricDbh->prepare($query)
8387
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
8389
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
8408
my ($inp, $div) = @_;
8409
my $rem = (($inp / $div) - (int($inp / $div))) * $div;
8415
#****f* lyricue/user_admin
8421
# User access administration
8427
debug("User access administration");
8428
$widgets->{'admin'} =
8429
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogAdmin', 'lyricue');
8430
$widgets->{'admin'}->signal_autoconnect_from_package('');
8431
eval { open(ACCESS, $globals->{'accessfile'}); };
8433
debug("No existing access.conf");
8436
my (@username, @useraccess);
8438
($username[$users], $useraccess[$users]) = split(/=/, $_, 2);
8439
$username[$users] =~ s/ *$//g;
8440
$useraccess[$users] =~ s/ *$//g;
8444
$widgets->{'admin'}->get_widget('tableAccess')->resize($users, 6);
8445
foreach my $count (0 .. ($users - 1)) {
8446
debug("Users: " . $username[$count]);
8447
$widgets->{'adminUsername'}[$count] =
8448
Gtk2::Label->new($username[$count]);
8449
$widgets->{'admin'}->get_widget('tableAccess')
8450
->attach($widgets->{'adminUsername'}[$count],
8451
0, 1, $count + 2, $count + 3, 'fill', 'expand', 0, 0);
8453
$widgets->{'adminPlaylist'}[$count] = Gtk2::CheckButton->new();
8454
$widgets->{'admin'}->get_widget('tableAccess')
8455
->attach($widgets->{'adminPlaylist'}[$count],
8456
1, 2, $count + 2, $count + 3, 'fill', 'expand', 0, 0);
8457
$widgets->{'adminEdit'}[$count] = Gtk2::CheckButton->new();
8458
$widgets->{'admin'}->get_widget('tableAccess')
8459
->attach($widgets->{'adminEdit'}[$count],
8460
2, 3, $count + 2, $count + 3, 'fill', 'expand', 0, 0);
8461
$widgets->{'adminDelete'}[$count] = Gtk2::CheckButton->new();
8462
$widgets->{'admin'}->get_widget('tableAccess')
8463
->attach($widgets->{'adminDelete'}[$count],
8464
3, 4, $count + 2, $count + 3, 'fill', 'expand', 0, 0);
8465
$widgets->{'adminDisplay'}[$count] = Gtk2::CheckButton->new();
8466
$widgets->{'admin'}->get_widget('tableAccess')
8467
->attach($widgets->{'adminDisplay'}[$count],
8468
4, 5, $count + 2, $count + 3, 'fill', 'expand', 0, 0);
8469
$widgets->{'adminAdmin'}[$count] = Gtk2::CheckButton->new();
8470
$widgets->{'admin'}->get_widget('tableAccess')
8471
->attach($widgets->{'adminAdmin'}[$count],
8472
5, 6, $count + 2, $count + 3, 'fill', 'expand', 0, 0);
8473
$_ = $useraccess[$count];
8476
$widgets->{'adminPlaylist'}[$count]->set_active(TRUE);
8478
if (/e/) { $widgets->{'adminEdit'}[$count]->set_active(TRUE); }
8480
$widgets->{'adminDelete'}[$count]->set_active(TRUE);
8483
$widgets->{'adminDisplay'}[$count]->set_active(TRUE);
8485
if (/a/) { $widgets->{'adminAdmin'}[$count]->set_active(TRUE); }
8487
$widgets->{'admin'}->get_widget('tableAccess')->show_all();
8489
my $confirm = $widgets->{'admin'}->get_widget('dialogAdmin')->run();
8490
if ($confirm eq "ok") {
8491
open(ACCESS, ">" . $globals->{'accessfile'})
8493
$errorcodes->{'fileopenwrite'} . $globals->{'accessfile'},
8494
$! . "\nSQL: " . $query);
8496
($widgets->{'admin'}->get_widget('tableAccess')->get('n-rows') - 2);
8497
foreach my $count (0 .. ($users - 1)) {
8498
my $out = $widgets->{'adminUsername'}[$count]->get_text() . " = ";
8499
if ($widgets->{'adminPlaylist'}[$count]->get_active()) {
8502
if ($widgets->{'adminEdit'}[$count]->get_active()) {
8505
if ($widgets->{'adminDelete'}[$count]->get_active()) {
8508
if ($widgets->{'adminDisplay'}[$count]->get_active()) {
8511
if ($widgets->{'adminAdmin'}[$count]->get_active()) {
8514
print ACCESS $out . "\n";
8518
$widgets->{'admin'}->get_widget('dialogAdmin')->destroy();
8519
$globals->{'access'} = load_access();
8525
#****f* lyricue/load_access
8531
# Loading access settings
8537
debug("Loading access settings");
8538
my $access = "blank";
8540
# Load the access settings (ignore if using sqlite)
8541
if (($config->{'DatabaseType'} eq "SQLite") || ($^O eq 'MSWin32')) {
8544
open(ACCESS, $globals->{'accessfile'})
8546
$errorcodes->{'fileopenread'} . $globals->{'accessfile'},
8547
$! . "\nSQL: " . $query);
8548
my $username = getpwuid($<);
8553
$access =~ s/^.*= *//g;
8558
if ($access eq "blank") {
8560
#my $accessxml = Gtk2::GladeXML->new($globals->{'gladefile'},
8561
# 'dialogConfirm', 'lyricue');
8562
#$accessxml->signal_autoconnect_from_package('');
8563
#my $labelText .= fromutf(
8565
# "This user has no access entry.\nBy default they will have full access.\nTo fix please edit /etc/lyricue/access.conf and add an entry for this user.\nClick OK to continue anyway or Cancel to Exit"
8568
#$accessxml->get_widget('labelDelete')->set_text($labelText);
8569
#$accessxml->get_widget('dialogConfirm')->set_title(fromutf(gettext("User access level")));
8571
#my $confirm = $accessxml->get_widget('dialogConfirm')->run();
8572
#if ($confirm ne "ok") {
8575
#close_dialog($accessxml->get_widget('dialogConfirm'));
8577
debug("Access set at " . $access);
8580
my @remove_items = ();
8581
my @show_items = ();
8583
push @remove_items, @edit_items;
8585
push @show_items, @edit_items;
8589
push @remove_items, @delete_items;
8591
push @show_items, @delete_items;
8595
push @remove_items, @display_items;
8597
push @show_items, @display_items;
8601
push @remove_items, @playlist_items;
8603
push @show_items, @playlist_items;
8607
push @remove_items, @admin_items;
8609
push @show_items, @admin_items;
8611
if (!-w $globals->{'accessfile'}) {
8612
push @remove_items, "user_administration1";
8615
foreach my $item (@show_items) {
8616
debug("Showing $item");
8617
if (defined $widgets->{'main'}->get_widget($item)) {
8618
$widgets->{'main'}->get_widget($item)->show();
8622
foreach my $item (@remove_items) {
8623
debug("Hiding $item");
8624
if (defined $widgets->{'main'}->get_widget($item)) {
8625
$widgets->{'main'}->get_widget($item)->hide();
8633
#****f* lyricue/add_user
8645
debug("Adding a user");
8646
my $userxml = Gtk2::GladeXML->new($globals->{'gladefile'},
8647
'dialogPromptEntry', 'lyricue');
8648
$userxml->signal_autoconnect_from_package('');
8649
$userxml->get_widget('dialogPromptEntry')
8650
->set_title(fromutf(gettext("Add a user")));
8651
$userxml->get_widget('labelPromptE')
8652
->set_text(fromutf(gettext("Enter username")));
8653
my $confirm = $userxml->get_widget('dialogPromptEntry')->run();
8654
if ($confirm eq "ok") {
8656
($widgets->{'admin'}->get_widget('tableAccess')->get('n-rows') - 2);
8657
debug("Users :" . $users);
8658
$widgets->{'admin'}->get_widget('tableAccess')->resize($users + 3, 6);
8659
$widgets->{'adminUsername'}[$users] =
8660
Gtk2::Label->new($userxml->get_widget('entryPromptE')->get_text());
8661
$widgets->{'admin'}->get_widget('tableAccess')
8662
->attach($widgets->{'adminUsername'}[$users],
8663
0, 1, $users + 2, $users + 3, 'fill', 'expand', 0, 0);
8664
$widgets->{'adminPlaylist'}[$users] = Gtk2::CheckButton->new();
8665
$widgets->{'admin'}->get_widget('tableAccess')
8666
->attach($widgets->{'adminPlaylist'}[$users],
8667
1, 2, $users + 2, $users + 3, 'fill', 'expand', 0, 0);
8668
$widgets->{'adminEdit'}[$users] = Gtk2::CheckButton->new();
8669
$widgets->{'admin'}->get_widget('tableAccess')
8670
->attach($widgets->{'adminEdit'}[$users],
8671
2, 3, $users + 2, $users + 3, 'fill', 'expand', 0, 0);
8672
$widgets->{'adminDelete'}[$users] = Gtk2::CheckButton->new();
8673
$widgets->{'admin'}->get_widget('tableAccess')
8674
->attach($widgets->{'adminDelete'}[$users],
8675
3, 4, $users + 2, $users + 3, 'fill', 'expand', 0, 0);
8676
$widgets->{'adminDisplay'}[$users] = Gtk2::CheckButton->new();
8677
$widgets->{'admin'}->get_widget('tableAccess')
8678
->attach($widgets->{'adminDisplay'}[$users],
8679
4, 5, $users + 2, $users + 3, 'fill', 'expand', 0, 0);
8680
$widgets->{'adminAdmin'}[$users] = Gtk2::CheckButton->new();
8681
$widgets->{'admin'}->get_widget('tableAccess')
8682
->attach($widgets->{'adminAdmin'}[$users],
8683
5, 6, $users + 2, $users + 3, 'fill', 'expand', 0, 0);
8685
$widgets->{'admin'}->get_widget('tableAccess')->show_all();
8686
close_dialog($userxml->get_widget('dialogPromptEntry'));
8691
#****f* lyricue/search_changed
8702
sub search_changed {
8703
debug("Search changed");
8704
reset_timer($globals->{'update_timer'});
8705
$globals->{'update_timer'} = Glib::Timeout->add(500, \&update_available);
8710
#****f* lyricue/search_activated
8714
# search_activated()
8721
sub search_activated{
8722
debug("Search activated");
8723
my $model = $widgets->{'main'}->get_widget('treeAvailable')->get_model;
8724
my $iter = $model->get_iter_first;
8725
if (defined $iter) {
8726
my $songid = $model->get($iter, 3);
8727
add_single_song($songid);
8734
#****f* lyricue/init_preview
8746
debug("init preview");
8748
# Start/stop preview as needed
8749
if ($config->{'DynamicPreview'}) {
8750
if (!defined($widgets->{'preview'})) {
8751
$widgets->{'main'}->get_widget('labelPreview')->show();
8752
$widgets->{'main'}->get_widget('framePreview')->show();
8753
$widgets->{'main'}->get_widget('framePreview')
8754
->set_size_request(100, 75);
8755
$widgets->{'preview'} = Gtk2::Socket->new;
8756
$widgets->{'preview'}->show;
8757
$widgets->{'main'}->get_widget('framePreview')
8758
->add($widgets->{'preview'});
8759
$widgets->{'preview'}->set_size_request(-1, -1);
8763
"%s -r %s -m %d -p %d",
8764
$globals->{'lyricue_server'} , $globals->{'mysqlhost'}, $widgets->{'preview'}->get_id,
8765
$globals->{'preview_port'}
8769
$globals->{'preview_pid'} = fork;
8770
if ($globals->{'preview_pid'} < 0) {
8772
"Unable to start the lyricue server as a preview window",
8773
$! . "\nSQL: " . $query);
8775
if ($globals->{'preview_pid'} == 0) {
8777
if ($globals->{'debugging'}) {
8782
"%s -r %s -m %d -p %d %s\n",
8783
$globals->{'lyricue_server'} ,
8784
$globals->{'mysqlhost'},
8785
$widgets->{'preview'}->get_id,
8786
$globals->{'preview_port'},
8791
$widgets->{'preview'}->signal_connect(
8792
'plug-removed' => sub {
8793
debug("Lyricue preview died..restarting\n");
8794
$widgets->{'main'}->get_widget('framePreview')
8795
->remove($widgets->{'preview'});
8802
if ($widgets->{'preview'}) {
8803
$widgets->{'preview'}->destroy;
8804
undef $widgets->{'preview'};
8805
kill 9, $globals->{'preview_pid'};
8807
$widgets->{'main'}->get_widget('framePreview')->hide();
8808
$widgets->{'main'}->get_widget('labelPreview')->hide();
8814
#****f* lyricue/init_miniview
8826
debug("init miniview");
8828
# Start/stop miniview as needed
8829
if ($config->{'Miniview'}) {
8830
if (!defined($widgets->{'miniview'})) {
8831
update_display("status", "previewon", "");
8832
$widgets->{'main'}->get_widget('labelCurrent')->show();
8833
$widgets->{'main'}->get_widget('frameCurrent')->show();
8834
$widgets->{'miniview'} = Gtk2::Socket->new;
8835
$widgets->{'miniview'}->set_size_request(100, 75);
8836
$widgets->{'miniview'}->show;
8837
$widgets->{'main'}->get_widget('frameCurrent')
8838
->add($widgets->{'miniview'});
8839
$widgets->{'main'}->get_widget('frameCurrent')
8840
->set_size_request(-1, -1);
8843
"%s -r %s -m %d -p %d\n",
8844
$globals->{'lyricue_server'},
8845
$globals->{'mysqlhost'},
8846
$widgets->{'miniview'}->get_id,
8847
$globals->{'miniview_port'}
8851
$globals->{'miniview_pid'} = fork;
8852
if ($globals->{'miniview_pid'} < 0) {
8854
"Unable to start the lyricue server as a preview window",
8855
$! . "\nSQL: " . $query);
8857
if ($globals->{'miniview_pid'} == 0) {
8860
"%s -r %s -m %d -p %d\n",
8861
$globals->{'lyricue_server'},
8862
$globals->{'mysqlhost'},
8863
$widgets->{'miniview'}->get_id,
8864
$globals->{'miniview_port'}
8869
$widgets->{'miniview'}->signal_connect(
8870
'plug-removed' => sub {
8871
debug("Lyricue miniview died..restarting");
8872
$widgets->{'main'}->get_widget('frameCurrent')
8873
->remove($widgets->{'miniview'});
8880
if ($widgets->{'miniview'}) {
8881
$widgets->{'miniview'}->destroy;
8882
undef $widgets->{'miniview'};
8883
kill 9, $globals->{'miniview_pid'};
8885
update_display("status", "previewoff", "");
8886
$widgets->{'main'}->get_widget('frameCurrent')->hide();
8887
$widgets->{'main'}->get_widget('labelCurrent')->hide();
8893
#****f* lyricue/quick_save
8905
debug("Quick Save");
8906
my $buffer = $widgets->{'main'}->get_widget('textQuick')->get_buffer();
8907
my $songtext = $buffer->get_text($buffer->get_bounds, FALSE);
8908
my $playorder = $widgets->{'main'}->get_widget('textQuick')->{user_data};
8909
my $query = "SELECT data,type FROM playlist WHERE playorder=" . $playorder;
8911
$sth = $lyricDbh->prepare($query)
8912
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
8914
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
8915
my @row = $sth->fetchrow_array();
8917
if ($row[1] eq "play") {
8919
"SELECT data,type FROM playlist WHERE playlist="
8921
. " ORDER BY playorder";
8923
$sth = $lyricDbh->prepare($query)
8924
|| display_fatal($errorcodes->{'sqlprepare'},
8925
$! . "\nSQL: " . $query);
8927
|| display_fatal($errorcodes->{'sqlexecute'},
8928
$! . "\nSQL: " . $query);
8929
@row = $sth->fetchrow_array();
8932
if ($row[1] eq "song") {
8933
if (!defined $row[0]) { $row[0] = ""; }
8936
"UPDATE page SET lyrics="
8937
. $lyricDbh->quote($songtext)
8941
$sth = $lyricDbh->prepare($query)
8942
|| display_fatal($errorcodes->{'sqlprepare'},
8943
$! . "\nSQL: " . $query);
8945
|| display_fatal($errorcodes->{'sqlexecute'},
8946
$! . "\nSQL: " . $query);
8950
# Just put the text in the quickview section onto the screen
8953
#****f* lyricue/quick_show
8959
# Quickshow textarea
8965
debug("Quickshow textarea");
8966
my $buffer = $widgets->{'main'}->get_widget('textQuick')->get_buffer();
8967
my $songtext = $buffer->get_text($buffer->get_bounds, FALSE);
8968
$songtext =~ s/\n/#BREAK#/g;
8969
$songtext =~ s/:/#SEMI#/g;
8970
update_display("preview", "ignore", $songtext);
8975
#****f* lyricue/quick_osd
8988
debug("Update OSD");
8989
debug($widget->get_name);
8991
if (($widgets->{'main'}->get_widget('buttonQuickOSD')->get_active()) || ($widget->get_name eq "entryMainOSD")) {
8992
$songtext = $widgets->{'main'}->get_widget('entryMainOSD')->get_text;
8993
$songtext =~ s/\n/#BREAK#/g;
8994
$songtext =~ s/:/#SEMI#/g;
8996
update_display("osd", "default", $songtext);
9001
#****f* lyricue/resize_preview
9005
# resize_preview($widget, $event)
9007
# Called when the preview windows are resized
9014
sub resize_preview {
9015
my ($widget, $event) = @_;
9018
#debug ("Resizing previews");
9019
#my $pos = $widgets->{'main'}->get_widget('hpanedMainRight')->get_position();
9020
#my ($width,$height) = $widgets->{'preview'}->get_size();
9021
#print ("$width * $height\n");
9025
# Return a Gdk::Pixbuf of the given media at the given res
9028
#****f* lyricue/create_pixbuf
9032
# create_pixbuf($data, $width, $height)
9043
my ($data, $width, $height) = @_;
9045
my ($type, $id) = split /;/, $data;
9046
if ($type eq "dir") {
9050
if (($width > $globals->{'thumb_width'}) || ($width == 0)) {
9052
# Bigger than cache value so just send new pixbuf
9054
$pixbuf = Gtk2::Gdk::Pixbuf->new_from_file_at_scale($id, $width,
9057
# Try thumbnailing with video thumbnailer
9058
my $thumbfile = "/tmp/lyricue-tmpthumb.png";
9059
if (-e $thumbfile) {
9065
$globals->{'video-thumbnailer'}
9068
. $thumbfile . "\"";
9070
if (-e $thumbfile) {
9071
$pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($thumbfile);
9072
$pixbuf = $pixbuf->scale_simple($width, $height, 'bilinear');
9080
my $mtime = (stat($id))[9];
9083
$globals->{'thumbnail_factory'}->lookup("file://" . $id, $mtime);
9084
if (!defined $filename) {
9085
if ($globals->{'thumbnail_factory'}
9086
->has_valid_failed_thumbnail("file://" . $id, $mtime))
9091
$globals->{'thumbnail_factory'}
9092
->generate_thumbnail("file://" . $id, $mtime);
9094
$globals->{'thumbnail_factory'}
9095
->save_thumbnail($pixbuf, "file://" . $id, $mtime);
9096
$pixbuf = $pixbuf->scale_simple($width, $height, 'bilinear');
9099
# Try thumbnailing with video thumbnailer
9100
my $thumbfile = "/tmp/lyricue-tmpthumb.png";
9101
if (-e $thumbfile) {
9105
$globals->{'video-thumbnailer'}
9108
. $thumbfile . "\"";
9110
if (-e $thumbfile) {
9111
$pixbuf = Gtk2::Gdk::Pixbuf->new_from_file($thumbfile);
9112
$globals->{'thumbnail_factory'}
9113
->save_thumbnail($pixbuf, "file://" . $id, $mtime);
9114
$pixbuf = $pixbuf->scale_simple($width, $height, 'bilinear');
9121
$pixbuf = Gtk2::Gdk::Pixbuf->new_from_file_at_scale($filename, $width, $height, TRUE);
9125
my $query = "SELECT format, description, data FROM media WHERE id=\""
9128
my $sth = $mediaDbh->prepare($query)
9129
|| display_fatal($errorcodes->{'sqlprepare'},
9130
$! . "\nSQL: " . $query);
9131
my $rv = $sth->execute
9132
|| display_fatal($errorcodes->{'sqlexecute'},
9133
$! . "\nSQL: " . $query);
9134
my $row = $sth->fetchrow_hashref();
9135
if ($row->{'format'} eq "bg") {
9136
my @xpm = ("1 1 1 1", " c " . $row->{'description'}, " ");
9137
$pixbuf = Gtk2::Gdk::Pixbuf->new_from_xpm_data(@xpm);
9139
my $pixbuf_loader = Gtk2::Gdk::PixbufLoader->new();
9140
eval { $pixbuf_loader->write($row->{'data'}); };
9141
eval { $pixbuf_loader->close() };
9143
my @xpm = ("1 1 1 1", " c " . $row->{'description'}, " ");
9144
$pixbuf = Gtk2::Gdk::Pixbuf->new_from_xpm_data(@xpm);
9146
$pixbuf = $pixbuf_loader->get_pixbuf();
9153
return $pixbuf->scale_simple($width, $height, 'nearest');
9160
#****f* lyricue/import_image
9172
import_media("img");
9177
#****f* lyricue/import_background
9181
# import_background()
9188
sub import_background {
9194
#****f* lyricue/import_media
9198
# import_media($type)
9208
debug("Import media to db of type:" . $type);
9209
my $filexml = Gtk2::GladeXML->new($globals->{'gladefile'},
9210
'dialogFileChooser', 'lyricue');
9211
$filexml->signal_autoconnect_from_package('');
9212
$filexml->get_widget('buttonFileOK')
9213
->signal_connect("clicked", "select_category", $filexml);
9214
$filexml->get_widget('dialogFileChooser')->{user_data} = $type;
9215
$filexml->get_widget('dialogFileChooser')->set_select_multiple(TRUE);
9216
$filexml->get_widget('dialogFileChooser')->show_all();
9221
#****f* lyricue/select_category
9225
# select_category($widget, $filexml)
9234
sub select_category {
9235
my ($widget, $filexml) = @_;
9236
debug("select category");
9238
my @filenames = $filexml->get_widget('dialogFileChooser')->get_filenames;
9240
my $type = $filexml->get_widget('dialogFileChooser')->{user_data};
9241
close_dialog($filexml->get_widget('dialogFileChooser'));
9243
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogSelectCategory');
9246
"SELECT DISTINCT category FROM media WHERE type=\""
9248
. "\" ORDER BY category";
9250
my $sth = $mediaDbh->prepare($query)
9251
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
9252
my $rv = $sth->execute
9253
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
9255
my $model = Gtk2::ListStore->new('Glib::String');
9256
$choosexml->get_widget('comboSelectCategory')->set_model($model);
9257
$choosexml->get_widget('comboSelectCategory')->set_text_column(0);
9259
while (@row = $sth->fetchrow_array()) {
9260
$choosexml->get_widget('comboSelectCategory')->append_text($row[0]);
9262
my $confirm = $choosexml->get_widget('dialogSelectCategory')->run;
9263
if ($confirm == 1) {
9264
if ($choosexml->get_widget('comboSelectCategory')->get_active_text() eq
9269
debug("Importing media");
9271
$choosexml->get_widget('comboSelectCategory')->get_active_text();
9273
foreach $filename (@filenames) {
9274
my $format = $filename;
9275
$format =~ s/^.*\.//g;
9276
my $description = $filename;
9277
$description =~ s/^.*\///g;
9278
$description =~ s/\..*?$//g;
9279
my $owner = getpwuid($<);
9280
debug("Category: $category\nFilename: $filename");
9281
open(MEDIA, $filename);
9288
debug("Length: " . length($data));
9289
my $sth = $mediaDbh->prepare(
9290
q{INSERT INTO media(category, subcategory, type, format, insertedby, insertdate, description, data) VALUES (?,?,?,?,?,NOW(),?,?)}
9293
$sth->execute($category, "", $type, $format, $owner, $description,
9297
close_dialog($choosexml->get_widget('dialogSelectCategory'));
9299
$widgets->{'image'}->get_widget('optionImageCategory')
9300
->get_menu->get_active->{user_data};
9302
$widgets->{'image'}->get_widget('optionImageCategory')->{'user_data'},
9308
#****f* lyricue/update_category
9312
# update_category($selection, $choosexml)
9314
# Selected a category
9321
sub update_category {
9322
my ($selection, $choosexml) = @_;
9323
debug("Selected a category");
9325
my ($model, $iter) = $selection->get_selected;
9327
$choosexml->get_widget('entryChoosePlay')
9328
->set_text($model->get($iter, 0));
9334
#****f* lyricue/update_quickedit
9338
# update_quickedit()
9340
# Updating Quick edit
9345
sub update_quickedit {
9346
debug("Updating Quick edit");
9348
$widgets->{'main'}->get_widget('treePlaylist')->get_selection;
9349
my ($model, $iter) = $selection->get_selected;
9353
my $plnumber = $model->get($iter, 2);
9356
# Find the items lyrics for Quick Editing
9357
while ($loop == 0) {
9359
"SELECT type,data,playlist FROM playlist WHERE playorder="
9362
$sth = $lyricDbh->prepare($query)
9363
|| display_fatal($errorcodes->{'sqlprepare'},
9364
$! . "\nSQL: " . $query);
9366
|| display_fatal($errorcodes->{'sqlexecute'},
9367
$! . "\nSQL: " . $query);
9368
my @row = $sth->fetchrow_array();
9369
if (defined($row[0])) {
9370
if ($row[0] eq "song") {
9372
"SELECT lyrics FROM playlist as pl, page as pa WHERE pl.data=pa.pageid AND pl.playorder="
9375
$sth = $lyricDbh->prepare($query)
9376
|| display_fatal($errorcodes->{'sqlprepare'},
9377
$! . "\nSQL: " . $query);
9379
|| display_fatal($errorcodes->{'sqlexecute'},
9380
$! . "\nSQL: " . $query);
9381
my @row2 = $sth->fetchrow_array();
9382
if (!defined $row2[0]) { $row2[0] = ""; }
9383
$quicktext = $row2[0];
9385
$widgets->{'main'}->get_widget('textQuick')
9386
->set_wrap_mode('none');
9387
$quicktext = $quicktext;
9388
} elsif ($row[0] eq "play") {
9390
"SELECT playorder FROM playlist WHERE playlist="
9392
. " ORDER BY playorder";
9394
$sth = $lyricDbh->prepare($query)
9395
|| display_fatal($errorcodes->{'sqlprepare'},
9396
$! . "\nSQL: " . $query);
9398
|| display_fatal($errorcodes->{'sqlexecute'},
9399
$! . "\nSQL: " . $query);
9400
my @row = $sth->fetchrow_array();
9401
$plnumber = $row[0];
9403
} elsif ($row[0] eq "vers") {
9404
my ($startv, $endv) = split(/-/, $row[1], 2);
9405
$query = "SELECT title FROM playlists WHERE id=" . $row[2];
9407
$sth = $lyricDbh->prepare($query)
9408
|| display_fatal($errorcodes->{'sqlprepare'},
9409
$! . "\nSQL: " . $query);
9411
|| display_fatal($errorcodes->{'sqlexecute'},
9412
$! . "\nSQL: " . $query);
9413
my @row = $sth->fetchrow_array();
9414
my @line = split(/:/, $row[0]);
9415
if ($globals->{'usesword'}) {
9416
my $command = sprintf(
9417
"%s -b %s -e UTF8 -k '%s' %d:%d-%d:%d |tr \\\\n \' \'",
9418
$globals->{'diatheke'}, $globals->{'bibledb'},
9424
my $command_out = fromutf(`$command`);
9425
($line[0], undef) = split(/\s\d/, $command_out, 2);
9426
my @command_lines = split(/$line[0] /, $command_out);
9428
foreach $lineno (1 .. @command_lines) {
9429
my $line2 = $command_lines[$lineno - 1];
9432
if ($lineno != @command_lines) {
9435
$quicktext .= $line2;
9439
my ($table, $dbname) =
9440
split(/@/, $globals->{'bibledb'}, 2);
9442
"SELECT chapternum,versenum,verse FROM "
9446
. "\" AND chapternum="
9450
. " AND versenum <= "
9453
$sth = $bibleDbh->prepare($query)
9455
$errorcodes->{'sqlprepare'},
9456
$! . "\nSQL: " . $query
9460
$errorcodes->{'sqlexecute'},
9461
$! . "\nSQL: " . $query
9464
while (@row = $sth->fetchrow_array()) {
9466
$row[0] . ":" . $row[1] . " " . $row[2] . "\n";
9468
$quicktext = fromutf($quicktext);
9471
$widgets->{'main'}->get_widget('textQuick')
9472
->set_wrap_mode('word');
9473
} elsif ($row[0] eq "imag") {
9474
$quicktext = "Image";
9476
} elsif ($row[0] eq "back") {
9477
$quicktext = "Background";
9487
$widgets->{'main'}->get_widget('textQuick')
9488
->get_buffer->set_text($quicktext);
9489
$widgets->{'main'}->get_widget('textQuick')->{user_data} =
9490
$model->get($iter, 2);
9497
#****f* lyricue/media_move
9509
debug("Moving media");
9510
my $selection = $widgets->{'image'}->get_widget('treeImage')->get_selection;
9511
my @selecteditems = $selection->get_selected_rows();
9514
$widgets->{'image'}->get_widget('optionImageCategory')->{'user_data'};
9515
if ($selecteditems[0]) {
9516
foreach (@selecteditems) {
9518
$widgets->{'image'}->get_widget('treeImage')
9519
->get_model->get_iter($_);
9521
$widgets->{'image'}->get_widget('treeImage')
9522
->get_model->get($iter, 1);
9527
Gtk2::GladeXML->new($globals->{'gladefile'}, 'windowChoosePlay');
9528
$choosexml->get_widget('windowChoosePlay')
9529
->set_title(fromutf(gettext("Select Category")));
9530
$choosexml->get_widget('buttonLoad')->set_label("Select");
9531
$choosexml->get_widget('buttonDelete')->hide();
9532
$choosexml->get_widget('buttonRename')->hide();
9533
$choosexml->get_widget('buttonLoad')
9534
->signal_connect("clicked", "do_move_media", $choosexml);
9535
$choosexml->get_widget('buttonNew')
9536
->signal_connect("clicked", "do_move_media", $choosexml);
9537
$choosexml->get_widget('buttonCancel')
9538
->signal_connect("clicked", "close_dialog");
9539
$choosexml->get_widget('windowChoosePlay')->show;
9540
$choosexml->get_widget('treeChoosePlay')->{'user_data'} = $type;
9541
$choosexml->get_widget('windowChoosePlay')->{'user_data'} = \@id;
9542
my $store = $choosexml->get_widget('treeChoosePlay')->get_model();
9547
$store = Gtk2::ListStore->new('Glib::String');
9548
$choosexml->get_widget('treeChoosePlay')->set_model($store);
9549
my $renderer = Gtk2::CellRendererText->new;
9551
$choosexml->get_widget('treeChoosePlay')->get_selection;
9552
$selection->signal_connect("changed", "update_category",
9555
Gtk2::TreeViewColumn->new_with_attributes("Category", $renderer,
9557
$choosexml->get_widget('treeChoosePlay')->append_column($column);
9561
"SELECT DISTINCT category FROM media WHERE type=\""
9563
. "\" ORDER BY category";
9564
my $sth = $mediaDbh->prepare($query)
9565
|| display_fatal($errorcodes->{'sqlprepare'},
9566
$! . "\nSQL: " . $query);
9567
my $rv = $sth->execute
9568
|| display_fatal($errorcodes->{'sqlexecute'},
9569
$! . "\nSQL: " . $query);
9571
while (@row = $sth->fetchrow_array()) {
9572
my $iter = $store->append;
9573
$store->set($iter, 0, $row[0]);
9580
#****f* lyricue/do_move_media
9584
# do_move_media($widget, $choosexml)
9594
my ($widget, $choosexml) = @_;
9595
debug("Moving media");
9596
if ($choosexml->get_widget('entryChoosePlay')->get_text() ne "") {
9597
my $type = $choosexml->get_widget('treeChoosePlay')->{'user_data'};
9598
my $category = $choosexml->get_widget('entryChoosePlay')->get_text();
9599
my $id = $choosexml->get_widget('windowChoosePlay')->{'user_data'};
9602
"UPDATE media SET category=\""
9607
$sth = $mediaDbh->prepare($query)
9608
|| display_fatal($errorcodes->{'sqlprepare'},
9609
$! . "\nSQL: " . $query);
9611
|| display_fatal($errorcodes->{'sqlexecute'},
9612
$! . "\nSQL: " . $query);
9615
close_dialog($widget);
9617
$widgets->{'image'}->get_widget('optionImageCategory')
9618
->get_menu->get_active->{user_data};
9620
$widgets->{'image'}->get_widget('optionImageCategory')->{'user_data'},
9626
#****f* lyricue/media_delete
9638
debug("Deleting media");
9639
my $selection = $widgets->{'image'}->get_widget('treeImage')->get_selection;
9640
my @selecteditems = $selection->get_selected_rows();
9642
if ($selecteditems[0]) {
9644
foreach (@selecteditems) {
9646
$widgets->{'image'}->get_widget('treeImage')
9647
->get_model->get_iter($_);
9649
$widgets->{'image'}->get_widget('treeImage')
9650
->get_model->get($iter, 1);
9652
. $widgets->{'image'}->get_widget('treeImage')
9653
->get_model->get($iter, 0) . "\", ";
9657
debug("Deleting $title");
9659
fromutf(gettext("Are you sure you wish to delete "))
9661
my $deletexml = Gtk2::GladeXML->new($globals->{'gladefile'},
9662
'dialogConfirm', 'lyricue');
9663
$deletexml->signal_autoconnect_from_package('');
9664
$deletexml->get_widget('labelDelete')->set_text($labelText);
9665
$deletexml->get_widget('dialogConfirm')
9666
->set_title(fromutf(gettext("Confirm Delete Image")));
9667
my $confirm = $deletexml->get_widget('dialogConfirm')->run();
9669
if ($confirm eq "ok") {
9673
my $query = "DELETE FROM media WHERE id=" . $_;
9675
my $sth = $mediaDbh->prepare($query)
9676
|| display_fatal($errorcodes->{'sqlprepare'},
9677
$! . "\nSQL: " . $query);
9678
my $rv = $sth->execute
9679
|| display_fatal($errorcodes->{'sqlexecute'},
9680
$! . "\nSQL: " . $query);
9682
close_dialog($deletexml->get_widget('dialogConfirm'));
9684
$widgets->{'image'}->get_widget('optionImageCategory')
9685
->get_menu->get_active->{user_data};
9687
$widgets->{'image'}->get_widget('optionImageCategory')
9700
#****f* lyricue/rename_media
9704
# rename_media($widget, $id, $newname)
9715
my ($widget, $id, $newname) = @_;
9716
debug("rename media");
9717
my $oldname = $widget->get('text');
9718
if ($oldname ne $newname) {
9720
$widgets->{'image'}->get_widget('treeImage')
9721
->get_model->get_iter_from_string($id);
9723
$widgets->{'image'}->get_widget('treeImage')
9724
->get_model->get($iter, 1);
9725
debug("Renaming media from $oldname to $newname");
9726
my $query = "UPDATE media SET description=\"$newname\" WHERE id=$id";
9728
my $sth = $mediaDbh->prepare($query)
9729
|| display_fatal($errorcodes->{'sqlprepare'},
9730
$! . "\nSQL: " . $query);
9731
my $rv = $sth->execute
9732
|| display_fatal($errorcodes->{'sqlexecute'},
9733
$! . "\nSQL: " . $query);
9735
$widgets->{'image'}->get_widget('optionImageCategory')
9737
$widgets->{'image'}->get_widget('optionImageCategory')
9738
->get_menu->get_active->{user_data}
9745
#****f* lyricue/change_colour_media
9747
# change_colour_media
9749
# change_colour_media($widget)
9751
# change colour media
9757
sub change_colour_media {
9759
debug("change colour media");
9761
$widgets->{'image'}->get_widget('entryImageFontColour')->get('text');
9763
$widgets->{'image'}->get_widget('entryImageShadowColour')->get('text');
9764
my $id = $widgets->{'image'}->get_widget('imageImage')->{user_data};
9767
my ($type, $id) = split /;/, $id;
9772
$id = substr $id, -100;
9774
if ($type eq "db") {
9775
debug("change_colour_media: $fontcolour, $shadowcolour, $id");
9777
"UPDATE media SET textcolour=\"$fontcolour\", shadowcolour=\"$shadowcolour\" WHERE id=$id";
9779
my $sth = $mediaDbh->prepare($query)
9780
|| display_fatal($errorcodes->{'sqlprepare'},
9781
$! . "\nSQL: " . $query);
9782
my $rv = $sth->execute
9783
|| display_fatal($errorcodes->{'sqlexecute'},
9784
$! . "\nSQL: " . $query);
9785
} elsif ($type eq "dir") {
9786
debug("change_colour_media: $fontcolour, $shadowcolour, $id");
9787
my $query = "DELETE FROM media WHERE format=\"file\" AND category=\"".$id."\"";
9789
my $sth = $mediaDbh->prepare($query)
9790
|| display_fatal($errorcodes->{'sqlprepare'},
9791
$! . "\nSQL: " . $query);
9792
my $rv = $sth->execute
9793
|| display_fatal($errorcodes->{'sqlexecute'},
9794
$! . "\nSQL: " . $query);
9795
$query = "INSERT INTO media (format, category, textcolour, shadowcolour) VALUES (\"file\", \"$id\", \"$fontcolour\", \"$shadowcolour\")";
9797
$sth = $mediaDbh->prepare($query)
9798
|| display_fatal($errorcodes->{'sqlprepare'},
9799
$! . "\nSQL: " . $query);
9801
|| display_fatal($errorcodes->{'sqlexecute'},
9802
$! . "\nSQL: " . $query);
9810
#****f* lyricue/restore_db
9822
debug("Restoring DB");
9824
# Get filename of DB
9825
my $fileDialog = Gtk2::GladeXML->new($globals->{'gladefile'},
9826
'dialogFileChooser', 'lyricue');
9827
$fileDialog->get_widget('dialogFileChooser')
9828
->set_title(fromutf(gettext("Select Database Backup file")));
9829
my $response = $fileDialog->get_widget('dialogFileChooser')->run();
9832
$fileDialog->get_widget('dialogFileChooser')->get_filename;
9833
close_dialog($fileDialog->get_widget('dialogFileChooser'));
9835
my $confirmDialog = Gtk2::GladeXML->new($globals->{'gladefile'},
9836
'dialogConfirm', 'lyricue');
9837
$confirmDialog->signal_autoconnect_from_package('');
9838
$confirmDialog->get_widget('dialogConfirm')
9839
->set_title(fromutf(gettext("Confirm Restore Database")));
9840
$confirmDialog->get_widget('labelDelete')->set_text(
9843
"WARNING: Restoring this database will overwrite your current database"
9847
my $confirm = $confirmDialog->get_widget('dialogConfirm')->run();
9849
if ($confirm eq "ok") {
9852
open(INPUT, "gzip -dc " . $filename . "|");
9860
$db =~ s/^USE (.*);.*$/$1/g;
9862
debug($db . " - database");
9863
if ($db eq "lyricDb") {
9865
} elsif ($db eq "mediaDb") {
9870
} elsif (/^INSERT INTO/) {
9873
my $tmptable = $insert;
9874
$tmptable =~ s/^INSERT INTO `(.*?)`.*$/$1/g;
9875
if ($tmptable ne $table) {
9877
my $query = "DELETE FROM " . $table;
9878
my $sth = $dbh->prepare($query)
9880
$errorcodes->{'sqlprepare'},
9881
$! . "\nSQL: " . $query
9883
my $rv = $sth->execute
9885
$errorcodes->{'sqlexecute'},
9886
$! . "\nSQL: " . $query
9889
my $sth = $dbh->prepare($insert)
9891
$errorcodes->{'sqlprepare'},
9892
$! . "\nSQL: " . $query
9894
my $rv = $sth->execute
9896
$errorcodes->{'sqlexecute'},
9897
$! . "\nSQL: " . $query
9904
close_dialog($confirmDialog->get_widget('dialogConfirm'));
9906
close_dialog($fileDialog->get_widget('dialogFileChooser'));
9912
#****f* lyricue/import_songs
9916
# import_songs($filename)
9918
# Import the songs from a single xml file
9920
# $filename - file to import songs from
9925
my ($filename) = @_;
9926
debug("Importing songs from xml file");
9929
if ($filename =~ /[zZ]$/) {
9930
open $fh, "gzip -dc \"" . $filename . "\" |";
9932
open $fh, $filename;
9934
binmode($fh, ":utf8");
9938
ForceArray => ['song', 'page'],
9939
SuppressEmpty => '',
9944
my $songs = $xml->{'song'};
9946
$widgets->{'select_songs'} = Gtk2::GladeXML->new($globals->{'gladefile'},
9947
'dialogSelectSongs', 'lyricue');
9948
$widgets->{'select_songs'}->signal_autoconnect_from_package('');
9950
my $model = Gtk2::ListStore->new(
9951
'Glib::Boolean', 'Glib::String', 'Glib::String', 'Glib::String',
9952
'Glib::Uint', 'Glib::Uint'
9954
my $renderer = Gtk2::CellRendererToggle->new;
9955
$renderer->signal_connect(
9957
my ($cell, $path_str, $model) = @_;
9958
my $path = Gtk2::TreePath->new_from_string($path_str);
9960
my $iter = $model->get_iter($path);
9961
my ($toggle_item) = $model->get($iter, $column);
9963
debug 'setting ' . $path_str . ' to ' . $toggle_item;
9966
$model->set($iter, $column, $toggle_item);
9971
Gtk2::TreeViewColumn->new_with_attributes("", $renderer, active => 0);
9973
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Title")),
9974
Gtk2::CellRendererText->new, text => 1);
9976
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Artist")),
9977
Gtk2::CellRendererText->new, text => 2);
9979
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Book")),
9980
Gtk2::CellRendererText->new, text => 3);
9982
Gtk2::TreeViewColumn->new_with_attributes(fromutf(gettext("Song Number")),
9983
Gtk2::CellRendererText->new, text => 4);
9984
$column1->set_resizable(TRUE);
9985
$column2->set_resizable(TRUE);
9986
$column3->set_resizable(TRUE);
9987
$column4->set_resizable(TRUE);
9988
$column5->set_resizable(TRUE);
9989
$widgets->{'select_songs'}->get_widget('treeSongImport')
9990
->append_column($column1);
9991
$widgets->{'select_songs'}->get_widget('treeSongImport')
9992
->append_column($column2);
9993
$widgets->{'select_songs'}->get_widget('treeSongImport')
9994
->append_column($column3);
9995
$widgets->{'select_songs'}->get_widget('treeSongImport')
9996
->append_column($column4);
9997
$widgets->{'select_songs'}->get_widget('treeSongImport')
9998
->append_column($column5);
10000
my @sorted_songs = sort {$a->{'name'} cmp $b->{'name'}} @$songs;
10001
foreach my $songnum (0 .. (@sorted_songs - 1)) {
10002
debug("Adding " . $songnum . ":" . $sorted_songs[$songnum]->{'name'});
10003
my $iter = $model->append;
10007
$sorted_songs[$songnum]->{'name'}, 2,
10008
$sorted_songs[$songnum]->{'artist'}, 3,
10009
$sorted_songs[$songnum]->{'book'}, 4,
10010
$sorted_songs[$songnum]->{'number'}, 5,
10014
$widgets->{'select_songs'}->get_widget('treeSongImport')->set_model($model);
10015
$widgets->{'select_songs'}->get_widget('treeSongImport')
10016
->set_headers_clickable(TRUE);
10018
$widgets->{'select_songs'}->get_widget('dialogSelectSongs')->run();
10019
if ($confirm == 1) {
10020
$model->foreach(\&do_import_songs, $songs);
10021
update_available();
10023
close_dialog($widgets->{'select_songs'}->get_widget('dialogSelectSongs'));
10028
#****f* lyricue/import_selection
10032
# import_selection($filename)
10034
# Change the selection in the import dialog
10036
sub import_selection {
10038
debug("Selection changing");
10040
$widgets->{'select_songs'}->get_widget('treeSongImport')->get_model;
10041
my $toggle = FALSE;
10042
if ($widget->get_name() eq "buttonImportAll") {
10047
my ($store, $path, $iter, $toggle) = @_;
10048
$store->set($iter, 0, $toggle);
10056
#****f* lyricue/do_import_songs
10060
# do_import_songs($store, $path, $iter, $songs)
10062
# Import each individual song if marked for import
10064
# $store - List store
10065
# $path - Path of item being checked
10066
# $iter - Iter of item
10067
# $songs - Parsed xml input
10069
sub do_import_songs {
10070
my ($store, $path, $iter, $songs) = @_;
10071
my $songnum = $store->get($iter, 5);
10072
if ($store->get($iter, 0)) {
10073
my $song = @$songs[$songnum];
10074
debug("Importing " . $song->{'name'});
10077
my $query = "SELECT MAX(id)+1 FROM lyricMain WHERE id < 2000000";
10078
my $sth = $lyricDbh->prepare($query)
10079
|| display_fatal($errorcodes->{'sqlprepare'},
10080
$! . "\nSQL: " . $query);
10081
my $rv = $sth->execute
10082
|| display_fatal($errorcodes->{'sqlexecute'},
10083
$! . "\nSQL: " . $query);
10084
my @row = $sth->fetchrow_array;
10085
my $songid = $row[0];
10086
if ((! defined $songid) || ($songid < 1)) {
10090
"INSERT INTO lyricMain ( id, title, songnum, book, artist, keywords, copyright, entered, written ) VALUES ( ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())";
10091
$sth = $lyricDbh->prepare($query)
10092
|| display_fatal($errorcodes->{'sqlprepare'},
10093
$! . "\nSQL: " . $query);
10095
$sth->execute($songid, $song->{'name'}, $song->{'number'},
10096
$song->{'book'}, $song->{'artist'}, $song->{'keywords'},
10097
$song->{'copyright'})
10098
|| display_fatal($errorcodes->{'sqlexecute'},
10099
$! . "\nSQL: " . $query);
10101
my $pages = $song->{'page'};
10103
foreach (@$pages) {
10105
debug("Page Add : " . $pagenum);
10107
"INSERT INTO page (songid,pagenum,lyrics) VALUES ("
10112
$sth = $lyricDbh->prepare($query)
10113
|| display_fatal($errorcodes->{'sqlprepare'},
10114
$! . "\nSQL: " . $query);
10115
$sth->execute || display_fatal($errorcodes->{'sqlexecute'},
10116
$! . "\nSQL: " . $query);
10123
#****f* lyricue/export_songs
10127
# export_songs($filename)
10129
# Export the songs into a single xml file
10131
# $filename - file to save songs as
10136
my ($filename) = @_;
10140
my $query = "SELECT * FROM lyricMain";
10142
my $sth = $lyricDbh->prepare($query)
10143
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
10144
my $rv = $sth->execute
10145
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
10146
while (my $row = $sth->fetchrow_hashref()) {
10148
"SELECT lyrics FROM page WHERE songid="
10150
. " ORDER BY pagenum";
10151
my $sth2 = $lyricDbh->prepare($query2)
10152
|| display_fatal($errorcodes->{'sqlprepare'},
10153
$! . "\nSQL: " . $query2);
10154
my $rv2 = $sth2->execute
10155
|| display_fatal($errorcodes->{'sqlexecute'},
10156
$! . "\nSQL: " . $query2);
10158
while (my $row2 = $sth2->fetchrow_hashref()) {
10159
push @pages, $row2->{'lyrics'};
10163
'name' => [$row->{'title'}],
10164
'number' => [$row->{'songnum'}],
10165
'book' => [$row->{'book'}],
10166
'artist' => [$row->{'artist'}],
10167
'keywords' => [$row->{'keywords'}],
10168
'copyright' => [$row->{'copyright'}],
10171
push @songs, $song;
10173
my $out = {'song' => \@songs};
10174
my $writer = XML::Simple->new();
10175
open my $fh, "| gzip -c - > \"" . $filename . "\"";
10176
binmode($fh, ":utf8");
10177
$writer->XMLout($out, OutputFile => $fh, RootName => 'lyricue');
10184
#****f* lyricue/backup_db
10190
# Backup DB selected
10196
debug("Backup DB selected");
10197
$widgets->{'backupdb'} =
10198
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogDatabase', 'lyricue');
10199
$widgets->{'backupdb'}->signal_autoconnect_from_package('');
10200
$widgets->{'backupdb'}->get_widget('entryPrefDBFilename')
10201
->set_text($ENV{"HOME"} . "/Lyricue_DB.gz");
10202
my $response = $widgets->{'backupdb'}->get_widget('dialogDatabase')->run();
10203
if ($response eq "ok") {
10205
$widgets->{'backupdb'}->get_widget('entryPrefDBFilename')->get_text();
10206
if (!($filename =~ /\.gz$/)) {
10207
$filename .= ".gz";
10209
my $databases = "";
10210
if ($widgets->{'backupdb'}->get_widget('checkLyricdb')->get_active()) {
10211
$databases .= "lyricDb ";
10213
if ($widgets->{'backupdb'}->get_widget('checkMediadb')->get_active()) {
10214
$databases .= "mediaDb ";
10218
"mysqldump --skip-extended-insert --no-create-db --no-create-info --complete-insert --user=lyric --password='' --databases "
10225
debug("Failed to execute: " . $command);
10227
debug("Backed up to " . $filename);
10230
close_dialog($widgets->{'backupdb'}->get_widget('dialogDatabase'));
10235
#****f* lyricue/backup_db_browse
10239
# backup_db_browse()
10241
# Browsing for BackupDB filename
10246
sub backup_db_browse {
10247
debug("Browsing for BackupDB filename");
10248
my $fileDialog = Gtk2::GladeXML->new($globals->{'gladefile'},
10249
'dialogFileChooser', 'lyricue');
10250
$fileDialog->get_widget('dialogFileChooser')
10252
$widgets->{'backupdb'}->get_widget('entryPrefDBFilename')->get_text());
10253
my $response = $fileDialog->get_widget('dialogFileChooser')->run();
10256
$fileDialog->get_widget('dialogFileChooser')->get_filename;
10257
if (!($filename =~ /\.gz$/)) {
10258
$filename .= ".gz";
10260
$widgets->{'backupdb'}->get_widget('entryPrefDBFilename')
10261
->set_text($filename);
10263
close_dialog($fileDialog->get_widget('dialogFileChooser'));
10268
#****f* lyricue/get_bibles
10274
# Getting available bibles
10281
debug("Getting available bibles");
10283
if ($^O ne 'MSWin32') {
10285
# Bibles provided by Sword libraries
10286
open(SWORD, $globals->{'diatheke'} . " -b system -k modulelist|");
10288
if (/^Biblical Texts:/) {
10290
if (/^Commentaries:/) {
10291
while (<SWORD>) { }
10294
my @bible = split(/:/, $_, 2);
10295
$bible[0] =~ s/\s+$//;
10296
$bible[1] =~ s/^\s+//;
10297
$bibles->{$bible[0]} = "sword;" . $bible[1];
10305
# Bible databases found
10306
my $dbs = $globals->{'db_available_db'};
10307
foreach (keys %$dbs) {
10309
my $db = db_connect($dbname, $errorcodes->{'bibledbopen'});
10311
my @tables = $db->tables;
10313
foreach (@tables) {
10314
my $tablename = $_;
10315
$tablename =~ s/^.*`(.*)`$/$1/g;
10316
$tablename =~ s/^"(.*)"$/$1/g;
10318
$db->selectall_arrayref("describe " . $tablename);
10319
if (!defined $tmpfields) {
10322
my @fields = @{$tmpfields};
10323
my $a = $fields[0]->[0];
10324
if ($a eq "verseid") {
10326
"SELECT verse FROM "
10328
. " WHERE book=\"Bible\";";
10330
my $sth = $db->prepare($query)
10331
|| display_fatal($errorcodes->{'sqlprepare'},
10332
$! . "\nSQL: " . $query);
10333
my $rv = $sth->execute
10334
|| display_fatal($errorcodes->{'sqlexecute'},
10335
$! . "\nSQL: " . $query);
10336
my $row = $sth->fetchrow_hashref();
10337
if (defined $row->{'verse'}) {
10338
$bibles->{$tablename . "@" . $dbname} =
10339
"db;" . $row->{'verse'};
10353
#****f* lyricue/navigator_changed
10355
# navigator_changed
10357
# navigator_changed()
10359
# Navigator changed
10364
sub navigator_changed {
10365
debug("Navigator changed");
10366
reset_timer($globals->{'nav_update_timer'});
10367
$globals->{'nav_update_timer'} =
10368
Glib::Timeout->add(500, \&navigator_update);
10373
#****f* lyricue/navigator_update
10377
# navigator_update()
10379
# Updating navigator
10384
sub navigator_update {
10385
debug("Updating navigator");
10386
reset_timer($globals->{'nav_update_timer'});
10387
if ((!defined $globals->{'bibledb'}) || ($globals->{'bibledb'} eq "")) {
10388
display_message($errorcodes->{'nobible'});
10391
my $buffer = Gtk2::TextBuffer->new();
10392
$buffer->set_text("");
10393
my $iter = $buffer->get_iter_at_offset(0);
10394
my $verse = $widgets->{'main'}->get_widget('entryNavVerse')->get_text();
10395
$verse =~ s/ (\D)/_$1/g;
10396
my ($book, $chapter, $startverse, $endverse) =
10397
split(/[ :\-,]/, $verse, 4);
10400
if (defined $book) {
10405
biblebrowser_init();
10408
if ((!defined $chapter) or ($chapter eq "") or ($chapter =~ /\D/)) {
10410
if ($browser eq "") {
10411
$browser = "chapter";
10412
biblebrowser_chapter(NULL, $book, "entry");
10415
if ( (!defined $startverse)
10416
or ($startverse eq "")
10417
or ($startverse =~ /\D/))
10421
if ( (!defined $endverse)
10422
or ($endverse eq "")
10423
or ($endverse =~ /\D/)
10424
or ($endverse < $startverse))
10426
$endverse = $startverse;
10433
. $startverse . "-"
10435
if ($browser eq "") {
10436
$browser = "verse";
10438
if (!$globals->{'usesword'}) {
10439
my ($table, $dbname) = split(/@/, $globals->{'bibledb'}, 2);
10441
"SELECT DISTINCT(book) FROM "
10443
. " WHERE book LIKE \""
10446
my $sth = $bibleDbh->prepare($query)
10447
|| display_fatal($errorcodes->{'sqlprepare'},
10448
$! . "\nSQL: " . $query);
10449
my $rv = $sth->execute
10450
|| display_fatal($errorcodes->{'sqlexecute'},
10451
$! . "\nSQL: " . $query);
10452
my @bookrow = $sth->fetchrow_array();
10453
if ((defined $bookrow[0]) && ($book ne "")) {
10454
$newbook = $bookrow[0];
10457
my $command = sprintf(
10458
"%s -b %s -e UTF8 -k '%s' 1:1 | head -1",
10459
$globals->{'diatheke'},
10460
$globals->{'bibledb'}, $book
10463
my $command_out = fromutf(`$command`);
10464
($newbook, undef) = split(/\s\d/, $command_out, 2);
10466
my $text = $widgets->{'main'}->get_widget('entryNavVerse')->get_text();
10467
$text =~ s/$book[ :\-]/$newbook /i;
10468
$widgets->{'main'}->get_widget('entryNavVerse')->set_text($text);
10469
$widgets->{'main'}->get_widget('entryNavVerse')->set_position(-1);
10470
biblebrowser_verse(NULL, 0, "entry");
10471
foreach my $num ($startverse .. $endverse) {
10472
my $button = "button" . ($num - 1);
10473
if (defined $widgets->{'bibleBrowser'}{$button}) {
10474
$widgets->{'bibleBrowser'}{$button}->set_active(TRUE);
10478
if ($globals->{'usesword'}) {
10479
my $command = sprintf(
10480
"%s -b %s -e UTF8 -k '%s' %d:%d-%d |tr \\\\n \' \'",
10481
$globals->{'diatheke'},
10482
$globals->{'bibledb'}, $book, $chapter, $startverse, $endverse,
10486
my $command_out = fromutf(`$command`);
10487
($book, undef) = split(/\s\d/, $command_out, 2);
10488
my @command_lines = split(/$book /, $command_out);
10491
foreach $lineno (1 .. @command_lines) {
10492
my $line2 = $command_lines[$lineno - 1];
10494
if ($line2 ne "") {
10495
if ($lineno != @command_lines) {
10498
$buffer->create_mark($mark, $iter, TRUE);
10499
insert_link($buffer, $iter, $mark, $line2);
10503
$buffer->create_mark($mark, $iter, TRUE);
10505
# remove the trailing bible name
10506
#$quicktext =~ s/\($globals->{'bibledb'}\)/\n/g;
10508
my ($table, $dbname) = split(/@/, $globals->{'bibledb'}, 2);
10510
"SELECT book FROM " . $table . " WHERE book LIKE \"" . $book . "%\"";
10512
$sth = $bibleDbh->prepare($query)
10513
|| display_fatal($errorcodes->{'sqlprepare'},
10514
$! . "\nSQL: " . $query);
10515
$rv = $sth->execute
10516
|| display_fatal($errorcodes->{'sqlexecute'},
10517
$! . "\nSQL: " . $query);
10518
my @bookrow = $sth->fetchrow_array();
10519
if ((defined $bookrow[0]) && ($book ne "")) {
10520
$book = $bookrow[0];
10521
my ($table, $dbname) = split(/@/, $globals->{'bibledb'}, 2);
10523
"SELECT book,chapternum,versenum,verse FROM "
10525
. " WHERE book LIKE \""
10527
. "%\" AND chapternum="
10529
. " AND versenum>="
10531
. " AND versenum <= "
10533
. " ORDER BY versenum";
10535
$sth = $bibleDbh->prepare($query)
10536
|| display_fatal($errorcodes->{'sqlprepare'},
10537
$! . "\nSQL: " . $query);
10538
$rv = $sth->execute
10539
|| display_fatal($errorcodes->{'sqlexecute'},
10540
$! . "\nSQL: " . $query);
10542
while (my @row = $sth->fetchrow_array()) {
10543
my $verse = $row[1] . ":" . $row[2] . " " . $row[3] . "\n";
10544
$buffer->create_mark($mark, $iter, TRUE);
10545
insert_link($buffer, $iter, $mark, $verse);
10548
$buffer->create_mark($mark, $iter, TRUE);
10552
$widgets->{'main'}->get_widget('entryNavVerse')->{user_data} =
10553
$book . " " . $chapter . ":" . $startverse . "-" . $endverse;
10554
my $oldtext = get_buffer_text(
10555
$widgets->{'main'}->get_widget('textNavView')->get_buffer());
10556
my $quicktext = get_buffer_text($buffer);
10557
if ($oldtext ne $quicktext) {
10558
$widgets->{'main'}->get_widget('textNavView')->set_buffer($buffer);
10559
if ($widgets->{'main'}->get_widget('checkNavAuto')->get_active()) {
10567
#****f* lyricue/navigator_enter
10571
# navigator_enter()
10578
sub navigator_enter {
10579
navigator_update();
10585
#****f* lyricue/navigator_show
10591
# Bible navigator showing on server
10596
sub navigator_show {
10597
debug("Bible navigator showing on server");
10598
my $buffer = $widgets->{'main'}->get_widget('textNavView')->get_buffer();
10599
my $songtext = $buffer->get_text($buffer->get_bounds, FALSE);
10600
$songtext =~ s/\n/#BREAK#/g;
10601
$songtext =~ s/:/#SEMI#/g;
10604
$widgets->{'main'}->get_widget('entryNavVerse')->{user_data}
10605
. "#BREAK##BREAK##BREAK#wrap";
10607
update_display("preview", $verse, $songtext);
10612
#****f* lyricue/navigator_add
10618
# Adding verses from Bible navigator to playlist
10623
sub navigator_add {
10624
debug("Adding verses from Bible navigator to playlist");
10625
my $verse = $widgets->{'main'}->get_widget('entryNavVerse')->{user_data};
10626
$verse =~ s/ (\D)/_$1/;
10627
my ($book, $chapter, $startverse, $endverse) =
10628
split(/[ :\-,]/, $verse, 4);
10630
insert_verse($book, $chapter, $startverse, $endverse);
10635
#****f* lyricue/navigator_next
10641
# Showing next verse
10646
sub navigator_next {
10647
debug("Showing next verse");
10648
my $verse = $widgets->{'main'}->get_widget('entryNavVerse')->{user_data};
10649
$verse =~ s/ (\D)/_$1/;
10650
my ($book, $chapter, $startverse, $endverse) =
10651
split(/[ :\-,]/, $verse, 4);
10656
my $maxv = get_max_verse($book, $chapter, $startverse, $endverse);
10658
if ($maxv < $endverse) {
10664
if (!$globals->{'usesword'}) {
10665
my ($table, $dbname) = split(/@/, $globals->{'bibledb'}, 2);
10667
"SELECT MAX(versenum) FROM "
10671
. "\" AND chapternum="
10674
my $sth = $bibleDbh->prepare($query)
10675
|| display_fatal($errorcodes->{'sqlprepare'},
10676
$! . "\nSQL: " . $query);
10677
my $rv = $sth->execute
10678
|| display_fatal($errorcodes->{'sqlexecute'},
10679
$! . "\nSQL: " . $query);
10680
my @row = $sth->fetchrow_array();
10682
if ($endverse > $row[0]) {
10683
$endverse = $row[0];
10685
if ($startverse > $row[0]) {
10686
$startverse = $row[0];
10690
$verse = $book . " " . $chapter . ":" . $startverse . "-" . $endverse;
10691
$widgets->{'main'}->get_widget('entryNavVerse')->set_text($verse);
10692
navigator_update();
10698
#****f* lyricue/navigator_prev
10704
# Showing next verse
10709
sub navigator_prev {
10710
debug("Showing previous verse");
10711
my $verse = $widgets->{'main'}->get_widget('entryNavVerse')->{user_data};
10712
$verse =~ s/ (\D)/_$1/;
10713
my ($book, $chapter, $startverse, $endverse) =
10714
split(/[ :\-,]/, $verse, 4);
10718
if ($startverse < 1) {
10721
$endverse = get_max_verse($book, $chapter, $startverse, $endverse);
10722
$verse = $book . " " . $chapter . ":" . $startverse . "-" . $endverse;
10723
$widgets->{'main'}->get_widget('entryNavVerse')->set_text($verse);
10724
navigator_update();
10730
#****f* lyricue/reset_timer
10734
# reset_timer($timer)
10745
debug("Cancelling timer");
10746
Glib::Source->remove($timer);
10753
#****f* lyricue/do_pending
10765
while (Gtk2->events_pending) {
10766
Gtk2->main_iteration;
10772
#****f* lyricue/get_max_verse
10776
# get_max_verse($book, $chapter, $startverse, $endverse)
10787
sub get_max_verse {
10788
my ($book, $chapter, $startverse, $endverse) = @_;
10790
if ($config->{'Main'} eq "") {
10791
$config = load_config();
10793
if ($config->{'Width'} == 0) {
10794
$config->{'Width'} = 800;
10795
$config->{'Height'} = 600;
10797
debug("Get max verse that fits within ".$config->{'Width'}."x".$config->{'Height'});
10799
my $pageHeight = 0;
10802
$widgets->{'main'}->get_widget('windowMain')->create_pango_layout("");
10803
$layout->set_wrap('word');
10804
$layout->set_width(($config->{'Width'} - $config->{'OverscanH'}) * PANGO_SCALE);
10805
$layout->set_font_description(
10806
Gtk2::Pango::FontDescription->from_string($config->{'Main'}));
10810
if (!$globals->{'usesword'}) {
10811
my ($table, $dbname) = split(/@/, $globals->{'bibledb'}, 2);
10818
. "\" AND chapternum="
10820
. " AND versenum>="
10822
. " AND versenum <= "
10824
. " ORDER BY versenum";
10826
$sth = $bibleDbh->prepare($query)
10827
|| display_fatal($errorcodes->{'sqlprepare'},
10828
$! . "\nSQL: " . $query);
10830
$rv = $sth->execute
10831
|| display_fatal($errorcodes->{'sqlexecute'},
10832
$! . "\nSQL: " . $query);
10836
my $versenum = $startverse;
10839
if ($globals->{'usesword'}) {
10840
my $command = sprintf(
10841
"%s -b %s -e UTF8 -k '%s' %d:%d-%d | sed -e 's/^%s //g' | head -n -1",
10842
$globals->{'diatheke'},
10843
$globals->{'bibledb'}, $book, $chapter, $startverse, $versenum,
10847
$line = `$command`;
10849
if ($versenum > $endverse - 1) { $loop = FALSE; }
10852
if (!defined $line) { $loop = FALSE; }
10853
if ($row = $sth->fetchrow_hashref()) {
10855
$row->{'chapternum'} . ":"
10856
. $row->{'versenum'} . " "
10858
$versenum = $row->{'versenum'};
10864
$layout->set_text($page . "\n" . $line);
10865
my ($pageWidth, $pageHeight) = $layout->get_pixel_size;
10867
if ($pageHeight > $config->{'Height'} - (100 + $config->{'OverscanV'})) {
10868
if ($versenum > $startverse) { $versenum--; }
10871
$page = $page . "\n" . $line;
10874
if ($versenum > $endverse) {
10875
$versenum = $endverse;
10880
# Inserts a piece of text into the buffer, giving it the usual
10881
# appearance of a hyperlink in a web browser: blue and underlined.
10882
# Additionally, attaches some data on the tag, to make it recognizable
10887
#****f* lyricue/insert_link
10891
# insert_link($buffer, $iter, $mark, $verse)
10903
my ($buffer, $iter, $mark, $verse) = @_;
10904
my $tag = $buffer->create_tag(
10906
foreground => "blue",
10907
underline => 'single'
10909
$tag->{markname} = $mark;
10910
$buffer->create_mark($mark, $iter, TRUE);
10911
my ($chap, $num, $text) = split(/[:\ ]/, $verse, 3);
10912
$verse = $chap . ":" . $num;
10913
$text = " " . $text;
10914
$buffer->insert_with_tags($iter, $verse, $tag);
10915
$buffer->insert($iter, $text);
10918
# Looks at all tags covering the position of iter in the text view,
10919
# and if one of them is a link, follow it by showing the page identified
10920
# by the data attached to it.
10924
#****f* lyricue/follow_if_link
10928
# follow_if_link($text_view, $iter)
10930
# Showing $book $verse
10937
sub follow_if_link {
10938
my ($text_view, $iter) = @_;
10939
my $verse = $widgets->{'main'}->get_widget('entryNavVerse')->{user_data};
10940
$verse =~ s/ (\D)/_$1/;
10941
my ($book, $chapter, $startverse, $endverse) =
10942
split(/[ :\-,]/, $verse, 4);
10944
foreach my $tag ($iter->get_tags) {
10945
my $buffer = $text_view->get_buffer();
10946
my $mark = $buffer->get_mark($tag->{markname});
10947
my $startiter = $buffer->get_iter_at_mark($mark);
10949
$buffer->get_iter_at_mark($buffer->get_mark($tag->{markname} + 1));
10950
my $quicktext = $buffer->get_text($startiter, $enditer, FALSE);
10951
if ($verse ne "") {
10952
debug("Showing $book $verse");
10961
#****f* lyricue/navigator_event_after
10963
# navigator_event_after
10965
# navigator_event_after($text_view, $event)
10967
# Navigator text clicked
10974
sub navigator_event_after {
10975
my ($text_view, $event) = @_;
10976
debug("Navigator text clicked");
10977
return FALSE unless $event->type eq 'button-release';
10978
return FALSE unless $event->button == 1;
10979
my $buffer = $text_view->get_buffer;
10981
# we shouldn't follow a link if the user has selected something
10982
my ($start, $end) = $buffer->get_selection_bounds;
10983
return FALSE if defined $end and $start->get_offset != $end->get_offset;
10985
$text_view->window_to_buffer_coords('widget', $event->x, $event->y);
10986
my $iter = $text_view->get_iter_at_location($x, $y);
10987
follow_if_link($text_view, $iter);
10993
#****f* lyricue/text_set_cursor_if_appropriate
10995
# text_set_cursor_if_appropriate
10997
# text_set_cursor_if_appropriate($text_view, $x, $y)
11007
sub text_set_cursor_if_appropriate {
11008
my ($text_view, $x, $y) = @_;
11009
$globals->{'hovering'} = FALSE;
11010
my $buffer = $text_view->get_buffer;
11011
my $iter = $text_view->get_iter_at_location($x, $y);
11012
foreach my $tag ($iter->get_tags) {
11013
if (defined $tag->{markname}) {
11014
$globals->{'hovering'} = TRUE;
11019
if ($globals->{'hovering'} != $globals->{'hovering_over_link'}) {
11020
$globals->{'hovering_over_link'} = $globals->{'hovering'};
11021
$text_view->get_window('text')->set_cursor(
11022
$globals->{'hovering_over_link'}
11023
? $globals->{'hand_cursor'}
11024
: $globals->{'text_cursor'}
11029
# Update the cursor image if the pointer moved.
11033
#****f* lyricue/text_motion_notify_event
11035
# text_motion_notify_event
11037
# text_motion_notify_event($text_view, $event)
11046
sub text_motion_notify_event {
11047
my ($text_view, $event) = @_;
11049
$text_view->window_to_buffer_coords('widget', $event->x, $event->y);
11050
text_set_cursor_if_appropriate($text_view, $x, $y);
11051
$text_view->window->get_pointer;
11055
# Also update the cursor image if the window becomes visible
11056
# (e.g. when a window covering it got iconified).
11060
#****f* lyricue/text_visibility_notify_event
11062
# text_visibility_notify_event
11064
# text_visibility_notify_event($text_view, $event)
11073
sub text_visibility_notify_event {
11074
my ($text_view, $event) = @_;
11075
my (undef, $wx, $wy, undef) = $text_view->window->get_pointer;
11076
my ($bx, $by) = $text_view->window_to_buffer_coords('widget', $wx, $wy);
11077
text_set_cursor_if_appropriate($text_view, $bx, $by);
11083
#****f* lyricue/import_song_from_file
11085
# import_song_from_file
11087
# import_song_from_file($filename)
11095
sub import_song_from_file {
11096
my ($filename) = @_;
11097
import_songs($filename);
11102
#****f* lyricue/import_song_songselect
11104
# import_song_songselect
11106
# import_song_songselect($filename)
11108
# import songselect song
11114
sub import_song_songselect {
11115
my ($filename) = @_;
11116
debug("import songselect song");
11117
open(SONG, $filename) || return;
11123
my @line = split(/=/, $_, 2);
11126
$widgets->{'add'}->get_widget('entryEditName')->set_text($line[1]);
11127
} elsif (/Author/) {
11128
$widgets->{'add'}->get_widget('entryEditArtist')
11129
->set_text($line[1]);
11130
} elsif (/Copyright/) {
11131
$widgets->{'add'}->get_widget('entryEditCopyright')
11132
->set_text($line[1]);
11133
} elsif (/Themes/) {
11134
$line[1] =~ s/\/t/ /g;
11135
$widgets->{'add'}->get_widget('entryEditKeywords')
11136
->set_text($line[1]);
11137
} elsif (/Words/) {
11138
my @words = split(/\/t/, $line[1]);
11143
if ($hashnum == 0) {
11144
$widgets->{'textAPageB'}{$hashnum}->set_text($_);
11147
$hashnum = add_page();
11148
$widgets->{'textAPageB'}{$hashnum}->set_text($_);
11160
#****f* lyricue/import_song_opw
11164
# import_song_opw($filename)
11172
sub import_song_opw {
11173
my ($filename) = @_;
11174
debug("import opw song");
11178
open(OPW, $filename) || die("Unable to open $filename");
11180
$input .= fromutf("cp-1252", $_);
11184
$input =~ /bundel>(.*)<\/bundel/;
11185
$widgets->{'add'}->get_widget('entryEditBook')->set_text($1);
11187
$input =~ /nummer>(.*)<\/nummer/;
11188
$widgets->{'add'}->get_widget('entryEditNumber')->set_text($1);
11190
$input =~ /titel>(.*)<\/titel/;
11191
$widgets->{'add'}->get_widget('entryEditName')->set_text($1);
11193
$input =~ /copyrights>(.*)<\/copyrights/;
11194
$widgets->{'add'}->get_widget('entryEditCopyright')->set_text($1);
11196
$input =~ /beginregel>(.*)<\/beginregel/;
11197
$widgets->{'add'}->get_widget('entryEditKeywords')->set_text($1);
11199
$input =~ /tekst>(.*)<\/tekst/s;
11202
my @lyrics = split(/\n \n/, $lyrics);
11204
foreach (@lyrics) {
11208
$_ =~ s/^[0-9]*\. //g;
11209
if ($hashnum == 0) {
11210
$widgets->{'textAPageB'}{$hashnum}->set_text($_);
11213
$hashnum = add_page();
11214
$widgets->{'textAPageB'}{$hashnum}->set_text($_);
11222
#****f* lyricue/import_song_html
11226
# import_song_html($filename)
11228
# import HTML/Opensong song
11234
sub import_song_html {
11235
my ($filename) = @_;
11236
debug("import HTML/Opensong song");
11237
my ($name, $author) = "";
11242
open(HTML, $filename) || die("Unable to open $filename");
11245
if (/div id="title"/) {
11247
$name =~ s/^.*id=\"title\">(.*)<\/div>.*$/$1/g;
11248
$widgets->{'add'}->get_widget('entryEditName')->set_text($name);
11249
} elsif (/div id="author"/) {
11251
$author =~ s/^.*id="author">(.*)<\/div>.*/$1/g;
11252
$widgets->{'add'}->get_widget('entryEditArtist')->set_text($author);
11253
} elsif (/div class="heading"/) {
11258
my $iter = $widgets->{'textAPageB'}{$hashnum}->get_end_iter();
11259
$widgets->{'textAPageB'}{$hashnum}->insert($iter, $page);
11261
$hashnum = add_page();
11263
} elsif (/td class="lyrics"/) {
11265
$line =~ s/^.*class="lyrics">(.*)<\/td>.*/$1/g;
11266
$line =~ s/ / /g;
11268
} elsif (/<\/table>/) {
11275
my $iter = $widgets->{'textAPageB'}{$hashnum}->get_end_iter();
11276
$widgets->{'textAPageB'}{$hashnum}->insert($iter, $page);
11282
# Install database functions
11286
#****f* lyricue/db_check_app
11292
# Checking for database servers
11298
debug("Checking for database servers");
11299
if (defined $globals->{'force_sqlite'} && ($globals->{'force_sqlite'})) {
11300
debug("Forcing usage of SQLite3");
11301
$config->{'DatabaseType'} = "SQLite";
11304
my @ary = DBI->available_drivers(1);
11306
my $sqlite = FALSE;
11308
if ($_ eq "mysql") {
11310
} elsif ($_ eq "SQLite") {
11315
$config->{'DatabaseType'} = "mysql";
11316
} elsif ($sqlite) {
11317
$config->{'DatabaseType'} = "SQLite";
11319
die("No supported DB found");
11325
#****f* lyricue/db_get_admin
11331
# Get the db admin login information
11337
debug("Get the db admin login information");
11341
$dbh = DBI->connect(
11343
. $config->{'DatabaseType'}
11345
. $globals->{'mysqlhost'},
11350
$globals->{'db_adminuser'} = "root";
11351
$globals->{'db_adminpassword'} = "";
11355
if ($config->{'DatabaseType'} eq "mysql") {
11356
my $adminxml = Gtk2::GladeXML->new($globals->{'gladefile'},
11357
'dialogAdminLogin', 'lyricue');
11358
$adminxml->signal_autoconnect_from_package('');
11359
my $confirm = $adminxml->get_widget('dialogAdminLogin')->run();
11360
if ($confirm == 0) {
11361
$globals->{'db_adminuser'} =
11362
$adminxml->get_widget('entryAdminLogin')->get_text();
11363
$globals->{'db_adminpassword'} =
11364
$adminxml->get_widget('entryAdminPass')->get_text();
11366
my $confirmxml = Gtk2::GladeXML->new($globals->{'gladefile'},
11367
'dialogConfirm', 'lyricue');
11368
$confirmxml->signal_autoconnect_from_package('');
11369
$confirmxml->get_widget('labelDelete')
11371
fromutf(gettext("Are you sure you want to exit Lyricue?")));
11372
$confirm = $confirmxml->get_widget('dialogConfirm')->run();
11373
close_dialog($adminxml->get_widget('dialogAdminLogin'));
11374
if ($confirm eq "ok") {
11375
debug("Exiting on request");
11383
close_dialog($adminxml->get_widget('dialogAdminLogin'));
11385
$globals->{'db_adminuser'} = "lyricue";
11386
$globals->{'db_adminpassword'} = "";
11390
$dbh = DBI->connect(
11392
. $config->{'DatabaseType'}
11394
. $globals->{'mysqlhost'},
11395
$globals->{'db_adminuser'}, $globals->{'db_adminpassword'}
11400
debug("Password incorrect - retry");
11407
#****f* lyricue/db_install_user
11411
# db_install_user()
11413
# Install lyric database user
11418
sub db_install_user {
11419
debug("Install lyric database user");
11422
if ($config->{'DatabaseType'} eq "mysql") {
11424
$dbh = DBI->connect(
11426
. $config->{'DatabaseType'}
11428
. $globals->{'mysqlhost'},
11429
$globals->{'db_adminuser'}, $globals->{'db_adminpassword'}
11433
my $labelText = fromutf(
11436
"Unable to login to database as admin, maybe the database is down.\nPlease re-enter your database admin login and retry"
11439
my $loginxml = Gtk2::GladeXML->new($globals->{'gladefile'},
11440
'dialogConfirm', 'lyricue');
11441
$loginxml->signal_autoconnect_from_package('');
11442
$loginxml->get_widget('dialogConfirm')
11443
->set_title(fromutf(gettext("Login Error")));
11444
$loginxml->get_widget('labelDelete')->set_text($labelText);
11445
my $confirm = $loginxml->get_widget('dialogConfirm')->run();
11446
if ($confirm eq "ok") {
11447
close_dialog($loginxml->get_widget('dialogConfirm'));
11451
display_fatal($errorcodes->{'lyricdbopen'}, $DBI::errstr);
11455
my $sth = $dbh->prepare("select * from user where User='lyric'");
11456
my $rv = $sth->execute;
11459
debug("User already setup\n");
11461
debug("Creating mysql user..");
11462
$sth = $dbh->prepare(
11463
"insert into user set Host='%',User='lyric',Password='',Select_priv='Y',Insert_priv='Y', Update_priv='Y',Delete_priv='Y',Lock_tables_priv='Y',"
11466
$sth = $dbh->prepare(
11467
"insert into user set Host='localhost',User='lyric',Password='',Select_priv='Y',Insert_priv='Y', Update_priv='Y',Delete_priv='Y',Lock_tables_priv='Y'"
11470
$sth = $dbh->prepare("flush privileges");
11474
db_check_databases();
11479
#****f* lyricue/db_check_databases
11481
# db_check_databases
11483
# db_check_databases()
11485
# Update/install databases
11490
sub db_check_databases {
11491
debug("Update/install databases");
11492
if ($config->{'DatabaseType'} eq "mysql") {
11493
my @dbs = DBI->data_sources($config->{'DatabaseType'},
11494
{"host" => $globals->{'mysqlhost'}, "user" => "lyric"});
11497
$_ =~ s/^DBI:.*://g;
11498
$globals->{'db_available_db'}{$_} = TRUE;
11501
opendir(DIR, $globals->{'basedir'});
11502
while (readdir(DIR)) {
11505
$globals->{'db_available_db'}{$_} = TRUE;
11510
if ($globals->{'db_available_db'}{'lyricDb'}) {
11511
db_updatedb_lyricDb();
11513
db_installdb($globals->{'sharedir'} . "mysql/Create_lyricDb.sql",
11517
if ($globals->{'db_available_db'}{'mediaDb'}) {
11518
db_updatedb_mediaDb();
11520
debug("Creating mediaDb");
11521
db_installdb($globals->{'sharedir'} . "mysql/Create_mediaDb.sql",
11525
# Don't do this anymore - leave stuff in their homes
11526
#debug("Importing existing backgrounds/images\n");
11528
# NOTE FAILS WITH SQLITE
11529
#if ($config->{'DatabaseType'} eq "mysql") {
11530
# system("import_media img " . $globals->{'sharedir'} . "images");
11531
# system("import_media bg " . $globals->{'sharedir'} . "backgrounds");
11539
#****f* lyricue/db_reload
11551
debug("Reload db");
11552
if ($globals->{'db_adminuser'} eq "") {
11555
if ($config->{'DatabaseType'} eq "mysql") {
11556
my $drh = DBI->install_driver('mysql');
11557
my $rc = $drh->func(
11560
$globals->{'mysqlhost'}, $globals->{'db_adminuser'},
11561
$globals->{'adminpassword'},
11570
#****f* lyricue/db_installdb
11574
# db_installdb($db_file, $db_name)
11584
my ($db_file, $db_name) = @_;
11585
debug("Install db from " . $db_file);
11586
if ($globals->{'db_adminuser'} eq "") {
11589
if ($config->{'DatabaseType'} eq "mysql") {
11592
. " | mysql -f -h "
11593
. $globals->{'mysqlhost'} . " -u "
11594
. $globals->{'db_adminuser'}
11596
. $globals->{'db_adminpassword'}."\"");
11598
my $dbh = db_connect($db_name, "Unable to create DB:" . $db_name);
11599
open(DB, $db_file);
11602
$_ =~ s/^CREATE DATABASE*;$//g;
11603
$_ =~ s/^USE *;$//g;
11604
if ( (/^ *UNIQUE KEY/)
11606
|| (/^CREATE DATABASE /)
11611
$_ =~ s/(PRIMARY KEY .*),$/$1/g;
11612
$_ =~ s/auto_increment,$/,/g;
11613
$_ =~ s/TYPE=MyISAM;$/;/g;
11614
$_ =~ s/unsigned NOT NULL/NOT NULL/g;
11615
$_ =~ s/int(11)/INTEGER/g;
11623
if ($query ne "") {
11629
$dbh->disconnect();
11635
#****f* lyricue/db_updatedb_mediaDb
11637
# db_updatedb_mediaDb
11639
# db_updatedb_mediaDb()
11641
# Update the mediaDb table if needed
11646
sub db_updatedb_mediaDb {
11647
debug("Update the mediaDb table if needed");
11648
my $dbh = db_connect($globals->{'mediadb'}, "");
11649
if ($config->{'DatabaseType'} eq "mysql") {
11650
my $fields = $dbh->selectall_arrayref("describe media");
11652
foreach (@$fields) {
11653
$trans->{$_->[0]} = 1;
11655
if (!defined $trans->{'textcolour'}) {
11656
debug("Text Colouring fields not found\n");
11657
debug("Upgrading database from 1.9 to 1.9.4\n");
11658
db_installdb($globals->{'sharedir'} . "mysql/Update_1.9.4.sql",
11667
#****f* lyricue/db_updatedb_lyricDb
11669
# db_updatedb_lyricDb
11671
# db_updatedb_lyricDb()
11673
# Update the lyricDb table if needed
11678
sub db_updatedb_lyricDb {
11679
debug("Update the lyricDb table if needed");
11680
my $dbh = db_connect($globals->{'lyricdb'}, $errorcodes->{'lyricdbopen'});
11681
my @tables = $dbh->tables;
11683
foreach (@tables) {
11684
$_ =~ s/^.*`(.*)`$/$1/g;
11685
$_ =~ s/^"(.*)"$/$1/g;
11688
if (!defined $table->{'associations'}) {
11689
debug("Associations table not found\n");
11690
debug("Upgrading database from < 1.2 to 1.2\n");
11691
db_installdb($globals->{'sharedir'} . "mysql/Update_1.2.sql",
11695
if (!defined $table->{'config'}) {
11696
debug("Configuration tables not found\n");
11697
debug("Upgrading database from < 2.4 to 2.4\n");
11698
db_installdb($globals->{'sharedir'} . "mysql/Update_2.4.sql",
11702
if ($config->{'DatabaseType'} eq "mysql") {
11703
my $fields = $dbh->selectall_arrayref("describe playlist");
11705
foreach (@$fields) {
11706
$trans->{$_->[0]} = 1;
11708
if (!defined $trans->{'transition'}) {
11709
debug("Transition field not found\n");
11710
debug("Upgrading database from 1.2 to 1.9\n");
11711
db_installdb($globals->{'sharedir'} . "mysql/Update_1.9.sql",
11717
# Increase data size - does nothing if already done - only works for mysql
11718
if ($config->{'DatabaseType'} eq "mysql") {
11719
my $fields = $dbh->selectall_arrayref("describe playlist");
11721
foreach (@$fields) {
11722
$pl->{$_->[0]} = $_->[1];
11724
if ($pl->{'data'} ne "varchar(256)") {
11725
db_installdb($globals->{'sharedir'} . "mysql/Update_1.9.7.sql",
11731
if ($config->{'DatabaseType'} eq "mysql") {
11732
my $fields = $dbh->selectall_arrayref("describe page");
11734
foreach (@$fields) {
11735
$page->{$_->[0]} = $_->[1];
11737
if (!defined $page->{'pagetitle'}) {
11738
db_installdb($globals->{'sharedir'} . "mysql/Update_2.1.0.sql",
11743
# Ensure all tables are in UTF8 characterset
11744
my @toconvert = ();
11745
foreach my $tname (keys %$table) {
11746
my $fields = $dbh->selectall_arrayref("show create table " . $tname);
11747
foreach (@$fields) {
11748
if (!($_->[1] =~ /CHARSET=utf8/)) {
11749
push @toconvert, $tname;
11754
if (@toconvert > 0) {
11755
if ($globals->{'db_adminuser'} eq "") {
11759
$dbh = DBI->connect(
11761
. $config->{'DatabaseType'}
11763
. $globals->{'mysqlhost'},
11764
$globals->{'db_adminuser'}, $globals->{'db_adminpassword'}
11768
foreach (@toconvert) {
11769
debug("Converting " . $_ . " to utf8");
11770
$dbh->do("ALTER TABLE lyricDb."
11772
. " CONVERT TO CHARACTER SET utf8");
11781
#****f* lyricue/check_tracker
11792
sub check_tracker {
11794
#debug("Check tracker");
11795
my $query = "SELECT ref,title FROM playlists WHERE id=-1";
11797
#qdebug($query); # Commented out because it's too noisy
11798
my $sth = $lyricDbh->prepare($query)
11799
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
11800
my $rv = $sth->execute
11801
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
11802
my @row = $sth->fetchrow_array();
11805
if (@row && ($row[0] ne $globals->{'current_item'})) {
11806
$globals->{'previous_item'} = $globals->{'current_item'};
11807
$globals->{'current_item'} = $row[0];
11808
my $model = $widgets->{'main'}->get_widget('treePlaylist')->get_model();
11810
$globals->{'current_item_path'} = "";
11811
$model->foreach(\&update_current);
11812
if ($globals->{'current_item_path'} ne "") {
11813
my $path = Gtk2::TreePath->new_from_string(
11814
$globals->{'current_item_path'});
11815
while ($path->up()) {
11816
if ($path->get_depth() > 0) {
11817
my $iter = $model->get_iter($path);
11819
$model->set($iter, 1, $config->{'HighlightColour'});
11826
if (defined($row[1]) && $row[1] ne "") {
11827
my $blank_text = $widgets->{'main'}->get_widget('buttonMainClear')->get_active();
11828
my $blank_bg = $widgets->{'main'}->get_widget('buttonMainBlank')->get_active();
11829
my $blank_text_new = $blank_text;
11830
my $blank_bg_new = $blank_bg;
11831
if ($row[1] =~ /^blank_bg/) {
11832
$row[1] =~ s/^blank_bg//g;
11833
$blank_bg_new = TRUE;
11834
$blank_text_new = FALSE;
11835
} elsif ($row[1] =~ /^blank_text/) {
11836
$row[1] =~ s/^blank_text//g;
11837
$blank_bg_new = FALSE;
11838
$blank_text_new = TRUE;
11840
$blank_bg_new = FALSE;
11841
$blank_text_new = FALSE;
11843
if ($blank_bg != $blank_bg_new) {
11844
$globals->{'ignore_blank'} = TRUE;
11845
$widgets->{'main'}->get_widget('buttonMainBlank')->set_active($blank_bg_new);
11847
if ($blank_text != $blank_text_new) {
11848
$globals->{'ignore_clear'} = TRUE;
11849
$widgets->{'main'}->get_widget('buttonMainClear')->set_active($blank_text_new);
11851
my ($position, $duration, $status) = split(/;/, $row[1], 3);
11852
my $hscale = $widgets->{'main'}->get_widget('hscaleMediaPosition');
11853
if (defined $globals->{'video_skip_signal'}) {
11854
$hscale->signal_handler_disconnect($globals->{'video_skip_signal'});
11856
if ($duration <= 0) {
11857
$hscale->set_range(0, 1000);
11859
$hscale->set_range(0, $duration);
11861
$hscale->set_value($position);
11862
$position = sprintf("%d:%02d", $position / 60, $position % 60);
11863
$duration = sprintf("%d:%02d", $duration / 60, $duration % 60);
11864
$widgets->{'main'}->get_widget('labelMediaPosition')
11865
->set_text($position . "/" . $duration);
11867
$widgets->{'main'}->get_widget('buttonMediaPlay')->hide;
11868
$widgets->{'main'}->get_widget('buttonMediaPause')->show_all;
11870
$widgets->{'main'}->get_widget('buttonMediaPlay')->show_all;
11871
$widgets->{'main'}->get_widget('buttonMediaPause')->hide;
11874
$globals->{'video_skip_signal'} =
11875
$hscale->signal_connect('value-changed', "video_skip");
11882
#****f* lyricue/video_skip
11888
# Tell server to skip to position
11895
debug("Skipping to " . $hscale->get_value());
11896
update_display("media", "skip", $hscale->get_value());
11899
#****f* lyricue/update_current
11903
# update_current($store, $path, $iter)
11913
sub update_current {
11914
my ($store, $path, $iter) = @_;
11915
my $playlistid = $store->get($iter, 2);
11916
if ($playlistid eq $globals->{'current_item'}) {
11917
$store->set($iter, 1, $config->{'HighlightColour'});
11918
$globals->{'current_item_path'} = $path->to_string;
11920
if ($globals->{'current_item_path'} ne "") {
11922
!$path->is_ancestor(
11923
Gtk2::TreePath->new_from_string(
11924
$globals->{'current_item_path'}
11929
$store->set($iter, 1, undef);
11932
$store->set($iter, 1, undef);
11940
#****f* lyricue/clear_search
11946
# Clear search entry
11952
debug("Clear search entry");
11953
$widgets->{'main'}->get_widget('entrySearch')->set_text("");
11954
$widgets->{'main'}->get_widget('entrySearch')->grab_focus();
11959
#****f* lyricue/db_connect
11963
# db_connect($dbname, $dberror)
11973
my ($dbname, $dberror) = @_;
11975
if ($config->{'DatabaseType'} eq "SQLite") {
11977
DBI->connect("dbi:SQLite:" . $globals->{'basedir'} . $dbname . ".db",
11979
|| display_fatal($dberror, $DBI::errstr);
11981
$dbh = DBI->connect(
11983
. $config->{'DatabaseType'}
11984
. ":database=$dbname;host=$globals->{'mysqlhost'}",
11987
{mysql_enable_utf8 => 1}
11988
) || display_fatal($dberror, $DBI::errstr);
11989
$dbh->do('SET NAMES utf8');
11996
#****f* lyricue/prefs_select_mysql
11998
# prefs_select_mysql
12000
# prefs_select_mysql()
12002
# Selecting MySQL DB
12007
sub prefs_select_mysql {
12008
if ($config->{'DatabaseType'} ne "mysql") {
12009
debug("Selecting MySQL DB");
12010
$config->{'DatabaseType'} = "mysql";
12017
#****f* lyricue/prefs_select_sqlite
12019
# prefs_select_sqlite
12021
# prefs_select_sqlite()
12023
# Selecting SQLite DB
12028
sub prefs_select_sqlite {
12029
if ($config->{'DatabaseType'} ne "SQLite") {
12030
debug("Selecting SQLite DB");
12031
$config->{'DatabaseType'} = "SQLite";
12038
#****f* lyricue/db_restart
12044
# Reconnecting to DBs
12050
debug("Reconnecting to DBs");
12051
$lyricDbh->disconnect();
12052
$mediaDbh->disconnect();
12054
if (defined $config->{'DefBible'} && ($config->{'DefBible'} ne "")) {
12055
my @tmpbible = split(/;/, $config->{'DefBible'}, 2);
12056
$globals->{'biblename'} = $tmpbible[1];
12057
@tmpbible = split(/:/, $tmpbible[0], 2);
12058
do_change_bible($tmpbible[1], $tmpbible[0]);
12065
#****f* lyricue/db_select
12078
# Open lyricDB, bibleDB and mediaDb
12079
if ($config->{'DatabaseType'} eq "mysql") {
12080
my $sqldb = DBI->connect(
12082
. $config->{'DatabaseType'}
12084
. $globals->{'mysqlhost'},
12086
) || db_install_user();
12088
$sqldb->disconnect(); ## ERROR HERE ### Can't call 'disconnect' without a package or object reference
12091
db_check_databases();
12092
$lyricDbh = db_connect($globals->{'lyricdb'}, $errorcodes->{'lyricdbopen'});
12093
if ($config->{'DatabaseType'} eq "SQLite") {
12095
# Define a NOW command in sqlite
12096
$lyricDbh->func('NOW', 0, sub { return time }, 'create_function');
12098
$mediaDbh = db_connect($globals->{'mediadb'}, $errorcodes->{'mediadbopen'});
12099
$config->{'Bibles'} = get_bibles();
12104
#****f* lyricue/add_to_playlist_search
12106
# add_to_playlist_search
12108
# add_to_playlist_search($widget)
12110
# Songid \"" . $songid . "\" selected
12116
sub add_to_playlist_search {
12119
$widgets->{'search'}->get_widget('treeSearch')->get_selection;
12120
my ($model, $iter) = $selection->get_selected;
12122
my $songid = $model->get($iter, 4);
12123
debug("Songid \"" . $songid . "\" selected");
12124
add_single_song($songid);
12131
#****f* lyricue/on_hboxBackImage_drag_data_received
12133
# on_hboxBackImage_drag_data_received
12135
# on_hboxBackImage_drag_data_received($widget, $context, $x, $y, $data, $info, $time)
12137
# Dropped on backgrounds
12149
sub on_hboxBackImage_drag_data_received {
12150
debug("Dropped on backgrounds");
12151
my ($widget, $context, $x, $y, $data, $info, $time) = @_;
12152
my $category = $globals->{'category'};
12154
if (($category ne "") && ($data->length >= 0) && ($data->format == 8)) {
12155
debug("Recieved " . $data->data);
12157
my @uris = split(/\n/, $data->data);
12158
my ($filename, $format, $description);
12159
my $owner = getpwuid($<);
12160
my @date = localtime(time);
12161
my $time = sprintf(
12162
"%04d-%02d-%02d %02d:%02d:%02d",
12164
$date[4], $date[3], $date[2], $date[1], $date[0]
12166
for my $uri (@uris) {
12167
$filename = URI->new($uri);
12168
debug("Category: $category, Filename: " . $filename->file);
12170
$format = $filename->file;
12171
$format =~ s/^.*\.//g;
12172
$description = $filename->file;
12173
$description =~ s/^.*\///g;
12174
$description =~ s/\..*?$//g;
12176
open(MEDIA, $filename->file);
12183
debug("Length: " . length($filedata));
12184
my $sth = $mediaDbh->prepare(
12185
q{INSERT INTO media(category, subcategory, type, format, insertedby, insertdate, description, data) VALUES (?,?,?,?,?,?,?,?)}
12188
$sth->execute($category, "", "bg", $format, $owner, $time,
12189
$description, $filedata);
12191
bgdir_change($widget, $category);
12194
$context->finish(1, 0, $time);
12197
debug("global category=$category");
12203
#****f* lyricue/alphanum
12216
# $a and $b are automagically passed to alphanum.
12217
# A copy of them has to be made, or else we will edit the global $a and $b
12224
# (A chunk is either a group of letters or a group of numbers)
12226
my ($a_chunk) = $a_copy =~ /([\D]+|[\d]+)/;
12228
substr($a_copy, length($a_chunk), length($a_copy) - length($a_chunk));
12230
my ($b_chunk) = $b_copy =~ /([\D]+|[\d]+)/;
12232
substr($b_copy, length($b_chunk), length($b_copy) - length($b_chunk));
12234
# Compare the chunks
12236
# Case 1: They both contain letters
12237
if (($a_chunk =~ /\D+/) && ($b_chunk =~ /\D+/)) {
12238
$n = $a_chunk cmp $b_chunk;
12241
# Case 2: They both contain numbers
12243
if (($a_chunk =~ /\d+/) && ($b_chunk =~ /\d+/)) {
12244
$n = $a_chunk <=> $b_chunk;
12247
# Case 3: One has letters, one has numbers; or one is empty
12249
$n = $a_chunk cmp $b_chunk;
12251
# If these are equal, make one (which one is arbitrary) come before
12252
# the other (or else we'll be stuck in this "while $n==0" loop)
12253
if ($n == 0) { $n = 1 }
12262
#****f* lyricue/fromutf
12276
utf8::decode($line) unless utf8::is_utf8($line);
12282
#****f* lyricue/toutf
12296
return Encode::encode("utf8", $line);
12301
#****f* lyricue/pause_media
12313
debug("Play/Pause media");
12314
update_display("media", "pause", "");
12319
#****f* lyricue/media_v4l
12325
# Starting Live Video
12331
debug("Starting Live Video");
12332
update_display("backdrop", "uri;v4l2#SEMI#//");
12337
#****f* lyricue/media_dvd
12343
# Starting DVD Video
12349
debug("Checking DVD");
12350
$widgets->{'dialogDvd'} =
12351
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogDvd', 'lyricue');
12352
$widgets->{'dialogDvd'}->signal_autoconnect_from_package('');
12353
my $vbox = $widgets->{'dialogDvd'}->get_widget('vboxDvd');
12354
my $com = `lsdvd -Op`;
12356
#my $com = `./lsdvd-test.sh -Op`;
12357
$com =~ s/^our //g;
12360
my $tracks = $lsdvd{'track'};
12361
my $longest_track = $lsdvd{'longest_track'};
12362
if (!defined $longest_track) {
12364
fromutf(gettext("No DVD titles found")),
12367
"Unable to open the dvd. There may be no media in the drive"
12374
Gtk2::RadioButton->new(undef, "Longest title (" . $longest_track . ")");
12375
$longest->{user_data} = $longest_track;
12376
$vbox->add($longest);
12378
foreach (@$tracks) {
12380
Gtk2::RadioButton->new($longest,
12381
"Title " . $_->{"ix"} . " - " . sec_to_time($_->{"length"}));
12382
debug("Title " . $_->{"ix"} . " - " . sec_to_time($_->{"length"}));
12383
$radio->{user_data} = $_->{"ix"};
12384
$vbox->add($radio);
12386
if ($_->{"ix"} == $longest_track) {
12387
select_dvdtitle($longest, $_->{"length"});
12389
$radio->signal_connect(toggled => \&select_dvdtitle, $_->{"length"});
12392
$longest->set_active(TRUE);
12393
$widgets->{'dialogDvd'}->get_widget('comboDvdEnd')->set_active(0);
12394
my $confirm = $widgets->{'dialogDvd'}->get_widget('dialogDvd')->run();
12395
if ($confirm == 0) {
12397
my $group = $longest->get_group;
12399
foreach my $r (@$group) {
12400
if ($r->get_active) {
12401
$selected = $r->{user_data};
12404
debug("Adding DVD title:" . $selected);
12406
$widgets->{'dialogDvd'}->get_widget('comboDvdEnd')->get_active;
12407
my $start = time_to_sec(
12408
$widgets->{'dialogDvd'}->get_widget('entryDvdStart')->get_text);
12409
my $end = time_to_sec(
12410
$widgets->{'dialogDvd'}->get_widget('entryDvdEnd')->get_text);
12412
$widgets->{'dialogDvd'}->get_widget('entryDvdEnd')->{user_data};
12414
$end = $start + $end;
12416
if (($start eq 0) && (($end - 1) < $total) && (($end + 1) > $total)) {
12417
do_add_file("dvd://" . $selected,
12418
$widgets->{'main'}->get_widget('labelCurrentPlaylist')
12424
. sec_to_time($start) . "-"
12425
. sec_to_time($end),
12426
$widgets->{'main'}->get_widget('labelCurrentPlaylist')
12432
close_dialog($widgets->{'dialogDvd'}->get_widget('dialogDvd'));
12437
#****f* lyricue/select_dvdtitle
12441
# select_dvdtitle($widget, $length)
12443
# Fill in the start/end times for dvd media
12449
sub select_dvdtitle {
12450
my ($widget, $length) = @_;
12451
if ($widget->get_active) {
12452
$widgets->{'dialogDvd'}->get_widget('comboDvdEnd')->set_active(0);
12453
$widgets->{'dialogDvd'}->get_widget('entryDvdStart')
12454
->set_text(sec_to_time(0));
12455
$widgets->{'dialogDvd'}->get_widget('entryDvdEnd')
12456
->set_text(sec_to_time($length));
12457
$widgets->{'dialogDvd'}->get_widget('entryDvdEnd')->{user_data} =
12464
#****f* lyricue/sec_to_time
12468
# sec_to_time($seconds)
12470
# Convert seconds to pretty 0:00:00 format
12477
my ($seconds) = @_;
12478
if (!defined $seconds) {
12481
my @parts = gmtime($seconds);
12482
if ($parts[2] == 0) {
12483
return sprintf("%d:%02d", @parts[1, 0]);
12485
return sprintf("%d:%02d:%02d", @parts[2, 1, 0]);
12491
#****f* lyricue/time_to_sec
12495
# time_to_sec($time)
12497
# Convert pretty 0:00:00 format to seconds
12505
if (!defined $time) {
12508
my @parts = split(/:/, $time);
12509
if (defined $parts[2]) {
12510
return ($parts[0] * 3600) + ($parts[1] * 60) + $parts[2];
12511
} elsif (defined $parts[1]) {
12512
return ($parts[0] * 60) + $parts[1];
12520
#****f* lyricue/install_bibles
12526
# Loading bible install window
12531
sub install_bibles {
12532
debug("Loading bible install window");
12533
$widgets->{'bible'} = Gtk2::GladeXML->new($globals->{'gladefile'},
12534
'windowBibleManager', 'lyricue');
12535
$widgets->{'bible'}->signal_autoconnect_from_package('');
12536
$widgets->{'bible'}->get_widget('buttonBibleSword')->{'user_data'} =
12537
"http://crosswire.org/sword/modules/ModDisp.jsp?modType=Bibles";
12538
$widgets->{'bible'}->get_widget('buttonBibleDB')->{'user_data'} =
12539
"http://www.lyricue.org/bibles";
12540
$widgets->{'bible'}->get_widget('windowBibleManager')->show_all();
12545
#****f* lyricue/do_install_bible
12549
# do_install_bible()
12556
sub do_install_bible {
12558
$widgets->{'bible'}->get_widget('fileBibleInstall')->get_filename();
12559
close_dialog($widgets->{'bible'}->get_widget('windowBibleManager'));
12560
if (!defined $dbfilename) {
12561
debug("No file selected");
12564
debug("Installing bible from " . $dbfilename);
12568
my $tmpdir = tempdir("lyricue-XXXX", TMPDIR => 1, CLEANUP => 1);
12569
if ($dbfilename =~ /sql.gz$/i) {
12571
# Compressed bibleDb
12573
"gzip -dc \"" . $dbfilename . "\" > " . $tmpdir . "/bibleDb.sql";
12576
$dbfilename = $tmpdir . "/bibleDb.sql";
12578
if ($dbfilename =~ /sql$/i) {
12580
# Uncompressed bibleDb
12581
open(DB, $dbfilename);
12582
debug("bibleDb: " . $dbfilename);
12583
my $dbname = "bibleDb";
12585
if (/^CREATE DATABASE.*;$/) {
12587
$dbname =~ s/^CREATE DATABASE (.*);$/$1/g;
12592
if ($dbname ne "") {
12593
db_installdb($dbfilename, $dbname);
12594
$message = gettext("Bible installed from ") . $dbfilename;
12596
$message = gettext("Unable to load from ") . $dbfilename;
12598
} elsif ($dbfilename =~ /zip$/i) {
12601
my $command = "unzip \"" . $dbfilename . "\" -d \$HOME/.sword/";
12604
$message = "Sword bible extracted to ~/.sword";
12608
Gtk2::GladeXML->new($globals->{'gladefile'}, 'dialogError', 'lyricue');
12609
$donexml->signal_autoconnect_from_package('');
12610
$donexml->get_widget('labelError')->set_text($message);
12611
$donexml->get_widget('expanderDetails')->hide();
12612
my $confirm = $donexml->get_widget('dialogError')->run();
12613
close_dialog($donexml->get_widget('dialogError'));
12620
#****f* lyricue/load_link
12624
# load_link($widget)
12634
debug("Load URL:" . $widget->{'user_data'});
12635
my $command = "xdg-open " . $widget->{'user_data'};
12641
#****f* lyricue/load_biblemenu
12647
# Populate biblemenu
12652
sub load_biblemenu {
12653
debug("Populate biblemenu");
12654
my $menutop = Gtk2::Menu->new();
12658
Gtk2::MenuItem->new_with_label(gettext("Install new bibles"));
12659
$bibleMenuAdd->signal_connect("activate", "install_bibles");
12660
$bibleMenuAdd->show();
12661
$menutop->append($bibleMenuAdd);
12663
db_check_databases();
12664
$config->{'Bibles'} = get_bibles();
12665
my $bibles = $config->{'Bibles'};
12666
my ($defbible, undef) = split(/\:/, $config->{'DefBible'}, 2);
12667
my @swordBibles = ();
12669
foreach (sort keys %$bibles) {
12671
push @dbBibles, $_;
12673
push @swordBibles, $_;
12677
foreach (@dbBibles, "", @swordBibles) {
12679
my $sep = Gtk2::SeparatorMenuItem->new;
12681
$menutop->append($sep);
12683
my @bible = split(/;/, $config->{'Bibles'}->{$_}, 2);
12685
Gtk2::RadioMenuItem->new_with_label($group, $bible[1]);
12686
if ($group == -1) {
12687
$group = $bibleMenu->{$_}->get_group;
12690
->signal_connect("toggled", "select_bible_db", $bible[0] . ";" . $_);
12691
if (defined($defbible) && ($_ eq $defbible)) {
12692
$bibleMenu->{$_}->set_active(TRUE);
12694
$bibleMenu->{$_}->show;
12695
$menutop->append($bibleMenu->{$_});
12698
$widgets->{'main'}->get_widget('bible1')->set_submenu($menutop);
12703
#****f* lyricue/open_dirchooser
12707
# open_dirchooser($widget)
12709
# Opening Directory chooser
12715
sub open_dirchooser {
12717
debug("Opening Directory chooser");
12718
my $directoryxml = Gtk2::GladeXML->new($globals->{'gladefile'},
12719
'dialogDirChooser', 'lyricue');
12720
$directoryxml->signal_autoconnect_from_package('');
12721
my $dir = $widget->get_label();
12722
$dir =~ s/^~/$ENV{'HOME'}/;
12723
$directoryxml->get_widget('dialogDirChooser')->set_filename($dir);
12724
my $confirm = $directoryxml->get_widget('dialogDirChooser')->run();
12726
if ($confirm eq "ok") {
12727
$dir = $directoryxml->get_widget('dialogDirChooser')->get_filename();
12728
$dir =~ s/^$ENV{'HOME'}/~/;
12729
if ($widget->{'user_data'} eq "img") {
12730
$widgets->{'prefs'}->get_widget('filePrefSpecialImagedir')
12732
} elsif ($widget->{'user_data'} eq "bg") {
12733
$widgets->{'prefs'}->get_widget('filePrefSpecialBGdir')
12735
} elsif ($widget->{'user_data'} eq "fr_img") {
12736
$widgets->{'firstrunxml'}->get_widget('fileFRImagedir')
12738
} elsif ($widget->{'user_data'} eq "fr_bg") {
12739
$widgets->{'firstrunxml'}->get_widget('fileFRBGdir')
12743
close_dialog($directoryxml->get_widget('dialogDirChooser'));
12748
#****f* lyricue/import_db
12754
# Import DB selected
12760
debug("Import DB selected");
12761
my $importxml = Gtk2::GladeXML->new($globals->{'gladefile'},
12762
'dialogImportData', 'lyricue');
12763
$importxml->signal_autoconnect_from_package('');
12764
my $filter = Gtk2::FileFilter->new();
12765
$filter->add_pattern("*.xmlz");
12766
$filter->add_pattern("*.xml");
12767
$importxml->get_widget('fileImportData')->set_filter($filter);
12768
my $confirm = $importxml->get_widget('dialogImportData')->run();
12769
debug(":" . $confirm);
12771
if ($confirm == 0) {
12772
my $filename = $importxml->get_widget('fileImportData')->get_filename();
12773
if (defined $filename) {
12774
close_dialog($importxml->get_widget('dialogImportData'));
12775
import_songs($filename);
12779
close_dialog($importxml->get_widget('dialogImportData'));
12784
#****f* lyricue/export_db
12790
# Export DB selected
12796
debug("Export DB selected");
12797
my $exportxml = Gtk2::GladeXML->new($globals->{'gladefile'},
12798
'dialogFileChooser', 'lyricue');
12799
$exportxml->signal_autoconnect_from_package('');
12800
my $filter = Gtk2::FileFilter->new;
12801
$filter->add_pattern("*.xmlz");
12802
$exportxml->get_widget('dialogFileChooser')->set_filter($filter);
12803
$exportxml->get_widget('dialogFileChooser')->set_filename("lyricue.xmlz");
12804
my $confirm = $exportxml->get_widget('dialogFileChooser')->run();
12808
$exportxml->get_widget('dialogFileChooser')->get_filename;
12810
$filename =~ s/\..*?$//g;
12811
$filename .= ".xmlz";
12812
if (defined $filename) {
12813
export_songs($filename);
12815
close_dialog($exportxml->get_widget('dialogFileChooser'));
12821
#****f* lyricue/biblebrowser_init
12823
# biblebrowser_init
12825
# biblebrowser_init()
12832
sub biblebrowser_init {
12833
my @items = ('Old Testament', 'New Testament');
12834
biblebrowser_loaditems("book", \@items, 2);
12839
#****f* lyricue/biblebrowser_book
12841
# biblebrowser_book
12843
# biblebrowser_book()
12850
sub biblebrowser_book {
12851
my ($widget, $section) = @_;
12852
debug("Looking up " . $section);
12854
if ($section eq "Old Testament") {
12856
'Genesis', 'Exodus', 'Leviticus', 'Numbers',
12857
'Deuteronomy', 'Joshua', 'Judges', 'Ruth',
12858
'1 Samuel', '2 Samuel', '1 Kings', '2 Kings',
12859
'1 Chronicles', '2 Chronicles', 'Ezra', 'Nehemiah',
12860
'Esther', 'Job', 'Psalms', 'Proverbs',
12861
'Ecclesiastes', 'Song of Songs', 'Isaiah', 'Jeremiah',
12862
'Lamentations', 'Ezekiel', 'Daniel', 'Hosea',
12863
'Joel', 'Amos', 'Obadiah', 'Jonah',
12864
'Micah', 'Nahum', 'Habakkuk', 'Zephaniah',
12865
'Haggai', 'Zechariah', 'Malachi'
12872
'1 Corinthians', '2 Corinthians',
12873
'Galatians', 'Ephesians',
12874
'Philippians', 'Colossians',
12875
'1 Thessalonians', '2 Thessalonians',
12876
'1 Timothy', '2 Timothy',
12877
'Titus', 'Philemon',
12878
'Hebrews', 'James',
12879
'1 Peter', '2 Peter',
12880
'1 John', '2 John',
12885
biblebrowser_loaditems("chapter", \@items, 3);
12890
#****f* lyricue/biblebrowser_chapter
12892
# biblebrowser_chapter
12894
# biblebrowser_chapter($widget, $book, $source)
12904
sub biblebrowser_chapter {
12905
my ($widget, $book, $source) = @_;
12906
debug("Looking up book " . $book);
12907
my $translated_book = gettext($book);
12910
if ($globals->{'usesword'}) {
12912
# Find proper book name
12913
my $command = sprintf(
12914
"%s -b %s -e UTF8 -k '%s' 1:1 '%s' 1:1",
12915
$globals->{'diatheke'},
12916
$globals->{'bibledb'}, $book, $translated_book
12919
$maxchap = fromutf(`$command`);
12920
($book, undef) = split(/\s\d/, $maxchap, 2);
12922
$command = sprintf(
12923
"%s -b %s -e UTF8 -k '%s' | grep '^%s'| tail -2 | head -1",
12924
$globals->{'diatheke'},
12925
$globals->{'bibledb'}, $book, $book
12928
$maxchap = fromutf(`$command`);
12929
$maxchap =~ s/^$book ([0-9]*):[0-9].*$/$1/g;
12934
my ($table, $dbname) = split(/@/, $globals->{'bibledb'}, 2);
12936
"SELECT MAX(chapternum) FROM "
12938
. " WHERE book like \""
12940
. "%\" or book like \""
12941
. toutf($translated_book) . "%\"";
12943
$sth = $bibleDbh->prepare($query)
12944
|| display_fatal($errorcodes->{'sqlprepare'},
12945
$! . "\nSQL: " . $query);
12946
$rv = $sth->execute
12947
|| display_fatal($errorcodes->{'sqlexecute'},
12948
$! . "\nSQL: " . $query);
12949
if (my @row = $sth->fetchrow_array) {
12951
$maxchap = $row[0];
12958
foreach (1 .. $maxchap) {
12961
biblebrowser_loaditems("verse", \@items, 8);
12962
if ($source ne "entry") {
12963
$widgets->{'main'}->get_widget('entryNavVerse')
12964
->set_text($book . " ");
12965
$widgets->{'main'}->get_widget('entryNavVerse')->set_position(-1);
12972
#****f* lyricue/biblebrowser_verse
12974
# biblebrowser_verse
12976
# biblebrowser_verse($widget, $chapter, $source)
12978
# biblebrowser_verse called from ".$source.":
12986
sub biblebrowser_verse {
12987
my ($widget, $chapter, $source) = @_;
12988
debug("biblebrowser_verse called from " . $source . ":" . $chapter);
12989
my $book = $widgets->{'main'}->get_widget('entryNavVerse')->get_text();
12991
if ($chapter == 0) {
12993
$chapter =~ s/^.*( [0-9:\-]*)/$1/;
12995
($chapter, $verse) = split(/:/, $chapter);
12996
$book =~ s/ [0-9:\-]*$//;
12997
if ((!defined $verse) || ((defined $verse) && ($verse eq ""))) {
12998
$globals->{'verseStart'} = 0;
12999
$globals->{'verseEnd'} = 0;
13002
if ($source ne "entry") {
13003
$widgets->{'main'}->get_widget('entryNavVerse')
13004
->set_text($book . " " . $chapter);
13005
$widgets->{'main'}->get_widget('entryNavVerse')->set_position(-1);
13007
debug("Looking up book " . $book . " chapter " . $chapter);
13009
if ($globals->{'usesword'}) {
13010
my $command = sprintf(
13011
"%s -b %s -e UTF8 -k '%s' %d | grep '^%s' | tail -1",
13012
$globals->{'diatheke'},
13013
$globals->{'bibledb'}, $book, $chapter, $book
13016
$maxverse = fromutf(`$command`);
13017
$maxverse =~ s/^$book [0-9]*:([0-9]*):.*$/$1/g;
13019
my ($table, $dbname) = split(/@/, $globals->{'bibledb'}, 2);
13021
"SELECT MAX(versenum) FROM "
13025
. "\" AND chapternum=\""
13028
$sth = $bibleDbh->prepare($query)
13029
|| display_fatal($errorcodes->{'sqlprepare'},
13030
$! . "\nSQL: " . $query);
13031
$rv = $sth->execute
13032
|| display_fatal($errorcodes->{'sqlexecute'},
13033
$! . "\nSQL: " . $query);
13035
if (my @row = $sth->fetchrow_array) {
13036
$maxverse = $row[0];
13042
foreach (1 .. $maxverse) {
13045
biblebrowser_loaditems("verses", \@items, 8);
13046
if ($source ne "entry") {
13047
$widgets->{'main'}->get_widget('entryNavVerse')
13048
->set_text($book . " " . $chapter);
13049
$widgets->{'main'}->get_widget('entryNavVerse')->set_position(-1);
13056
#****f* lyricue/biblebrowser_loaditems
13058
# biblebrowser_loaditems
13060
# biblebrowser_loaditems($section, $items, $cols)
13062
# Filling bible section
13070
sub biblebrowser_loaditems {
13071
my ($section, $items, $cols) = @_;
13072
debug("Filling bible section");
13073
my $buttons = $widgets->{'bibleBrowser'};
13074
foreach (keys %$buttons) {
13075
$widgets->{'bibleBrowser'}{$_}->destroy();
13076
delete $widgets->{'bibleBrowser'}{$_};
13079
my $size = @$items;
13080
my $buffer = Gtk2::TextBuffer->new();
13081
$widgets->{'main'}->get_widget('textBible')->set_buffer($buffer);
13082
my $sizegroup = Gtk2::SizeGroup->new('both');
13083
foreach my $itemnum (0 .. ($size - 1)) {
13084
if ($section eq "verses") {
13085
$widgets->{'bibleBrowser'}{'button' . $itemnum} =
13086
Gtk2::ToggleButton->new(@$items[$itemnum]);
13087
$widgets->{'bibleBrowser'}{'button' . $itemnum}
13088
->signal_connect("event", "changeVerseStatus", $size);
13089
$widgets->{'bibleBrowser'}{'button' . $itemnum}->show();
13091
$widgets->{'bibleBrowser'}{'button' . $itemnum} =
13092
Gtk2::Button->new(fromutf(gettext(@$items[$itemnum])));
13093
$widgets->{'bibleBrowser'}{'button' . $itemnum}
13094
->signal_connect("clicked", "biblebrowser_" . $section,
13095
@$items[$itemnum]);
13097
$sizegroup->add_widget($widgets->{'bibleBrowser'}{'button' . $itemnum});
13098
$widgets->{'bibleBrowser'}{'button' . $itemnum}->show;
13099
my $anchor = $buffer->create_child_anchor($buffer->get_end_iter);
13100
$widgets->{'main'}->get_widget('textBible')
13101
->add_child_at_anchor($widgets->{'bibleBrowser'}{'button' . $itemnum},
13104
$widgets->{'main'}->get_widget('textBible')->show_all();
13109
#****f* lyricue/firstrun_wizard
13113
# firstrun_wizard()
13120
sub firstrun_wizard {
13121
debug("First Run Wizard");
13122
$config = load_config();
13123
$widgets->{'firstrunxml'} = Gtk2::GladeXML->new($globals->{'gladefile'},
13124
'assistantFirstRun', 'lyricue');
13125
$widgets->{'firstrunxml'}->signal_autoconnect_from_package('');
13126
$widgets->{'firstrun'} =
13127
$widgets->{'firstrunxml'}->get_widget('assistantFirstRun');
13128
$widgets->{'firstrun'}->show_all();
13133
#****f* lyricue/firstrun_cancel
13137
# firstrun_cancel()
13144
sub firstrun_cancel {
13145
debug("Cancelled Wizard");
13151
#****f* lyricue/firstrun_close
13162
sub firstrun_close {
13163
debug("Closing Wizard");
13164
close_dialog($widgets->{'firstrun'});
13165
if ($globals->{'firstrun'}) {
13172
#****f* lyricue/firstrun_prepare
13176
# firstrun_prepare()
13183
sub firstrun_prepare {
13184
debug("Firstrun prepare page:" . $widgets->{'firstrun'}->get_current_page);
13186
$widgets->{'firstrun'}
13187
->get_nth_page($widgets->{'firstrun'}->get_current_page);
13188
my $font = "Serif 30";
13189
my $header = gettext("First-run wizard");
13191
if ($widgets->{'firstrun'}->get_current_page == 0) {
13194
$header = gettext("Welcome");
13195
$widgets->{'firstrun'}->set_page_complete($page, TRUE);
13196
} elsif ($widgets->{'firstrun'}->get_current_page == 1) {
13197
$header = gettext("Location");
13198
$widgets->{'firstrunxml'}->get_widget('entryFRHostDB')
13199
->set_text($globals->{'mysqlhost'});
13200
$widgets->{'firstrunxml'}->get_widget('entryFRHostServer')
13201
->set_text($globals->{'host'});
13202
$widgets->{'firstrun'}->set_page_complete($page, TRUE);
13203
} elsif ($widgets->{'firstrun'}->get_current_page == 2) {
13204
$globals->{'mysqlhost'} =
13205
$widgets->{'firstrunxml'}->get_widget('entryFRHostDB')->get_text();
13208
$header = gettext("Database login");
13209
firstrun_pw_check();
13210
} elsif ($widgets->{'firstrun'}->get_current_page == 3) {
13213
$header = gettext("Projector settings");
13214
$widgets->{'firstrunxml'}->get_widget('spinFRWidth')
13215
->set_value($config->{'Width'});
13216
$widgets->{'firstrunxml'}->get_widget('spinFRHeight')
13217
->set_value($config->{'Height'});
13218
if ($config->{'VerticalLocation'}) {
13219
$widgets->{'firstrunxml'}->get_widget('comboFRVertical')
13220
->prepend_text($config->{'VerticalLocation'});
13222
$widgets->{'firstrunxml'}->get_widget('comboFRVertical')->set_active(0);
13223
if ($config->{'HorizontalLocation'}) {
13224
$widgets->{'firstrunxml'}->get_widget('comboFRHorizontal')
13225
->prepend_text($config->{'HorizontalLocation'});
13227
$widgets->{'firstrunxml'}->get_widget('comboFRHorizontal')
13229
if ($config->{'Justification'}) {
13230
$widgets->{'firstrunxml'}->get_widget('comboFRJustification')
13231
->prepend_text($config->{'Justification'});
13233
$widgets->{'firstrunxml'}->get_widget('comboFRJustification')
13235
$widgets->{'firstrun'}->set_page_complete($page, TRUE);
13236
} elsif ($widgets->{'firstrun'}->get_current_page == 4) {
13239
$header = gettext("Fonts");
13240
$widgets->{'firstrun'}->set_page_complete($page, TRUE);
13241
$widgets->{'firstrunxml'}->get_widget('fontFRMain')
13242
->set_font_name($config->{'Main'});
13243
$widgets->{'firstrunxml'}->get_widget('fontFRHeader')
13244
->set_font_name($config->{'Header'});
13245
$widgets->{'firstrunxml'}->get_widget('fontFRFooter')
13246
->set_font_name($config->{'Footer'});
13247
$widgets->{'firstrunxml'}->get_widget('fontFROSD')
13248
->set_font_name($config->{'OSD'});
13249
} elsif ($widgets->{'firstrun'}->get_current_page == 5) {
13252
$header = gettext("Image Directories");
13253
$widgets->{'firstrunxml'}->get_widget('fileFRBGdir')
13254
->set_label($config->{'BGDirectory'});
13255
$widgets->{'firstrunxml'}->get_widget('fileFRBGdir')->{'user_data'} =
13257
$widgets->{'firstrunxml'}->get_widget('fileFRImagedir')
13258
->set_label($config->{'ImageDirectory'});
13259
$widgets->{'firstrunxml'}->get_widget('fileFRImagedir')->{'user_data'} =
13261
$widgets->{'firstrun'}->set_page_complete($page, TRUE);
13262
} elsif ($widgets->{'firstrun'}->get_current_page == 6) {
13265
$header = gettext("Most-used items");
13266
$widgets->{'firstrunxml'}->get_widget('entryFRSong')
13267
->set_text($config->{'SpecialSong'});
13268
$widgets->{'firstrunxml'}->get_widget('entryFRImage')
13269
->set_text($config->{'SpecialImage'});
13270
$widgets->{'firstrunxml'}->get_widget('entryFRBack')
13271
->set_text($config->{'SpecialBack'});
13272
my $bibles = $config->{'Bibles'};
13273
my $store = Gtk2::ListStore->new('Glib::String', 'Glib::String');
13274
$widgets->{'firstrunxml'}->get_widget('comboFRBible')->remove_text(0);
13275
my ($iter, $activeiter);
13277
foreach (sort keys %$bibles) {
13278
my ($type, $bible) = split(/;/, $config->{'Bibles'}->{$_});
13279
$iter = $store->append;
13280
$store->set($iter, 0, $bible, 1,
13281
$_ . ":" . $config->{'Bibles'}->{$_});
13282
if ($config->{'DefBible'} eq $_ . ":" . $config->{'Bibles'}->{$_}) {
13283
$activeiter = $iter;
13286
$widgets->{'firstrunxml'}->get_widget('comboFRBible')
13287
->set_model($store);
13288
if (defined $activeiter) {
13289
$widgets->{'firstrunxml'}->get_widget('comboFRBible')
13290
->set_active_iter($activeiter);
13292
$widgets->{'firstrun'}->set_page_complete($page, TRUE);
13293
} elsif ($widgets->{'firstrun'}->get_current_page == 7) {
13296
$header = gettext("Confirm");
13297
$widgets->{'firstrun'}->set_page_complete($page, TRUE);
13300
$header = fromutf($header);
13301
my $layout = $page->create_pango_layout($header);
13302
my $desc = Gtk2::Pango::FontDescription->from_string($font);
13303
$layout->set_font_description($desc);
13304
my ($text_width, $text_height) = $layout->get_pixel_size;
13305
my $pixmap = Gtk2::Gdk::Pixmap->new(undef, $text_width, $text_height, 24);
13306
$pixmap->draw_rectangle($page->get_style->white_gc,
13307
TRUE, 0, 0, $text_width, $text_height);
13308
$pixmap->draw_layout($page->get_style->text_gc($page->state), 0, 0,
13311
Gtk2::Gdk::Pixbuf->get_from_drawable($pixmap, undef, 0, 0, 0, 0,
13312
$text_width, $text_height);
13313
$widgets->{'firstrun'}->set_page_header_image($page, $pixbuf);
13318
#****f* lyricue/firstrun_pw_changed
13320
# firstrun_pw_changed
13322
# firstrun_pw_changed()
13324
# Firstrun login changed
13329
sub firstrun_pw_changed {
13330
debug("Firstrun login changed");
13331
reset_timer($globals->{'nav_update_timer'});
13332
$globals->{'fr_update_timer'} =
13333
Glib::Timeout->add(500, \&firstrun_pw_check);
13338
#****f* lyricue/firstrun_pw_check
13340
# firstrun_pw_check
13342
# firstrun_pw_check()
13349
sub firstrun_pw_check {
13350
debug("Checking login");
13351
reset_timer($globals->{'fr_update_timer'});
13352
$globals->{'db_adminuser'} =
13353
$widgets->{'firstrunxml'}->get_widget('entryFRUsername')->get_text();
13354
$globals->{'db_adminpassword'} =
13355
$widgets->{'firstrunxml'}->get_widget('entryFRPassword')->get_text();
13357
$widgets->{'firstrun'}
13358
->get_nth_page($widgets->{'firstrun'}->get_current_page);
13361
$dbh = DBI->connect(
13363
. $config->{'DatabaseType'}
13365
. $globals->{'mysqlhost'},
13366
$globals->{'db_adminuser'}, $globals->{'db_adminpassword'}
13371
debug("Login accepted");
13372
$widgets->{'firstrun'}->set_page_complete($page, TRUE);
13373
$widgets->{'firstrunxml'}->get_widget('labelFRDBCheck')
13374
->set_markup(gettext("<i>Username/Password accepted</i>"));
13376
debug("Login failed");
13377
$widgets->{'firstrun'}->set_page_complete($page, FALSE);
13378
$widgets->{'firstrunxml'}->get_widget('labelFRDBCheck')
13379
->set_markup(gettext("<i>Username/Password failed</i>"));
13385
#****f* lyricue/firstrun_apply
13396
sub firstrun_apply {
13397
debug("Apply Wizard");
13399
# Confirmed changes - so save them
13401
$config->{'Main'} =
13402
$widgets->{'firstrunxml'}->get_widget('fontFRMain')->get_font_name();
13403
$config->{'Header'} =
13404
$widgets->{'firstrunxml'}->get_widget('fontFRHeader')->get_font_name();
13405
$config->{'Footer'} =
13406
$widgets->{'firstrunxml'}->get_widget('fontFRFooter')->get_font_name();
13408
$widgets->{'firstrunxml'}->get_widget('fontFROSD')->get_font_name();
13409
$config->{'Height'} =
13410
$widgets->{'firstrunxml'}->get_widget('spinFRHeight')->get_value();
13411
$config->{'Width'} =
13412
$widgets->{'firstrunxml'}->get_widget('spinFRWidth')->get_value();
13415
foreach my $value ("Top", "Bottom", "Centre") {
13418
fromutf(gettext($value)) eq ucfirst(
13419
$widgets->{'firstrunxml'}->get_widget('comboFRVertical')
13420
->get_active_text()
13429
$widgets->{'firstrunxml'}->get_widget('comboFRVertical')
13430
->get_active_text();
13432
$config->{'VerticalLocation'} = $set;
13435
foreach my $value ("Left", "Right", "Centre") {
13437
fromutf(gettext($value)) eq ucfirst(
13438
$widgets->{'firstrunxml'}->get_widget('comboFRHorizontal')
13439
->get_active_text()
13446
fromutf(gettext($value)) eq ucfirst(
13447
$widgets->{'firstrunxml'}->get_widget('comboFRJustification')
13448
->get_active_text()
13457
$widgets->{'firstrunxml'}->get_widget('comboFRHorizontal')
13458
->get_active_text();
13462
$widgets->{'firstrunxml'}->get_widget('comboFRJustification')
13463
->get_active_text();
13465
$config->{'HorizontalLocation'} = $set;
13466
$config->{'Justification'} = $set2;
13468
#$config->{'BGImage'} = $widgets->{'prefs'}->get_widget('imagePrefBG')->{user_data};
13469
$config->{'SpecialSong'} =
13470
$widgets->{'firstrunxml'}->get_widget('entryFRSong')->get_text();
13471
$config->{'SpecialImage'} =
13472
$widgets->{'firstrunxml'}->get_widget('entryFRImage')->get_text();
13473
$config->{'SpecialBack'} =
13474
$widgets->{'firstrunxml'}->get_widget('entryFRBack')->get_text();
13476
$widgets->{'firstrunxml'}->get_widget('comboFRBible')->get_active_iter;
13478
$config->{'DefBible'} =
13479
$widgets->{'firstrunxml'}->get_widget('comboFRBible')
13480
->get_model->get($iter, 1);
13482
$config->{'ImageDirectory'} =
13483
$widgets->{'firstrunxml'}->get_widget('fileFRImagedir')->get_label();
13484
$config->{'BGDirectory'} =
13485
$widgets->{'firstrunxml'}->get_widget('fileFRBGdir')->get_label();
13486
$config->{'DBHost'} =
13487
$widgets->{'firstrunxml'}->get_widget('entryFRHostDB')->get_text();
13488
$config->{'ProjectorHost'} =
13489
$widgets->{'firstrunxml'}->get_widget('entryFRHostServer')->get_text();
13490
$globals->{'host'} = $config->{'ProjectorHost'};
13491
$globals->{'mysqlhost'} = $config->{'DBHost'};
13494
write_config(FALSE);
13496
if (!$globals->{'firstrun'}) {
13500
preview_display("reconfig", "", "", "MINI");
13501
update_display("reconfig", "", "");
13502
preview_display("display", "current", "", "MINI");
13503
update_display("display", "current", "");
13509
#****f* lyricue/firstrun_bible
13519
sub firstrun_bible {
13524
#****f* lyricue/online-help
13530
# Load documentation in browser
13534
debug("Load Documentation");
13535
my $command = "xdg-open ghelp:lyricue";
13541
#****f* lyricue/start_transaction
13543
# start_transaction
13545
# start_transaction()
13547
# Mark the start of a bunch of queries to be run in a single transaction
13550
sub start_transaction {
13551
my $globals->{'old_re'} = $lyricDbh->{RaiseError};
13552
$lyricDbh->{RaiseError} = 1;
13553
$lyricDbh->{AutoCommit} = 0;
13558
#****f* lyricue/end_transaction
13562
# end_transaction()
13564
# Mark the end of a bunch of queries to be run in a single transaction
13567
sub end_transaction {
13568
$lyricDbh->rollback() if $@;
13569
$lyricDbh->{AutoCommit} = 1;
13570
$lyricDbh->{RaiseError} = $globals->{'old_re'};
13575
#****f* lyricue/clean_database
13581
# Rescan the image/backgrounds directories
13582
# Cleans up old associations
13583
# Cleans up left-over playlist items
13586
sub clean_database {
13587
debug("Cleaning database");
13588
my $query = "SELECT description,category FROM media WHERE format=\"file\"";
13590
my $sth = $mediaDbh->prepare($query)
13591
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
13592
my $rv = $sth->execute
13593
|| display_fatal($errorcodes->{'sqlexecute'}, $! . "\nSQL: " . $query);
13594
while ($row = $sth->fetchrow_hashref()) {
13595
my @mystat = stat($row->{'category'});
13598
# file no longer exists so remove it from db
13599
my $query2 = "DELETE FROM media WHERE format=\"file\" AND category="
13600
. quote($row->{'category'});
13602
my $sth2 = $mediaDbh->prepare($query2)
13603
|| display_fatal($errorcodes->{'sqlprepare'},
13604
$! . "\nSQL: " . $query2);
13605
my $rv2 = $sth2->execute
13606
|| display_fatal($errorcodes->{'sqlexecute'},
13607
$! . "\nSQL: " . $query2);
13611
# Remove leftover playlist item from failed re-orders
13612
$query = "DELETE FROM playlist WHERE playorder=-1";
13614
$sth = $lyricDbh->prepare($query)
13615
|| display_fatal($errorcodes->{'sqlprepare'}, $! . "\nSQL: " . $query);
13616
$rv = $sth->execute; # Don't worry if it fails
13621
sub start_editview {
13622
if (defined ($widgets->{'EditPreview'})) {
13625
$widgets->{'EditPreview'} = Gtk2::Socket->new;
13626
$widgets->{'EditPreview'}->show;
13627
$widgets->{'EditPreview'}->set_size_request(-1, -1);
13628
$widgets->{'add'}->get_widget('frameEditPreview')->show;
13629
$widgets->{'add'}->get_widget('frameEditPreview')->add($widgets->{'EditPreview'});
13630
my $command = sprintf( "%s -r %s -m %d -p %d",
13631
$globals->{'lyricue_server'} , $globals->{'mysqlhost'}, $widgets->{'EditPreview'}->get_id, $globals->{'editview_port'});
13633
$globals->{'editview_pid'} = fork;
13634
if ($globals->{'editview_pid'} < 0) {
13636
"Unable to start the lyricue server as a preview window",
13637
$! . "\nSQL: " . $query);
13639
if ($globals->{'editview_pid'} == 0) {
13642
$widgets->{'EditPreview'}->signal_connect(
13643
'plug-removed' => sub {
13644
debug("Lyricue edit preview died..restarting\n");
13645
$widgets->{'main'}->get_widget('frameEditPreview')
13646
->remove($widgets->{'preview'});
13653
sub stop_editview {
13654
if (defined ($globals->{'editview_pid'})) {
13655
kill 9, $globals->{'editview_pid'};
13657
if (defined ($widgets->{'EditPreview'})) {
13658
$widgets->{'EditPreview'}->destroy;
13659
undef $widgets->{'EditPreview'};
13664
debug("Toggle Blur");
13666
if ($widget->get_active()) {
13667
update_display("blur",1);
13669
update_display("blur",0);
13674
debug("Changing fade amount");
13676
update_display("fade",$widget->get_value());
13679
sub start_display {
13680
debug("Start lyricue display");
13681
execute_app("",$globals->{'lyricue_server'});