summaryrefslogtreecommitdiff
path: root/dalos-binaryops.lua
blob: 886f153b170dfecfb0f4db2e69420682cfe4e304 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
-- bit.tobit  bit.tohex  bit.bnot    bit.band bit.bor  bit.bxor
-- bit.lshift bit.rshift bit.arshift bit.rol  bit.ror  bit.bswap

dalosp.binaryops = {
    operations = {
        XOR = 0,
        AND = 1,
        OR = 2,
        ADD = 3,
        SUB = 4,
    },
    
    opnames = {
        [0] = "XOR",
        [1] = "AND",
        [2] = "OR",
        [3] = "ADD",
        [4] = "SUB",
    },
    
    configure = function (self)
        local accept, operation, maximize = iup.GetParam(self.name .. " configuration", nil, [[
Operation: %l|xor|and|or|add|sub|{Binary operation that's going to occur}
Maximize: %b[No,Yes]{Check if you want to maximize the output}
]], self.op or 0, self.maximize and 1 or 0)
        if accept then
            self.op = operation
            self.maximize = maximize == 1
        end
    end,
    
    input_change = function (self, ind)
        local h1 = self:get_linked_input(1)
        local h2 = self:get_linked_input(1)
        local op = self.extra.op or dalosp.binaryops.operations.XOR
        if h1 and h2 then
            self.color = cd.GREEN
            local obj = {
                h1 = h1,
                h2 = h2,
                op = op,
                maximize = self.extra.maximize,
                offset = 0,
                size = self.extra.maximize and math.max(h1:getsize(), h2:getsize()) or math.min(h1:getsize(), h2:getsize()),
                canread = function (self) return true end,
                canwrite = function (self) return false end,
                canseek = function (self) return true end,
                canwatch = function (self) return false end,
                getname = function (self) return  end,
                tell = function (self) return self.offset end,
                getsize = function (self) return self.size end,
                getmodif = function (self) return 0 end,
                flush = function (self) return true end,
                seek = function (self, offset, wheel) 
                    if wheel == SEEK_SET then
                        self.offset = offset
                    elseif wheel == SEEK_CUR then
                        self.offset = self.offset + offset
                    elseif wheel == SEEK_END then
                        self.offset = self.size + offset
                    else
                        error "Unknown wheel"
                    end
                    if self.offset < 0 then self.offset = 0 end
                    if self.offset >= self.size then self.offset = self.size end
                    return self.offset
                end,
                read = function (self, dummy, count)
                    count = math.min(count, self.size - self.offset)
                    
                    if count == 0 then
                        if self.got_eof then self.lh:close() end
                        self.got_eof = true
                        return 0
                    end
                    
                    self.got_eof = false
                    
                    self.h1:seek(self.offset)
                    self.h2:seek(self.offset)

                    local r1, t1 = self.h1:read(count)
                    local r2, t2 = self.h2:read(count)
                    local r = self.maximize and math.max(r1, r2) or math.min(r1, r2)
                    self.offset = self.offset + r
                    if r == 0 then self.got_eof = true return 0 end
                    local t = {}
                    local op
                    if self.op == dalosp.binaryops.operations.XOR then
                        op = bit.bxor
                    elseif self.op == dalosp.binaryops.operations.AND then
                        op = bit.band
                    elseif self.op == dalosp.binaryops.operations.OR then
                        op = bit.bor
                    elseif self.op == dalosp.binaryops.operations.ADD then
                        op = function(a, b) return a + b end
                    elseif self.op == dalosp.binaryops.operations.SUB then
                        op = function(a, b) return a - b end
                    end
                    for i = 0, r - 1 do
                        t[i] = bit.band(op(t1[i % r1], t2[i % r2]), 255)
                    end
                    return r, t
                end,
            }
            local newh = HandleLua(obj)
            obj.lh = newh
            self:set_houtput(newh)
            self.dcanvas:draw()
        else
            self.color = cd.YELLOW
            self:set_houtput(nil)
            self.dcanvas:draw()
        end
    end,
    
    draw = function (self, cv, x, y, w, h)
        dalosp.object.default_draw(self, cv, x, y, w, h)
        local cx, cy = x + w / 2, cv:InvertYAxis(y + h / 2)
        local op = self.extra.op or dalosp.binaryops.operations.XOR
        cv:TextAlignment(cd.CENTER)
        cv:Foreground(cd.BLACK)
        cv:Text(cx, cy, dalosp.binaryops.opnames[op])
    end,
    
    create = function (d, tab)
        tab.ninputs = 2
        tab.noutputs = 1
        tab.otype = dalos.objtype.LUA_FILTER
        tab.configure = dalosp.binaryops.configure
        tab.input_change = dalosp.binaryops.input_change
        tab.default_name = "Binary Ops"
        tab.draw = dalosp.binaryops.draw
        local extra = { }
        
        local obj = dalos.object(d, tab, extra)
    end,
}

dalos.binaryops = dalosp.binaryops.create
dalos:register_obj("Binary Ops", dalos.binaryops)