This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

Text player

Help for those learning Tcl or writing their own scripts.
Post Reply
m
moonlightz
Voice
Posts: 4
Joined: Wed Aug 07, 2019 7:52 am

Text player

Post by moonlightz »

Hi there.

Years ago I had a "desire": make a script that pastes lines from various text files, like a media player does when we leave it in shuffle mode.

So there is a directory with some text files.
From the irc channel, we type for example !play.
The script gets a list of the files in the text files directory.
Then it picks a random file.
Then pastes a line every 5 seconds and then when it reaches to the end, it opens a new file and continues playing that file, each line again 5 seconds.
Changing topic is trivial with a putserv topic channel and the name of the file, for example.
There has to be a !stop command to stop the text playback.
Maybe also a !shuffle to stop the current playback and get another file for reading.
An eggdrop bot was made solely for this task and a single channel.

Code: Select all

set textlines {
        "line1"
        "line2"
        "line3"
        "line4"
        "line5"
        "line6"
        "line7"
        "line8"
        "line9"
        "line10"
}

proc playcmd {nick uhost handle chan text} {
}

proc stopcmd {nick uhost handle chan text} {
}
bind pub - "!play" playcmd
bind pub - "!stop" sttopcmd

proc textengine {} {
        utimer 5 [list s2c #mychannel] [llength $textlines]
        putlog "ended here"

}
if {![info exists positionplay]} {set positionplay}
proc s2c {chan} {
   putquick "PRIVMSG $chan :[lindex [split $::textlines "\n"] $::positionplay]"
putlog "$::positionplay"
   incr ::positionplay
        if {$::posicaoplay>[llength $::linhasdetexto]} {set ::posicaoplay 0}
}
The example above is a just a rough bad example.
Can someone help or at least point me to an existing script that does what it is asked above and then I can modify it? THank you.
User avatar
CrazyCat
Revered One
Posts: 1301
Joined: Sun Jan 13, 2002 8:00 pm
Location: France
Contact:

Re: Text player

Post by CrazyCat »

Let me ensure I understand well:
A !play command will choose a file randomly in a directory and then read it (a line each 5s), when the file is ended it takes ne next one (in its randomized list) and do the same.
The !shuffle command is the same than !play, it just resets the play list and start it again. So it could be the same command.

Here is a way to get all your files and shuffle the list:
# get all .txt files in playlist/ directory
set flist [glob -types {f} -directory playlist/ -- *.txt]

proc lshuffle {sorted} {
   set shuffled {}
   while { [llength $sorted] > 0} {
      set j [expr {int(rand() * [llength $sorted])}]
      lappend shuffled [lindex $sorted $j]
      set sorted [lreplace $sorted $j $j]
   }
   return $shuffled
}

set randomized [lshuffle $flist]
Whith that, you can now loop in $randomized. And if you want to randomize again, just redo set randomized [lshuffle $flist]
m
moonlightz
Voice
Posts: 4
Joined: Wed Aug 07, 2019 7:52 am

Re: Text player

Post by moonlightz »

Yeah. Like you put it.
More like, when I issue !play, the script picks randomly a file, updates the topic, reads each file to the irc channel, 5-7 sec a line.
When the "playback" reachs the end of the file, puts another file randomly, updates the topic, spams the new file, then picks another one, updates the topic, more spam to the channel.
The !stop has to stop the "spamming" on-demand.
The !shuffle is probably something to not implement. Issueing !play will just repick a file and read it to a channel.

For random history, I was thinking of a 10 slot list to hold filenames.
Picking one file, will fill the first slot (index 0), play the file, then get another file, check if the file is in the slot list, if not,
goes to the index 1.

Code: Select all

set slotslist {}
....
set fileslist [glob -path books/ -tails *]
while {1} {
set newpickedfilename [lindex $fileslist [expr int(rand()*[llength $fileslist])]]
if {[lsearch $slotslist $newpickedfilename]<0} {lappend $slotslist $newpickedfilename}
_1_
}
When all slots are filled, slot 1 -> slot 0, slot 2 -> slot 1,... slot 9->slo 8... new filename goes to slot 9.

Code: Select all

_1_:
if {[llength $slotslist]>10} {set slotslist [lrange $slotslist 1 9]; lappend slotslist $newpickedfilename}
When using !stop, the slots list is just cleared.
Most of times, I think of a script and it changes loads until the desired final result.
I just don't know do I can control the playback.
I was thinking of using bind time every minute to check if there are named utimers, if not, pick random file and play. But there can be upto 55 seconds of channel idling.
User avatar
CrazyCat
Revered One
Posts: 1301
Joined: Sun Jan 13, 2002 8:00 pm
Location: France
Contact:

Re: Text player

Post by CrazyCat »

wow wow wow!
Stop, quiet quite, breathe.

I gave you a way to get and shuffle the list of files, what did you do with that ? I won't make the script for you, I can help you to do it, by giving tips and tracks.
m
moonlightz
Voice
Posts: 4
Joined: Wed Aug 07, 2019 7:52 am

Re: Text player

Post by moonlightz »

I ended up baking this script myself. Text files are placed inside of books directory near the eggdrop executable.
It may need some additional tweaks and corrections but it seems to work. When I use play, it starts playing, and if I type stop, it stops playback.
I even added an "info" trigger that shows the remaining lines to display, the total lines, and an approx ETA. Hope it is useful for someone in the future.

Code: Select all

set booksdir "books/"
set chan "#books"

proc check_and_init {minute hour day month year} {
        global chan
        if {[utimers]!=""} {return}
        playbackengine $chan
}

proc playbackengine {chan} {
        global slotslist booksdir textlines
        if {![info exists slotslist]} { set slotslist {}}
        #if {![info exists positionplay]} {set positionplay 0}

#putlog "1>$slotslist"
        set bookslist [glob -path $booksdir -tails *]
        if {[llength $bookslist]>10} {
                set slotsmax 10
        } else {
                set slotsmax [expr [llength $listadelivros]-1]
        }
        while {1} {
                set pickedfile [lindex $bookslist [expr int(rand()*[llength $bookslist])]]
                if {[llength $slotslist]==$slotsmax} {
                        set slotslist [lrange $slotslist 1 end]
                }
                if {[lsearch $slotslist $fich]<0} {
                        lappend slotslist $pickedfile
                        break
                }
        }
#putlog "2>$slotslist"

        set fp [open $booksdir$pickedfile r]
        set contents [read -nonewline $fp]
        close $fp

        putquick "topic $chan :Welcome to $chan! || Now: $pickedfile"
        set textlines $contents

        bind time - "* * * * *" check_and_init
#putlog "$textlines"
        set ::positionplay 0
        utimer 5 [list s2c $chan] [llength [split $textlines \n]]
        
}


proc s2c {chan} {
        set textline [lindex [split $::textlines "\n"] $::positionplay]
        if {$textline==""} {
                set textline " "
        }
        putquick "PRIVMSG $chan :$textline"
        incr ::positionplay
}


proc playcmd {nick uhost handle chan text} {
#putquick "privmsg $chan :play"
        if {[utimers]!=""} {return}
        playbackengine $chan
}

proc stopcmd {nick uhost handle chan text} {
#putquick "privmsg $chan :stop"
        if {[utimers]!=""} {
                killutimer [lindex [lindex [utimers] 0] 2]
        }
        catch {unbind time - "* * * * *" check_and_init}
}
proc infocmd {nick uhost handle chan text} {
        global textlines
        set remaininglines [lindex [lindex [utimers] 0] 3]
        putquick "privmsg $chan :\00308,02 \002$remaininglines\002 to show of [llength [split $textlines \n]] lines. Approx [conv_sec_to_wdhms [expr $remaininglines*5]] to finish."
}

bind pub m "play" playcmd
bind pub m "stop" stopcmd
bind pub m "info" infocmd

proc conv_sec_to_wdhms {xnumber} {
        set zw 0; set zd 0; set zh 0; set zm 0; set zs 0
        set outputtext ""
        set zw [expr $xnumber/604800]
        set xnumber [expr $xnumber-$zw*604800]
        set zd [expr $xnumber/86400]
        set xnumber [expr $xnumber-$zd*86400]
        set zh [expr $xnumber/3600]
        set xnumber [expr $xnumber-$zh*3600]
        set zm [expr $xnumber/60]
        set xnumber [expr $xnumber-$zm*60]
        set zs $xnumber
        if {$zw == 1} {append outputtext $zw "w"}
        if {$zw > 1} {append outputtext $zw "w"}
        if {$zd == 1} {append outputtext $zd "d"}
        if {$zd > 1} {append outputtext $zd "d"}
        if {$zh == 1} {append outputtext $zh "h"}
        if {$zh > 1} {append outputtext $zh "h"}
        if {$zm == 1} {append outputtext $zm "m"}
        if {$zm > 1} {append outputtext $zm "m"}
        if {$zs == 1} {append outputtext $zs "s"}
        if {$zs > 1} {append outputtext $zs "s"}
        return $outputtext
}
User avatar
CrazyCat
Revered One
Posts: 1301
Joined: Sun Jan 13, 2002 8:00 pm
Location: France
Contact:

Re: Text player

Post by CrazyCat »

Ok.
Post Reply