#!/usr/bin/perl # SR Feb18 # c.f. http://gtk2-perl.sourceforge.net/doc/gtk2-perl-tut/sec-RangeWidgetsExample.html use Glib qw/TRUE FALSE/; use Gtk2 '-init'; use Gtk2::Helper; use LWP::Simple; use IO::Socket; # Incoming socket for audio reactive data $| = 1; # Send data immediately without buffering $socket = IO::Socket::INET->new( LocalPort => 7778, Proto => 'udp') or die "ERROR creating incoming socket : $!\n"; # default addresses in the boxes $address1="192.168.2.45"; $name1="2m WS2801"; $address2="192.168.2.49"; $name2=")'( fence 2*75"; $address3="192.167.2.64"; $name3="101 LEDs 12V"; # Starting values for the sliders $red=30; $green=20; $blue=10; # call when sliders moved or regularly for auto update sub set { ($r,$g,$b)=@_; $data=chr($r).chr($g).chr($b); if ($active1) { $sock1->send($data x101) or print "Send error: $!\n"; } if ($active2) { $sock2->send($data x101) or print "Send error: $!\n"; } if ($active3) { $sock3->send($data x101) or print "Send error: $!\n"; } } # UI $window = Gtk2::Window->new('toplevel'); $window->set_title("LED Control!"); $window->set_border_width(10); $vbox = Gtk2::VBox->new(FALSE, 0); $window->add($vbox); $label = Gtk2::Label->new("Connect to IPs: "); $vbox->pack_start($label, TRUE, TRUE, 0); $label->show; # Address boxes $box1 = Gtk2::HBox->new(FALSE, 0); $vbox->pack_start($box1, TRUE, TRUE, 0); $button1 = Gtk2::CheckButton->new("static"); $button1->signal_connect(toggled => sub{ $active1= $button1->get_active(); activate($sock1,$address1,$active1||$mactive1); }); $box1->pack_start($button1, TRUE, TRUE, 0); $music1 = Gtk2::CheckButton->new("music "); $music1->signal_connect(toggled => sub{ $mactive1= $music1->get_active(); activate($sock1,$address1,$active1||$mactive1); }); $box1->pack_start($music1, TRUE, TRUE, 0); $IP1 = Gtk2::Entry->new(); $IP1->set_text($address1); $IP1->signal_connect (changed => sub { $address1 = $IP1->get_text; activate($sock1,$address1,$active1||$mactive1) }); $box1->pack_start($IP1, TRUE, TRUE, 0); $label1 = Gtk2::Entry->new(); $label1->set_text($name1); $box1->pack_start($label1, TRUE, TRUE, 0); $box1->show_all; $box2 = Gtk2::HBox->new(FALSE, 0); $vbox->pack_start($box2, TRUE, TRUE, 0); $button2 = Gtk2::CheckButton->new("static"); $button2->signal_connect(toggled => sub{ $active2= $button2->get_active(); activate($sock2,$address2,$active2||$mactive2); }); $box2->pack_start($button2, TRUE, TRUE, 0); $music2 = Gtk2::CheckButton->new("music "); $music2->signal_connect(toggled => sub{ $mactive2= $music2->get_active(); activate($sock2,$address2,$active2||$mactive2); }); $box2->pack_start($music2, TRUE, TRUE, 0); $IP2 = Gtk2::Entry->new(); $IP2->set_text($address2); $IP2->signal_connect (changed => sub { $address2 = $IP2->get_text; activate($sock2,$address2,$active2||$mactive2) }); $box2->pack_start($IP2, TRUE, TRUE, 0); $label2 = Gtk2::Entry->new(); $label2->set_text($name2); $box2->pack_start($label2, TRUE, TRUE, 0); $box2->show_all; $box3 = Gtk2::HBox->new(FALSE, 0); $vbox->pack_start($box3, TRUE, TRUE, 0); $button3 = Gtk2::CheckButton->new("static"); $button3->signal_connect(toggled => sub{ $active3= $button3->get_active(); activate($sock3,$address3,$active3||$mactive3); }); $box3->pack_start($button3, TRUE, TRUE, 0); $music3 = Gtk2::CheckButton->new("music "); $music3->signal_connect(toggled => sub{ $mactive3= $music3->get_active(); activate($sock3,$address3,$active3||$mactive3); }); $box3->pack_start($music3, TRUE, TRUE, 0); $IP3 = Gtk2::Entry->new(); $IP3->set_text($address3); $IP3->signal_connect (changed => sub { $address3 = $IP3->get_text; activate($sock3,$address3,$active3||$mactive3) }); $box3->pack_start($IP3, TRUE, TRUE, 0); $label3 = Gtk2::Entry->new(); $label3->set_text($name3); $box3->pack_start($label3, TRUE, TRUE, 0); $box3->show_all; sub activate { # ($sock,$address,$active) if ($_[2]) { if ($_[0]) { print "Active, closing...\n"; $_[0]=0; } print "Activating : $_[1]\n"; $_[0] = IO::Socket::INET->new(Proto=>'udp',PeerPort=>7778,PeerAddr=>$_[1]) or print "Invalid IP!\n"; } else { $_[0]=0; }} $vbox->pack_start(Gtk2::HSeparator->new(),FALSE,FALSE,4); # Auto update, RGB $box0 = Gtk2::HBox->new(FALSE, 0); $vbox->pack_start($box0, TRUE, TRUE, 0); $box0->show; $label = Gtk2::Label->new("static RGB - Auto update: "); $box0->pack_start($label, TRUE, TRUE, 0); $label->show; $button = Gtk2::CheckButton->new("On"); $button->signal_connect(toggled => sub{ ($state) = @_; $autoupdate= $button->get_active(); }); $box0->pack_start($button, TRUE, TRUE, 0); $button->show; $box = Gtk2::HBox->new(FALSE, 0); $vbox->pack_start($box, TRUE, TRUE, 0); $label = Gtk2::Label->new("R "); $box->pack_start($label, FALSE, TRUE, 0); $label->show; $adj = Gtk2::Adjustment->new($red, 0, 255, 5, 5, 0); $scale = Gtk2::HScale->new($adj); $scale->set_digits(0); $adj->signal_connect(value_changed => sub { ($scale) = @_ ; $red= $scale->value; set($red,$green,$blue) }); $box->pack_start($scale, TRUE, TRUE, 0); $scale->show; $box = Gtk2::HBox->new(FALSE, 0); $vbox->pack_start($box, TRUE, TRUE, 0); $label = Gtk2::Label->new("G "); $box->pack_start($label, FALSE, TRUE, 0); $label->show; $adj = Gtk2::Adjustment->new($green, 0, 255, 5, 5, 0); $scale = Gtk2::HScale->new($adj); $scale->set_digits(0); $adj->signal_connect(value_changed => sub { ($scale) = @_ ; $green= $scale->value; set($red,$green,$blue) }); $box->pack_start($scale, TRUE, TRUE, 0); $scale->show; $box = Gtk2::HBox->new(FALSE, 0); $vbox->pack_start($box, TRUE, TRUE, 0); $label = Gtk2::Label->new("B "); $box->pack_start($label, FALSE, TRUE, 0); $label->show; $adj = Gtk2::Adjustment->new($blue, 0, 255, 5, 5, 0); $scale = Gtk2::HScale->new($adj); $scale->set_digits(0); $adj->signal_connect(value_changed => sub { ($scale) = @_ ; $blue= $scale->value; set($red,$green,$blue) }); $box->pack_start($scale, TRUE, TRUE, 0); $scale->show; $vbox->pack_start(Gtk2::HSeparator->new(),FALSE,FALSE,4); # indicator for music data $box = Gtk2::HBox->new(FALSE, 0); $vbox->pack_start($box, TRUE, TRUE, 0); $label = Gtk2::Label->new("Music data received: "); $box->pack_start($label, FALSE, TRUE, 0); $label->show; $indicator = Gtk2::Label->new("000000"); $box->pack_end($indicator, FALSE, TRUE, 0); $indicator->show; $vbox->pack_start($box, TRUE, TRUE, 0); $label = Gtk2::Label->new("LED control SR 2020"); $vbox->pack_start($label, TRUE, TRUE, 0); $label->show; $vbox->show_all; $window->show; # Background tasks: Update RGB to keep clients happy Glib::Timeout->add (800, sub { # 800ms because 1000ms timeout on receiver if ($autoupdate == "1") { set($red,$green,$blue); }; return 1 }, 0, G_PRIORITY_DEFAULT); # Read data and pass it on Gtk2::Helper->add_watch ( $socket->fileno, "in", sub { $socket->recv($data,512); # enough for 170 pixels... # print "Received datagram from ", $socket->peerhost, ", length ", length $data, "\n"; #: $data\n"; $rgb=unpack "H*", substr $data,(length $data)/2,3; $indicator->set_text($rgb); if ( $mactive1 ) { $sock1->send($data) or print "Send error: $!\n"; } if ( $mactive2 ) { $sock2->send($data) or print "Send error: $!\n"; } if ( $mactive3 ) { $sock3->send($data) or print "Send error: $!\n"; } return 1 } ); # Main loop Gtk2->main; 0;