applications/luci-asterisk: add meetme support, data integrity improvements
authorJo-Philipp Wich <jow@openwrt.org>
Mon, 30 Mar 2009 19:29:37 +0000 (19:29 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Mon, 30 Mar 2009 19:29:37 +0000 (19:29 +0000)
applications/luci-asterisk/luasrc/asterisk.lua
applications/luci-asterisk/luasrc/controller/asterisk.lua
applications/luci-asterisk/luasrc/model/cbi/asterisk/meetme.lua [new file with mode: 0644]
applications/luci-asterisk/luasrc/model/cbi/asterisk/meetme_settings.lua [new file with mode: 0644]
applications/luci-asterisk/luasrc/model/cbi/asterisk/voicemail.lua
applications/luci-asterisk/luasrc/view/asterisk/dialplans.htm

index 23193e7..15081cc 100644 (file)
@@ -598,11 +598,102 @@ end
 
 --- Remove voicemailbox and associated extensions from config
 -- @param box  Voicemailbox number or table
 
 --- Remove voicemailbox and associated extensions from config
 -- @param box  Voicemailbox number or table
+-- @param ctx  UCI context to use (optional)
 -- @return             Boolean indicating success
 -- @return             Boolean indicating success
-function voicemail.remove(v)
+function voicemail.remove(v, ctx)
+       ctx = ctx or uci
        local box = type(v) == "string" and v or v.number
        local box = type(v) == "string" and v or v.number
-       local ok1 = uci:delete_all("asterisk", "voicemail", {number=box})
-       local ok2 = uci:delete_all("asterisk", "dialplanvoice", {voicebox=box})
+       local ok1 = ctx:delete_all("asterisk", "voicemail", {number=box})
+       local ok2 = ctx:delete_all("asterisk", "dialplanvoice", {voicebox=box})
+       return ( ok1 or ok2 ) and true or false
+end
+
+
+--- LuCI Asterisk - MeetMe Conferences
+-- @type       module
+meetme = luci.util.class()
+
+--- Parse a meetme section
+-- @param room Table containing the room info
+-- @return             Table with parsed information
+function meetme.parse(r)
+       if r.room and #r.room > 0 then
+               local v = {
+                       room            = r.room,
+                       pin                     = r.pin                         or '',
+                       adminpin        = r.adminpin            or '',
+                       description = r._description    or '',
+                       dialplans       = { }
+               }
+
+               uci:foreach("asterisk", "dialplanmeetme",
+                       function(s)
+                               if s.dialplan and #s.dialplan > 0 and s.room == v.room then
+                                       v.dialplans[#v.dialplans+1] = s.dialplan
+                               end
+                       end)
+
+               return v
+       end
+end
+
+--- Get a list of known meetme rooms
+-- @return             Associative table of rooms and table of room numbers
+function meetme.rooms()
+       local mrooms = { }
+       local mnames = { }
+       uci:foreach("asterisk", "meetme",
+               function(r)
+                       local v = meetme.parse(r)
+                       if v then
+                               mrooms[v.room] = v
+                               mnames[#mnames+1] = v.room
+                       end
+               end)
+       return mrooms, mnames
+end
+
+--- Get a specific meetme room
+-- @param number       Number of the room
+-- @return                     Table containing room information
+function meetme.room(n)
+       local room
+       uci:foreach("asterisk", "meetme",
+               function(r)
+                       if r.room == tostring(n) then
+                               room = meetme.parse(r)
+                       end
+               end)
+       return room
+end
+
+--- Find all meetme rooms within the given dialplan
+-- @param plan Dialplan name or table
+-- @return             Associative table containing extensions mapped to room info
+function meetme.in_dialplan(p)
+       local plan  = type(p) == "string" and p or p.name
+       local rooms = { }
+       uci:foreach("asterisk", "dialplanmeetme",
+               function(s)
+                       if s.extension and #s.extension > 0 and s.dialplan == plan then
+                               local room = meetme.room(s.room)
+                               if room then
+                                       rooms[s.extension] = room
+                               end
+                       end
+               end)
+       return rooms
+end
+
+--- Remove meetme room and associated extensions from config
+-- @param room Voicemailbox number or table
+-- @param ctx  UCI context to use (optional)
+-- @return             Boolean indicating success
+function meetme.remove(v, ctx)
+       ctx = ctx or uci
+       local room = type(v) == "string" and v or v.number
+       local ok1  = ctx:delete_all("asterisk", "meetme", {room=room})
+       local ok2  = ctx:delete_all("asterisk", "dialplanmeetme", {room=room})
        return ( ok1 or ok2 ) and true or false
 end
 
        return ( ok1 or ok2 ) and true or false
 end
 
@@ -633,6 +724,9 @@ function dialplan.parse(z)
                -- voicemailboxes
                plan.voicemailboxes = voicemail.in_dialplan(plan)
 
                -- voicemailboxes
                plan.voicemailboxes = voicemail.in_dialplan(plan)
 
+               -- meetme conferences
+               plan.meetmerooms = meetme.in_dialplan(plan)
+
                return plan
        end
 end
                return plan
        end
 end
index c258f2d..ab05339 100644 (file)
@@ -53,7 +53,11 @@ function index()
        entry({"admin", "asterisk", "voicemail", "mailboxes"},  cbi("asterisk/voicemail"),                      "Mailboxes",    1)
        entry({"admin", "asterisk", "voicemail", "settings"},   cbi("asterisk/voicemail_settings"),     "Settings",     2)
 
        entry({"admin", "asterisk", "voicemail", "mailboxes"},  cbi("asterisk/voicemail"),                      "Mailboxes",    1)
        entry({"admin", "asterisk", "voicemail", "settings"},   cbi("asterisk/voicemail_settings"),     "Settings",     2)
 
-       entry({"admin", "asterisk", "dialplans"},                               call("handle_dialplan"),                "Call Routing", 4)
+       entry({"admin", "asterisk", "meetme"},                          cbi("asterisk/meetme"),                 "MeetMe",               4)
+       entry({"admin", "asterisk", "meetme", "rooms"},                 cbi("asterisk/meetme"),                         "Rooms",                1)
+       entry({"admin", "asterisk", "meetme", "settings"},              cbi("asterisk/meetme_settings"),        "Settings",     2)
+
+       entry({"admin", "asterisk", "dialplans"},                               call("handle_dialplan"),                "Call Routing", 5)
        entry({"admin", "asterisk", "dialplans", "out"},                cbi("asterisk/dialplan_out"),           nil,            1).leaf = true
        entry({"admin", "asterisk", "dialplans", "zones"},              call("handle_dialzones"),                       "Dial Zones",   2).leaf = true
 
        entry({"admin", "asterisk", "dialplans", "out"},                cbi("asterisk/dialplan_out"),           nil,            1).leaf = true
        entry({"admin", "asterisk", "dialplans", "zones"},              call("handle_dialzones"),                       "Dial Zones",   2).leaf = true
 
@@ -125,6 +129,28 @@ function handle_dialplan()
                end
        end
 
                end
        end
 
+       for k, v in pairs(luci.http.formvaluetable("delmeetme")) do
+               local plan = ast.dialplan.plan(k)
+               if #v > 0 and plan then
+                       uci:delete_all("asterisk", "dialplanmeetme",
+                               { extension=v, dialplan=plan.name })
+               end
+       end
+
+       for k, v in pairs(luci.http.formvaluetable("addmeetme")) do
+               local plan = ast.dialplan.plan(k)
+               local meetme = ast.meetme.room(v)
+               if plan and meetme then
+                       local mext = luci.http.formvalue("addmeetmeext.%s" % plan.name)
+                       mext = ( mext and #mext > 0 ) and mext or meetme.room
+                       uci:section("asterisk", "dialplanmeetme", nil, {
+                               dialplan        = plan.name,
+                               extension       = mext,
+                               room            = meetme.room
+                       })
+               end
+       end
+
        local aname = luci.http.formvalue("addplan")
        if aname and #aname > 0 then
                if aname:match("^[a-zA-Z0-9_]+$") then
        local aname = luci.http.formvalue("addplan")
        if aname and #aname > 0 then
                if aname:match("^[a-zA-Z0-9_]+$") then
diff --git a/applications/luci-asterisk/luasrc/model/cbi/asterisk/meetme.lua b/applications/luci-asterisk/luasrc/model/cbi/asterisk/meetme.lua
new file mode 100644 (file)
index 0000000..b02a8f6
--- /dev/null
@@ -0,0 +1,49 @@
+--[[
+LuCI - Lua Configuration Interface
+
+Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+$Id$
+]]--
+
+local ast = require "luci.asterisk"
+
+cbimap = Map("asterisk", "MeetMe - Rooms")
+
+meetme = cbimap:section(TypedSection, "meetme", "MeetMe Rooms")
+meetme.addremove = true
+meetme.anonymous = true
+meetme.template = "cbi/tblsection"
+meetme:option(Value, "_description", "Description", "Short room description")
+
+room = meetme:option(Value, "room", "Room Number", "Unique room identifier")
+
+function room.write(self, s, val)
+       if val and #val > 0 then
+               local old = self:cfgvalue(s)
+               self.map.uci:foreach("asterisk", "dialplanmeetme",
+                       function(v)
+                               if v.room == old then
+                                       self.map:set(v['.name'], "room", val)
+                               end
+                       end)
+               Value.write(self, s, val)
+       end
+end
+
+
+meetme:option(Value, "pin", "PIN", "PIN required to access")
+meetme:option(Value, "adminpin", "Admin PIN", "PIN required for administration")
+
+function meetme.remove(self, s)
+       return ast.meetme.remove(self.map:get(s, "room"), self.map.uci)
+end
+
+
+return cbimap
diff --git a/applications/luci-asterisk/luasrc/model/cbi/asterisk/meetme_settings.lua b/applications/luci-asterisk/luasrc/model/cbi/asterisk/meetme_settings.lua
new file mode 100644 (file)
index 0000000..511d7a7
--- /dev/null
@@ -0,0 +1,28 @@
+--[[
+LuCI - Lua Configuration Interface
+
+Copyright 2009 Jo-Philipp Wich <xm@subsignal.org>
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+$Id$
+]]--
+
+cbimap = Map("asterisk", "MeetMe - Common Settings",
+       "Common settings for MeetMe phone conferences.")
+
+meetme = cbimap:section(TypedSection, "meetmegeneral", "General MeetMe Options")
+meetme.addremove = false
+meetme.anonymous = true
+
+audiobuffers = meetme:option(ListValue, "audiobuffers",
+       "Number of 20ms audio buffers to use for conferences")
+
+for i = 2, 32 do audiobuffers:value(i) end
+
+
+return cbimap
index 1c92d0d..5d0de75 100644 (file)
@@ -12,6 +12,8 @@ You may obtain a copy of the License at
 $Id$
 ]]--
 
 $Id$
 ]]--
 
+local ast = require "luci.asterisk"
+
 cbimap = Map("asterisk", "Voicemail - Mailboxes")
 
 voicemail = cbimap:section(TypedSection, "voicemail", "Voicemail Boxes")
 cbimap = Map("asterisk", "Voicemail - Mailboxes")
 
 voicemail = cbimap:section(TypedSection, "voicemail", "Voicemail Boxes")
@@ -22,7 +24,23 @@ voicemail.template = "cbi/tblsection"
 context = voicemail:option(ListValue, "context", "Context")
 context:value("default")
 
 context = voicemail:option(ListValue, "context", "Context")
 context:value("default")
 
-voicemail:option(Value, "number", "Mailbox Number", "Unique mailbox identifier")
+number = voicemail:option(Value, "number",
+       "Mailbox Number", "Unique mailbox identifier")
+
+function number.write(self, s, val)
+       if val and #val > 0 then
+               local old = self:cfgvalue(s)
+               self.map.uci:foreach("asterisk", "dialplanvoice",
+                       function(v)
+                               if v.voicebox == old then
+                                       self.map:set(v['.name'], "voicebox", val)
+                               end
+                       end)
+               Value.write(self, s, val)
+       end
+end
+
+
 voicemail:option(Value, "name", "Ownername", "Human readable display name")
 voicemail:option(Value, "password", "Password", "Access protection")
 voicemail:option(Value, "email", "eMail", "Where to send voice messages")
 voicemail:option(Value, "name", "Ownername", "Human readable display name")
 voicemail:option(Value, "password", "Password", "Access protection")
 voicemail:option(Value, "email", "eMail", "Where to send voice messages")
@@ -33,5 +51,9 @@ zone.titleref = luci.dispatcher.build_url("admin/asterisk/voicemail/settings")
 cbimap.uci:foreach("asterisk", "voicezone",
        function(s) zone:value(s['.name']) end)
 
 cbimap.uci:foreach("asterisk", "voicezone",
        function(s) zone:value(s['.name']) end)
 
+function voicemail.remove(self, s)
+       return ast.voicemail.remove(self.map:get(s, "number"), self.map.uci)
+end
+
 
 return cbimap
 
 return cbimap
index 79b81bd..a360162 100644 (file)
@@ -78,7 +78,8 @@ $Id$
                Here you can manage your dial plans which are used to route outgoing calls from your local extensions.<br /><br />
                Related tasks:<br />
                <a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans/zones')%>" class="cbi-title-ref">Manage dialzones</a> |
                Here you can manage your dial plans which are used to route outgoing calls from your local extensions.<br /><br />
                Related tasks:<br />
                <a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans/zones')%>" class="cbi-title-ref">Manage dialzones</a> |
-               <a href="<%=luci.dispatcher.build_url('admin/asterisk/voicemail/mailboxes')%>" class="cbi-title-ref">Manage voicemail boxes</a>
+               <a href="<%=luci.dispatcher.build_url('admin/asterisk/voicemail/mailboxes')%>" class="cbi-title-ref">Manage voicemail boxes</a> |
+               <a href="<%=luci.dispatcher.build_url('admin/asterisk/meetme/rooms')%>" class="cbi-title-ref">Manage meetme rooms</a>
        </div>
        <!-- tblsection -->
        <fieldset class="cbi-section" id="cbi-asterisk-sip">
        </div>
        <!-- tblsection -->
        <fieldset class="cbi-section" id="cbi-asterisk-sip">
@@ -117,10 +118,10 @@ $Id$
                                                </p>
                                        </td>
                                        <td style="width:5%" class="cbi-value-field">
                                                </p>
                                        </td>
                                        <td style="width:5%" class="cbi-value-field">
-                                               <a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans', 'out', zone.name)%>">
+                                               <a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans/out', zone.name)%>">
                                                        <img style="border:none" alt="Edit dialzone" title="Edit dialzone" src="/luci-static/resources/cbi/edit.gif" />
                                                </a>
                                                        <img style="border:none" alt="Edit dialzone" title="Edit dialzone" src="/luci-static/resources/cbi/edit.gif" />
                                                </a>
-                                               <a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans')%>?delzone.<%=plan.name%>=<%=zone.name%>">
+                                               <a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans')%>?delzone.<%=plan.name%>=<%=zone.name%>">
                                                        <img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" />
                                                </a>
                                        </td>
                                                        <img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" />
                                                </a>
                                        </td>
@@ -142,10 +143,10 @@ $Id$
                                                </p>
                                        </td>
                                        <td style="width:5%" class="cbi-value-field">
                                                </p>
                                        </td>
                                        <td style="width:5%" class="cbi-value-field">
-                                               <a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans', 'out', box.name)%>">
+                                               <a href="<%=luci.dispatcher.build_url('admin/asterisk/voicemail/mailboxes')%>">
                                                        <img style="border:none" alt="Edit dialzone" title="Edit dialzone" src="/luci-static/resources/cbi/edit.gif" />
                                                </a>
                                                        <img style="border:none" alt="Edit dialzone" title="Edit dialzone" src="/luci-static/resources/cbi/edit.gif" />
                                                </a>
-                                               <a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans')%>?delvbox.<%=plan.name%>=<%=ext%>">
+                                               <a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans')%>?delvbox.<%=plan.name%>=<%=ext%>">
                                                        <img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" />
                                                </a>
                                        </td>
                                                        <img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" />
                                                </a>
                                        </td>
@@ -153,6 +154,28 @@ $Id$
                                <% row = row + 1; end %>
                                <!-- /voicemail -->
 
                                <% row = row + 1; end %>
                                <!-- /voicemail -->
 
+                               <!-- meetme -->
+                               <% local rooms_used = { } %>
+                               <% for ext, room in luci.util.kspairs(plan.meetmerooms) do rooms_used[room.room] = true %>
+                               <tr class="cbi-section-table-row <%=rowstyle(row)%>">
+                                       <td style="text-align: left; padding: 3px" class="cbi-section-table-cell">
+                                               <strong>&#x2514; MeetMe Room <em><%=room.room%></em></strong> (<%=room.description%>)
+                                               <p style="padding-left: 1em; margin-bottom:0">
+                                                       Matches: <%=format_matches(ext)%>
+                                               </p>
+                                       </td>
+                                       <td style="width:5%" class="cbi-value-field">
+                                               <a href="<%=luci.dispatcher.build_url('admin/asterisk/meetme/rooms')%>">
+                                                       <img style="border:none" alt="Edit dialzone" title="Edit dialzone" src="/luci-static/resources/cbi/edit.gif" />
+                                               </a>
+                                               <a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans')%>?delmeetme.<%=plan.name%>=<%=ext%>">
+                                                       <img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" />
+                                               </a>
+                                       </td>
+                               </tr>
+                               <% row = row + 1; end %>
+                               <!-- /meetme -->
+
                                <tr class="cbi-section-table-row">
                                        <td style="text-align: left; padding: 3px" class="cbi-section-table-cell" colspan="2">
                                                <hr style="margin-bottom:0.5em; border-width:0 0 1px 0" />
                                <tr class="cbi-section-table-row">
                                        <td style="text-align: left; padding: 3px" class="cbi-section-table-cell" colspan="2">
                                                <hr style="margin-bottom:0.5em; border-width:0 0 1px 0" />
@@ -181,6 +204,19 @@ $Id$
                                                <input type="text" style="width:5%" name="addvboxext.<%=plan.name%>" />
                                                <br /><br />
 
                                                <input type="text" style="width:5%" name="addvboxext.<%=plan.name%>" />
                                                <br /><br />
 
+                                               Add MeetMe Conference:<br />
+                                               <select style="width:20%" name="addmeetme.<%=plan.name%>" onchange="this.form['addmeetmeext.<%=plan.name%>'].value=this.options[this.selectedIndex].value">
+                                                       <option value="">-- please select --</option>
+                                                       <% for ext, room in luci.util.kspairs(ast.meetme.rooms()) do %>
+                                                               <%# if not rooms_used[room.room] then %>
+                                                                       <option value="<%=room.room%>"><%=room.room%> (<%=room.description%>)</option>
+                                                               <%# end %>
+                                                       <% end %>
+                                               </select>
+                                               as extension
+                                               <input type="text" style="width:5%" name="addmeetmeext.<%=plan.name%>" />
+                                               <br /><br />
+
                                                <input type="submit" class="cbi-button cbi-button-add" value="Add item &raquo;" title="Add item ..."/>
                                        </td>
                                </tr>
                                                <input type="submit" class="cbi-button cbi-button-add" value="Add item &raquo;" title="Add item ..."/>
                                        </td>
                                </tr>