From df3c5bae24837b144a1f09d06d4cad90b8905915 Mon Sep 17 00:00:00 2001 From: Martin Peach Date: Thu, 21 Feb 2013 16:28:13 +0000 Subject: Example class that splits a text file into sentences. svn path=/trunk/externals/loaders/pdlua/; revision=17050 --- examples/ltextfile-drip-help.pd | 76 +++++++++++++ examples/ltextfile-drip.pd_lua | 230 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 306 insertions(+) create mode 100644 examples/ltextfile-drip-help.pd create mode 100644 examples/ltextfile-drip.pd_lua diff --git a/examples/ltextfile-drip-help.pd b/examples/ltextfile-drip-help.pd new file mode 100644 index 0000000..85811c0 --- /dev/null +++ b/examples/ltextfile-drip-help.pd @@ -0,0 +1,76 @@ +#N canvas 480 515 796 478 10; +#X msg 145 184 open test.txt; +#X obj 184 223 openpanel; +#X obj 122 208 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X obj 95 66 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 +-1; +#X floatatom 125 165 5 0 0 0 - - -; +#X msg 163 202 open tewt.txt; +#X obj 553 336 print EOF; +#X msg 203 242 rewind; +#X text 393 323 bang when no more lines; +#X text 252 241 rewind file to zero; +#X text 477 274 argument is a file name to be opened; +#X text 227 430 written in pd_lua by Martin Peach 2012/09/17; +#X text 239 183 open a file by name; +#X text 249 201 nonexistent file prints an error; +#X text 245 222 choose a file to open; +#X obj 201 380 s word; +#X obj 63 8 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X obj 126 15 + 500; +#X obj 126 -8 random 700; +#X obj -7 1 r ready; +#X msg 20 70 stop; +#X obj -7 25 t b b; +#X obj -7 49 delay 1000; +#X text 213 142 ltextfile-drip reads a text file. Incoming bangs cause +it to spit out sentences from the file in sequence.; +#X obj 251 342 print dripped->; +#X obj 154 66 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 +-1; +#X obj 319 388 print punctuation->; +#X obj 95 134 spigot; +#X obj 128 112 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X floatatom 194 58 5 0 0 0 - - -; +#X obj 251 307 ltextfile-drip ../a_modest_proposal_gutenberg_1080.txt +; +#X obj 95 92 delay 10; +#X symbolatom 252 363 80 0 0 0 - - -; +#X obj 63 38 metro 20000; +#X obj 144 341 route bang; +#X obj 144 401 print empty_line; +#X obj 20 156 delay 60000; +#X connect 0 0 30 0; +#X connect 1 0 30 0; +#X connect 2 0 1 0; +#X connect 3 0 31 0; +#X connect 3 0 36 0; +#X connect 4 0 30 0; +#X connect 5 0 30 0; +#X connect 7 0 30 0; +#X connect 16 0 33 0; +#X connect 18 0 17 0; +#X connect 19 0 21 0; +#X connect 20 0 36 0; +#X connect 21 0 22 0; +#X connect 21 1 20 0; +#X connect 22 0 3 0; +#X connect 25 0 30 0; +#X connect 27 0 30 0; +#X connect 28 0 27 1; +#X connect 29 0 31 1; +#X connect 30 0 24 0; +#X connect 30 0 32 0; +#X connect 30 0 34 0; +#X connect 30 1 26 0; +#X connect 30 2 6 0; +#X connect 30 2 7 0; +#X connect 31 0 27 0; +#X connect 33 0 30 0; +#X connect 34 0 35 0; +#X connect 34 0 3 0; +#X connect 34 1 15 0; +#X connect 36 0 3 0; diff --git a/examples/ltextfile-drip.pd_lua b/examples/ltextfile-drip.pd_lua new file mode 100644 index 0000000..16a1651 --- /dev/null +++ b/examples/ltextfile-drip.pd_lua @@ -0,0 +1,230 @@ +--[[ +-- ltextfile-drip +-- Output a text file as a sequence of symbols (sentences) +-- author Martin Peach 20120913 +--]] + +-- Pd class + +local LTextFileDrip = pd.Class:new():register("ltextfile-drip") +local file ourTextFile = nil +local words = {} +local wordIndex = 0 +local playbackIndex = 0 +local ourSentence, ourRemainingLine = nil +local ourLine = nil + +function LTextFileDrip:initialize(name, atoms) +--pd.post("LTextFileDrip:initialize-> name is " .. name); +--pd.post("number of atoms is ".. #atoms) +--for i,v in ipairs(atoms) do +-- pd.post(i .. " = " .. v) +--end + if #atoms > 0 then self:openOurTextFile(atoms[1]) end + if ourTextFile == nil then pd.post("LTextFileDrip:initialize: unable to open " .. atoms[1]) end + self.inlets = 1 + self.outlets = 3 + return true +end + +-- LTextFileDrip:openOurTextFile: open a text file using name as a path +function LTextFileDrip:openOurTextFile(name) + if ourTextFile ~= nil then +--pd.post("LTextFileDrip:openOurTextFile: closing old file") + ourTextFile:close() + ourTextFile = nil + end +--pd.post("LTextFileDrip:openOurTextFile ( " .. name .. " )") + ourTextFile = io.open(name) + if ourTextFile == nil then + pd.post("LTextFileDrip:openOurTextFile: Unable to open " .. name) + end + ourRemainingLine = nil +end + +function LTextFileDrip:rewindOurTextFile() +-- pd.post("LTextFileDrip:rewind") + if ourTextFile == nil then + pd.post("LTextFileDrip:rewindOurTextFile: no open file") + else + ourTextFile:seek("set") --sets the position to the beginning of the file (and returns 0) + wordIndex = 0 + playbackIndex = 0 + end +end + +-- LTextFileDrip:drip: accumulate a line of words from ourTextFile and output them as symbols, one per bang +function LTextFileDrip:drip() + local ourPunc + local repeatCount = 0 + + if ourTextFile == nil then + pd.post("LTextFileDrip:drip: no open file") + return + end +-- if wordIndex == 0 then -- read another line + repeat + repeatCount = repeatCount + 1 +--pd.post("repeat number " .. repeatCount) + if ourRemainingLine == nil then +--pd.post ("1> ourRemainingLine is nil") + ourLine = ourTextFile:read() + if ourLine == nil then + self:outlet(3, "bang", {}) -- end of file + return + end +--pd.post ("1> ourLine is [" .. ourLine .. "] len: " .. ourLine:len()) + -- strip CR LF + s,e = ourLine:find("[\n\r]") + if s then +--pd.post("1> CR or LF at " .. s) + ourLine = ourLine:sub(1,s-1) .. " " + else + ourLine = ourLine .. " " + end + elseif ourRemainingLine:len() == 0 then -- read another line +--pd.post ("2> ourRemainingLine length 0") + ourLine = ourTextFile:read() + if ourLine == nil then + self:outlet(3, "bang", {}) -- end of file + return + end +--pd.post ("2> ourLine is [" .. ourLine .. "] len: " .. ourLine:len()) + s,e = ourLine:find("[\n\r]") + if s then +--pd.post("2> CR or LF at " .. s) + ourLine = ourLine:sub(1,s-1) .. " " + else + ourLine = ourLine .. " " + end +--pd.post("Not setting ourLine from ourRemainingLine, whose length is precisely " .. ourRemainingLine:len()) + else + cstart,cend = ourRemainingLine:find("[,.;!?:]") + if cstart == nil then -- no punctuation in remainingLine, add next line from ourTextFile +--pd.post("3> Adding a new line to ourRemainingLine") + ourLine = ourTextFile:read() + if ourLine == nil then -- no more lines + self:outlet(3, "bang", {}) -- end of file + return + end +--pd.post ("3> ourLine is [" .. ourLine .. "] len: " .. ourLine:len()) + s,e = ourLine:find("[\n\r]") + if s then +--pd.post("3> CR or LF at " .. s) + ourLine = ourLine:sub(1,s-1) .. " " + else + ourLine = ourLine .. " " + end + --ourLine = ourLine:gsub("[\n\r]", " ") + if (ourLine:len() == 1) then -- an empty line +--pd.post("BLANK LINE (1)") + ourLine = "." -- replace blank line with punctuation to force a chop + end + ourLine = ourRemainingLine .. ourLine + else -- remainingLine has punctuation +--pd.post("4> ourRemainingLine contains punctuation") + ourLine = ourRemainingLine + end + ourRemainingLine = nil + end -- if ourRemainingLine == nil + ourPunc = nil + if ourLine ~= nil then -- line has content + if ourLine:len() > 0 then + wordIndex = 0 +--pd.post("LTextFileDrip:drip: <" .. ourLine .. ">") +--pd.post("LTextFileDrip:drip: len" .. ourLine:len()) +--pd.post("LTextFileDrip:drip: 1st char" .. ourLine:byte(1)) + if ((ourLine:len() == 1) and (ourLine:byte(1) == 13)) then -- a blank line +--pd.post("BLANK LINE (2)") + ourSentence = ourRemainingLine + ourRemainingLine = nil + else -- find a comma, period, semicolon, exclamation or question mark + cstart,cend = ourLine:find("[,.;!?:]") + if cstart ~= nil then -- take the line before the mark +--pd.post("LTextFileDrip:drip: cstart " .. string.format ('%d', cstart) .. " cend " .. string.format('%d', cend)) + ourPunc = ourLine:sub(cend, cend) +--pd.post("LTextFileDrip:drip: punctuation: " .. ourPunc) + ourSentence = ourLine:sub(1, cend) -- leave punctuation + if ourRemainingLine ~= nil then + ourSentence = ourRemainingLine .. ourSentence + end + ourRemainingLine = ourLine:sub(cend+1) +--pd.post("LTextFileDrip:drip punctuation found: ourSentence is " .. ourSentence) +--pd.post("LTextFileDrip:drip punctuation found: ourRemainingLine is " .. ourRemainingLine) + else -- no mark, take the whole line + if ourRemainingLine ~= nil then + ourRemainingLine = ourRemainingLine .. ourLine +--pd.post("LTextFileDrip:drip more to come: ourRemainingLine is " .. ourRemainingLine) +--for c = 1, ourRemainingLine:len() do pd.post("_" .. ourRemainingLine:byte(c) .. "_") end + else + ourRemainingLine = ourLine +--pd.post("LTextFileDrip:drip first: ourRemainingLine is " .. ourRemainingLine) + end + end -- if cstart ~= nil + end -- if ((ourLine:len() == 1) and (ourLine:byte(1) == 13)) + end -- if ourLine:len() > 0 + if ourSentence ~= nil then + if ourSentence:gmatch("%w+") then + if ((ourSentence:len() == 1) and (ourSentence:byte(1) <= 32)) then +--pd.post("BLANK LINE (3)") + wordIndex = 0 -- skip blank line + else + wordIndex = 1 + end +-- for w in ourSentence:gmatch("%w+") do +-- wordIndex = wordIndex + 1 +-- words[wordIndex] = w +--pd.post("wordIndex " .. wordIndex .. " for length " .. ourSentence:len() .. " starts with " .. ourSentence:byte(1)) + end + end + playbackIndex = 1 + else -- bang through outlet 3 serves as end of file notification + self:outlet(3, "bang", {}) + end -- if ourLine ~= nil +-- end + until ((wordIndex ~= 0) or (ourLine == nil)) + if ourPunc ~= nil then + self:outlet(2, "symbol", {ourPunc}) -- output punctuation + end + if wordIndex > 0 then -- output sentence as a single symbol + if ourSentence ~= nil then + len = ourSentence:len() +--pd.post ("ourSentence:len() is " .. len) + if len > 0 then +--pd.post("ourSentence is not zero-length") +--pd.post("ourSentence [" .. ourSentence .. "]") +--pd.post("starts with " .. ourSentence:byte(1)) + self:outlet(1, "symbol", {ourSentence}) -- output entire line + else +--pd.post("ourSentence is zero-length") + self:outlet(1, "bang", {}) -- an empty line + end + end + wordIndex = 0 -- no more words + ourSentence = nil -- no more sentence + end +end + +function LTextFileDrip:in_1(sel, atoms) -- anything +-- pd.post("LTextFileDrip:in-> sel is " .. sel); +-- pd.post("number of atoms is ".. #atoms) +-- for i,v in ipairs(atoms) do +-- pd.post(i .. " = " .. v) +-- end + + if sel == "bang" then -- output the next sentence + self:drip() + elseif sel == "open" then -- open a file + self:openOurTextFile(atoms[1]) + elseif sel == "rewind" then -- rewind the file + self:rewindOurTextFile() + elseif sel == "symbol" then -- assume it's a file name + self:openOurTextFile(atoms[1]) + elseif #atoms == 0 then -- a selector + self:error("LTextFileDrip:in_1: input not known") + else -- reject non-symbols + self:error("LTextFileDrip:in_1: input not a symbol or bang") + end +end +-- end of ltextfile-drip + -- cgit v1.2.1