--[[ Cue Monitor — INIT PLUGIN a grandMA3-hoz. EZ AZ A FÁJL, AMIT EGYSZER FELMÁSOLSZ A PENDRIVE-RA, és onnan importálsz be minden konzolra. Nincs benne beégetve semmi cím: MAGA KERESI MEG a Cue Monitor szervert a hálózaton, tehát bármelyik helyszínen ugyanez a fájl működik. MIT CSINÁL, ha lefuttatod: 1. Szórásban megkérdezi, hol a Cue Monitor szerver („CUEWHO?"). Ha válaszol, onnantól tudja a címét, a portjait, mindent. 2. Ha a szórás nem megy (sok konzol-hálón tiltják), VÉGIGKÉRDEZI a saját alhálózatát (254 apró csomag, egy másodperc). 3. Ha egyik sem talál, POPUPBAN kérdezi meg a szerver IP-jét — ez az EGYETLEN dolog, amit valaha be kell írni. 4. Keres egy SZABAD OSC-slotot. A már használtakhoz (Companion, Ableton, bármi) NEM nyúl. Ha talál korábbi „CUE MONITOR" slotot, azt használja újra. 5. Beállítja: név, port, cél-IP, Receive + ReceiveCommand + Send. 6. Bekapcsolja a GLOBÁLIS OSC be- és kimenetet. ENÉLKÜL A KONZOL KI SEM NYITJA AZ UDP-PORTOT — élőben bemérve, ez a leggyakoribb néma hiba. 7. Visszaszól a szervernek, így az megtudja a konzol IP-jét. Neked semmit nem kell begépelned a Cue Monitor felületén. MIÉRT KELL EZT MINDEN SHOWNÁL LEFUTTATNI: Az OSC-slotok beállítása a SHOW-ban él. Egy másik show betöltése után eltűnik (a fejlesztés közben pont ezt mértük: egy régi show egy MÁSIK HELYSZÍN cél-IP-jét hozta magával, és a globális OSC ki volt kapcsolva). Ez a plugin öt másodperc alatt helyreteszi. TELEPÍTÉS: 1. Másold a fájlt a pendrive-ra. 2. A konzolon: Menu > Plugins > Import, és válaszd ki. 3. Futtasd le (Go a plugin-poolban). Ennyi. Ha a Cue Monitor felületén a grandMA3 fülön megnyomod a „Kapcsolat próbája" gombot, lépésenként megmondja, mi megy és mi nem. --]] local ALAP_OSC_PORT = 7000 -- ezen HALLGAT a konzol, ha a szerver mást nem mond local ALAP_WIZ_PORT = 9001 -- ide jelentkezünk be local KERES_MP = 1.5 -- ennyit várunk a szerver válaszára local function kiir(szoveg) pcall(function() Printf('%s', szoveg) end) end local function uzenet(szoveg) kiir(szoveg) pcall(function() MessageBox({ title = 'Cue Monitor', message = szoveg, commands = { { value = 1, name = 'OK' } } }) end) end local function kerdez(cim, ertek) local ok, v = pcall(function() return TextInput(cim, ertek or '') end) if ok and v ~= nil and tostring(v) ~= '' then return tostring(v) end return nil end --[[ A KONZOL SAJÁT IP-JE. A klasszikus trükk: egy UDP-socketet „rákötünk" egy távoli címre (nem megy ki csomag), és megkérdezzük, milyen helyi címet választott hozzá az operációs rendszer. Ebből tudjuk meg, MELYIK alhálózaton vagyunk. --]] local function sajat_ip() local ok, ip = pcall(function() local u = require('socket').udp() u:setpeername('8.8.8.8', 53) local cim = u:getsockname() u:close() return cim end) if ok and ip and ip ~= '0.0.0.0' then return ip end return nil end --[[ A SZERVER MEGKERESÉSE — három úton, ebben a sorrendben: 1. SZÓRÁS: egy csomag, és kész. A legtöbb helyszínen ez elég. 2. PÁSZTÁZÁS: ha a hálózat tiltja a szórást (sok konzol-hálón így van), végigkérdezzük a saját /24-ünket. 254 apró csomag, egy másodperc. 3. POPUP: ha egyik sem talál, bekérjük az IP-t. A szerver a varázsló-portján figyel, és a saját címével válaszol. --]] local function valaszra_var(u, mp) local vege = os.time() + mp while os.time() <= vege do local adat = u:receive() if adat and adat:sub(1, 8) == 'CUEHERE ' then local ip, http, osc, wiz = adat:sub(9):match('([^|]+)|([^|]+)|([^|]+)|([^|]+)') if ip then return { ip = ip, http = tonumber(http), osc = tonumber(osc) or ALAP_OSC_PORT, wiz = tonumber(wiz) or ALAP_WIZ_PORT } end end if not adat then return nil end -- időtúllépés end return nil end local function szervert_keres() local socket = require('socket') local u = socket.udp() if not u then return nil end u:settimeout(KERES_MP) --[[ ELŐBB A KÖTÉS, UTÁNA A SZÓRÁS-KAPCSOLÓ. Ez a sorrend NEM ízlés kérdése. A LuaSocket a setsockname-ig nem hoz létre igazi operációs rendszer-beli socketet, tehát egy korábbi setoption('broadcast') nem tud mihez nyúlni: „setsockopt failed"-del elszáll, és onnantól MINDEN szórásos küldés „permission denied". Élőben bemérve a konzolon (2026-08-28): fordított sorrendben a szórás SOHA nem ment el, a hiba pedig pcall-ban elveszett, tehát a plugin némán mindig a 254 csomagos pásztázásra esett vissza. Felcserélve azonnal megjön a válasz. NE setsockname('*', 0) legyen! Szintén élőben bemérve: utána minden sendto elhasal „nodename nor servname provided" hibával — ez a LuaSocket-build nem oldja fel a csillagot. A '0.0.0.0' jó. --]] local kotes, kotes_hiba = u:setsockname('0.0.0.0', 0) if not kotes then kiir('Cue Monitor: a socket kotese nem ment (' .. tostring(kotes_hiba) .. ')') end local szoras, szoras_hiba = u:setoption('broadcast', true) if not szoras then kiir('Cue Monitor: a szoras nem kapcsolhato be (' .. tostring(szoras_hiba) .. '), jon a paszazas') end local enyem = sajat_ip() local a, b2, c if enyem then a, b2, c = enyem:match('^(%d+)%.(%d+)%.(%d+)%.%d+$') end -- 1. SZÓRÁS. Több címre is: van, ahol a 255.255.255.255-öt eldobják. -- A SAJÁT alhálózatunk szórási címe megy elsőnek: a kapcsolók és a -- router ezt engedik át a legnagyobb eséllyel. local celok = {} if a then celok[#celok + 1] = a .. '.' .. b2 .. '.' .. c .. '.255' end for _, x in ipairs({ '255.255.255.255', '192.168.255.255', '10.255.255.255' }) do celok[#celok + 1] = x end for _, cel in ipairs(celok) do pcall(function() u:sendto('CUEWHO?', cel, ALAP_WIZ_PORT) end) end local sz = valaszra_var(u, 2) if sz then u:close() return sz end -- 2. PÁSZTÁZÁS a saját alhálózaton. if enyem then if a then kiir('Cue Monitor: szoras nem valaszolt, vegigkerdezem a ' .. a .. '.' .. b2 .. '.' .. c .. '.0/24-et...') for i = 1, 254 do pcall(function() u:sendto('CUEWHO?', a .. '.' .. b2 .. '.' .. c .. '.' .. i, ALAP_WIZ_PORT) end) end sz = valaszra_var(u, 3) if sz then u:close() return sz end end end u:close() return nil end local function beallit(sz) local b = Root().ShowData.OSCBase local pick = nil -- 1. Van már CUE MONITOR slotunk? Azt használjuk újra. for _, c in ipairs(b:Children()) do if tostring(c:Get('Name')) == 'CUE MONITOR' then pick = c break end end -- 2. Van slot a mi portunkon? Azt vesszük át. if not pick then for _, c in ipairs(b:Children()) do if tonumber(tostring(c:Get('Port'))) == sz.osc then pick = c break end end end -- 3. Különben egy NEM HASZNÁLT slotot foglalunk el — más rendszertől -- (Companion, Ableton, médiaszerver) nem veszünk el működő kapcsolatot. if not pick then for _, c in ipairs(b:Children()) do if tostring(c:Get('Receive')) == 'false' and tostring(c:Get('Send')) == 'false' then pick = c break end end end if not pick then uzenet('Nincs szabad OSC-slot a konzolon. Szabadits fel egyet az In & Out menuben, aztan futtasd ujra.') return nil end pick:Set('Name', 'CUE MONITOR') pick:Set('Port', sz.osc) pick:Set('DestinationIP', sz.ip) pick:Set('DestinationPort', sz.osc) pick:Set('Receive', true) pick:Set('ReceiveCommand', true) pick:Set('Send', true) b:Set('EnableInput', true) b:Set('EnableOutput', true) return tostring(pick:Get('NO')) end local function fut() kiir('Cue Monitor: keresem a szervert a halozaton...') local sz = szervert_keres() if not sz then local ip = kerdez('Nem talaltam a Cue Monitor szervert. Mi az IP-je?', '192.168.1.') if not ip then uzenet('Megszakitva: nincs szerver-cim. (A Cue Monitor gepen a SETUP > grandMA3 fulon ki van irva.)') return end sz = { ip = ip, osc = ALAP_OSC_PORT, wiz = ALAP_WIZ_PORT } end local slot = beallit(sz) if not slot then return end -- Bejelentkezés: ebből tudja meg a szerver, MELYIK gép a konzol. pcall(function() local u = require('socket').udp() u:sendto('CUEHELLO grandMA3|' .. slot .. '|' .. sz.osc, sz.ip, sz.wiz) u:close() end) uzenet('Kesz. Cue Monitor: ' .. sz.ip .. ':' .. sz.osc .. ' | OSC-slot ' .. slot .. ' beallitva, globalis OSC be- es kimenet bekapcsolva, ' .. 'es jelentkeztem a szervernek. A tobbi slotodhoz nem nyultam.') end -- Kézzel is hívható a parancssorból: Lua "CueMonitorInit()" local G = _G or _ENV G.CueMonitorInit = fut fut() return true