# Path: modsdk/bundlemonitor.py
# class BundleMonitor:
# 
#     def __init__(self, callback):
#         self.callback = callback
#         self.watches = []
# 
#         self.mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE  | pyinotify.IN_CLOSE_WRITE
#         self.wm = pyinotify.WatchManager()
#         self.notifier = pyinotify.Notifier(self.wm, EventHandler(self), timeout=100)
# 
#     def monitor(self, bundle):
#         self.clear()
#         path = os.path.join(LV2_DIR, bundle)
#         self.add_watch(path)
#         self.schedule()
# 
#     def add_watch(self, path):
#         watch = self.wm.add_watch(path, self.mask, rec=True)
#         self.watches.append(watch)
#         
#     def notify(self, pathname, maskname = None):
#         self.callback()
# 
#     def schedule(self):
#         ioloop.IOLoop.instance().add_callback(self.check)
# 
#     def check(self):
#         self.notifier.process_events()
#         if self.notifier.check_events():
#             self.notifier.read_events()
#         if len(self.watches) > 0:
#             self.schedule()
# 
#     def clear(self):
#         while len(self.watches) > 0:
#             watch = self.watches.pop()
#             for path, handler in watch.items():
#                 if os.path.exists(path):
#                     self.wm.rm_watch(handler)


import json
import os
import random
import re
import shutil
import subprocess
import pyinotify
    import lilv
from base64 import b64encode
from PIL import Image
from time import time
from tornado import web, options, ioloop, template, httpclient, websocket
from tornado.escape import squeeze, url_escape
from tornado.util import unicode_type
from .bundlemonitor import BundleMonitor
from modsdk.settings import (PORT, HTML_DIR, WIZARD_DB, DEVICE_MODE, IMAGE_VERSION,
                             CONFIG_FILE, CONFIG_DIR, TEMPLATE_DIR, LV2_DIR,
                             DEFAULT_DEVICE, DEFAULT_ICON_IMAGE,
                             DEFAULT_ICON_TEMPLATE, DEFAULT_SETTINGS_TEMPLATE,
                             MAX_THUMB_WIDTH, MAX_THUMB_HEIGHT,
                             SCREENSHOT_SCRIPT, PHANTOM_BINARY)
    from modsdk.utils import (init as lv2_init2,
                              cleanup as lv2_cleanup2,
                              get_bundle_plugins as get_bundle_plugins2,
                              get_all_bundles)
    from modsdk.lilvlib import get_plugin_info as get_plugin_info2
    from modsdk.utils import (init as lv2_init,
                              cleanup as lv2_cleanup,
                              get_all_bundles,
                              get_bundle_plugins,
                              get_plugin_info)

    def get_bundle_location(self, data):
        # check for resourcesDirectory property (no modgui available if invalid)
        if not data['gui']['resourcesDirectory']:
            bundledir = data['bundles'][0]

            # check if we can use plugin bundle dir as output for modgui
            if os.path.isdir(bundledir) and os.access(bundledir, os.W_OK):
                resrcsdir = os.path.join(bundledir, "modgui")
                return (bundledir, resrcsdir, True)

        # check for modificableInPlace property (custom bundle.modgui folder)
        if data['gui']['modificableInPlace']:
            resrcsdir = data['gui']['resourcesDirectory']

            # make sure it's safe to use
            if os.path.isdir(resrcsdir) and os.access(resrcsdir, os.W_OK):
                bundledir = os.path.join(resrcsdir, os.path.pardir)
                return (bundledir, resrcsdir, False)

        # if we get here, we need to create a new modgui folder
        bundlname  = symbolify(data['name'])
        bundledir  = "%s/%s.modgui" % (LV2_DIR, bundlname)
        appendMode = False

        # never use modgui.ttl for new modguis
        data['gui']['usingSeeAlso'] = False

        # if bundle already exists, generate a new random bundle name
        if os.path.exists(bundledir):

# Path: modsdk/bundlemonitor.py
# class BundleMonitor:
# 
#     def __init__(self, callback):
#         self.callback = callback
#         self.watches = []
# 
#         self.mask = pyinotify.IN_DELETE | pyinotify.IN_CREATE  | pyinotify.IN_CLOSE_WRITE
#         self.wm = pyinotify.WatchManager()
#         self.notifier = pyinotify.Notifier(self.wm, EventHandler(self), timeout=100)
# 
#     def monitor(self, bundle):
#         self.clear()
#         path = os.path.join(LV2_DIR, bundle)
#         self.add_watch(path)
#         self.schedule()
# 
#     def add_watch(self, path):
#         watch = self.wm.add_watch(path, self.mask, rec=True)
#         self.watches.append(watch)
#         
#     def notify(self, pathname, maskname = None):
#         self.callback()
# 
#     def schedule(self):
#         ioloop.IOLoop.instance().add_callback(self.check)
# 
#     def check(self):
#         self.notifier.process_events()
#         if self.notifier.check_events():
#             self.notifier.read_events()
#         if len(self.watches) > 0:
#             self.schedule()
# 
#     def clear(self):
#         while len(self.watches) > 0:
#             watch = self.watches.pop()
#             for path, handler in watch.items():
#                 if os.path.exists(path):
#                     self.wm.rm_watch(handler)


# Path: modsdk/webserver.py
import json
import os
import random
import re
import shutil
import subprocess
import pyinotify
    import lilv
from base64 import b64encode
from PIL import Image
from time import time
from tornado import web, options, ioloop, template, httpclient, websocket
from tornado.escape import squeeze, url_escape
from tornado.util import unicode_type
from .bundlemonitor import BundleMonitor
from modsdk.settings import (PORT, HTML_DIR, WIZARD_DB, DEVICE_MODE, IMAGE_VERSION,
                             CONFIG_FILE, CONFIG_DIR, TEMPLATE_DIR, LV2_DIR,
                             DEFAULT_DEVICE, DEFAULT_ICON_IMAGE,
                             DEFAULT_ICON_TEMPLATE, DEFAULT_SETTINGS_TEMPLATE,
                             MAX_THUMB_WIDTH, MAX_THUMB_HEIGHT,
                             SCREENSHOT_SCRIPT, PHANTOM_BINARY)
    from modsdk.utils import (init as lv2_init2,
                              cleanup as lv2_cleanup2,
                              get_bundle_plugins as get_bundle_plugins2,
                              get_all_bundles)
    from modsdk.lilvlib import get_plugin_info as get_plugin_info2
    from modsdk.utils import (init as lv2_init,
                              cleanup as lv2_cleanup,
                              get_all_bundles,
                              get_bundle_plugins,
                              get_plugin_info)


    def get_bundle_location(self, data):
        # check for resourcesDirectory property (no modgui available if invalid)
        if not data['gui']['resourcesDirectory']:
            bundledir = data['bundles'][0]

            # check if we can use plugin bundle dir as output for modgui
            if os.path.isdir(bundledir) and os.access(bundledir, os.W_OK):
                resrcsdir = os.path.join(bundledir, "modgui")
                return (bundledir, resrcsdir, True)

        # check for modificableInPlace property (custom bundle.modgui folder)
        if data['gui']['modificableInPlace']:
            resrcsdir = data['gui']['resourcesDirectory']

            # make sure it's safe to use
            if os.path.isdir(resrcsdir) and os.access(resrcsdir, os.W_OK):
                bundledir = os.path.join(resrcsdir, os.path.pardir)
                return (bundledir, resrcsdir, False)

        # if we get here, we need to create a new modgui folder
        bundlname  = symbolify(data['name'])
        bundledir  = "%s/%s.modgui" % (LV2_DIR, bundlname)
        appendMode = False

        # never use modgui.ttl for new modguis
        data['gui']['usingSeeAlso'] = False

        # if bundle already exists, generate a new random bundle name
        if os.path.exists(bundledir):

            while True: