We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Import useful classes in mycroft package
This is open for discussion, but I think it is worth importing a few classes/functions in `mycroft/__init__.py` so that skills can do things like:
```Python
from mycroft import MycroftSkill  # vs. from mycroft.skills.core import MycroftSkil
class MySkill(MycroftSkill):
# ...
```

Or:
```Python
from mycroft import FallbackSkill, play_wav
class MediaFallback(FallbackSkill):
    def handle_fallback(self, message):
        # ...
        play_wav('my_song.wav')
        # ...

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mycroft/__init__.py`
Content:
```
1 from os.path import abspath, dirname, join
2 
3 __author__ = 'seanfitz'
4 
5 MYCROFT_ROOT_PATH = abspath(join(dirname(__file__), '..'))
6
```

Path: `mycroft/util/__init__.py`
Content:
```
1 # Copyright 2016 Mycroft AI, Inc.
2 #
3 # This file is part of Mycroft Core.
4 #
5 # Mycroft Core is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Mycroft Core is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Mycroft Core.  If not, see <http://www.gnu.org/licenses/>.
17 
18 
19 import socket
20 import subprocess
21 import tempfile
22 import time
23 
24 import os
25 import os.path
26 import time
27 from stat import S_ISREG, ST_MTIME, ST_MODE, ST_SIZE
28 import psutil
29 from mycroft.util.log import getLogger
30 from mycroft.util.signal import *
31 import mycroft.configuration
32 import mycroft.audio
33 
34 __author__ = 'jdorleans'
35 
36 logger = getLogger(__name__)
37 
38 
39 def resolve_resource_file(res_name):
40     """Convert a resource into an absolute filename.
41 
42     Resource names are in the form: 'filename.ext'
43     or 'path/filename.ext'
44 
45     The system wil look for ~/.mycroft/res_name first, and
46     if not found will look at /opt/mycroft/res_name,
47     then finally it will look for res_name in the 'mycroft/res'
48     folder of the source code package.
49 
50     Example:
51     With mycroft running as the user 'bob', if you called
52         resolve_resource_file('snd/beep.wav')
53     it would return either '/home/bob/.mycroft/snd/beep.wav' or
54     '/opt/mycroft/snd/beep.wav' or '.../mycroft/res/snd/beep.wav',
55     where the '...' is replaced by the path where the package has
56     been installed.
57 
58     Args:
59         res_name (str): a resource path/name
60     """
61 
62     # First look for fully qualified file (e.g. a user setting)
63     if os.path.isfile(res_name):
64         return res_name
65 
66     # Now look for ~/.mycroft/res_name (in user folder)
67     filename = os.path.expanduser("~/.mycroft/" + res_name)
68     if os.path.isfile(filename):
69         return filename
70 
71     # Next look for /opt/mycroft/res/res_name
72     filename = os.path.expanduser("/opt/mycroft/" + res_name)
73     if os.path.isfile(filename):
74         return filename
75 
76     # Finally look for it in the source package
77     filename = os.path.join(os.path.dirname(__file__), '..', 'res', res_name)
78     filename = os.path.abspath(os.path.normpath(filename))
79     if os.path.isfile(filename):
80         return filename
81 
82     return None  # Resource cannot be resolved
83 
84 
85 def play_wav(uri):
86     config = mycroft.configuration.ConfigurationManager.instance()
87     play_cmd = config.get("play_wav_cmdline")
88     play_wav_cmd = str(play_cmd).split(" ")
89     for index, cmd in enumerate(play_wav_cmd):
90         if cmd == "%1":
91             play_wav_cmd[index] = (get_http(uri))
92     return subprocess.Popen(play_wav_cmd)
93 
94 
95 def play_mp3(uri):
96     config = mycroft.configuration.ConfigurationManager.instance()
97     play_cmd = config.get("play_mp3_cmdline")
98     play_mp3_cmd = str(play_cmd).split(" ")
99     for index, cmd in enumerate(play_mp3_cmd):
100         if cmd == "%1":
101             play_mp3_cmd[index] = (get_http(uri))
102     return subprocess.Popen(play_mp3_cmd)
103 
104 
105 def record(file_path, duration, rate, channels):
106     if duration > 0:
107         return subprocess.Popen(
108             ["arecord", "-r", str(rate), "-c", str(channels), "-d",
109              str(duration), file_path])
110     else:
111         return subprocess.Popen(
112             ["arecord", "-r", str(rate), "-c", str(channels), file_path])
113 
114 
115 def get_http(uri):
116     return uri.replace("https://", "http://")
117 
118 
119 def remove_last_slash(url):
120     if url and url.endswith('/'):
121         url = url[:-1]
122     return url
123 
124 
125 def read_stripped_lines(filename):
126     with open(filename, 'r') as f:
127         return [line.strip() for line in f]
128 
129 
130 def read_dict(filename, div='='):
131     d = {}
132     with open(filename, 'r') as f:
133         for line in f:
134             (key, val) = line.split(div)
135             d[key.strip()] = val.strip()
136     return d
137 
138 
139 def connected(host="8.8.8.8", port=53, timeout=3):
140     """
141     Thanks to 7h3rAm on
142     Host: 8.8.8.8 (google-public-dns-a.google.com)
143     OpenPort: 53/tcp
144     Service: domain (DNS/TCP)
145 
146     NOTE:
147     This is no longer in use by this version
148     New method checks for a connection using ConnectionError only when
149     a question is asked
150     """
151     try:
152         socket.setdefaulttimeout(timeout)
153         socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
154         return True
155     except IOError:
156         try:
157             socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(
158                 ("8.8.4.4", port))
159             return True
160         except IOError:
161             return False
162 
163 
164 def curate_cache(dir, min_free_percent=5.0):
165     """Clear out the directory if needed
166 
167     This assumes all the files in the directory can be deleted as freely
168 
169     Args:
170         dir (str): directory path that holds cached files
171         min_free_percent (float): percentage (0.0-100.0) of drive to keep free
172     """
173 
174     # Simpleminded implementation -- keep a certain percentage of the
175     # disk available.
176     # TODO: Would be easy to add more options, like whitelisted files, etc.
177     space = psutil.disk_usage(dir)
178 
179     # space.percent = space.used/space.total*100.0
180     percent_free = 100.0-space.percent
181     if percent_free < min_free_percent:
182         # calculate how many bytes we need to delete
183         bytes_needed = (min_free_percent - percent_free) / 100.0 * space.total
184         bytes_needed = int(bytes_needed + 1.0)
185 
186         # get all entries in the directory w/ stats
187         entries = (os.path.join(dir, fn) for fn in os.listdir(dir))
188         entries = ((os.stat(path), path) for path in entries)
189 
190         # leave only regular files, insert modification date
191         entries = ((stat[ST_MTIME], stat[ST_SIZE], path)
192                    for stat, path in entries if S_ISREG(stat[ST_MODE]))
193 
194         # delete files with oldest modification date until space is freed
195         space_freed = 0
196         for moddate, fsize, path in sorted(entries):
197             try:
198                 os.remove(path)
199                 space_freed += fsize
200             except:
201                 pass
202 
203             if space_freed > bytes_needed:
204                 return  # deleted enough!
205 
206 
207 def get_cache_directory(domain=None):
208     """Get a directory for caching data
209 
210     This directory can be used to hold temporary caches of data to
211     speed up performance.  This directory will likely be part of a
212     small RAM disk and may be cleared at any time.  So code that
213     uses these cached files must be able to fallback and regenerate
214     the file.
215 
216     Args:
217         domain (str): The cache domain.  Basically just a subdirectory.
218 
219     Return:
220         str: a path to the directory where you can cache data
221     """
222     config = mycroft.configuration.ConfigurationManager.instance()
223     dir = config.get("cache_path")
224     if not dir:
225         # If not defined, use /tmp/mycroft/cache
226         dir = os.path.join(tempfile.gettempdir(), "mycroft", "cache")
227     return ensure_directory_exists(dir, domain)
228 
229 
230 def validate_param(value, name):
231     if not value:
232         raise ValueError("Missing or empty %s in mycroft.conf " % name)
233 
234 
235 def is_speaking():
236     """Determine if Text to Speech is occurring
237 
238     Returns:
239         bool: True while still speaking
240     """
241     logger.info("mycroft.utils.is_speaking() is depreciated, use "
242                 "mycroft.audio.is_speaking() instead.")
243     return mycroft.audio.is_speaking()
244 
245 
246 def wait_while_speaking():
247     """Pause as long as Text to Speech is still happening
248 
249     Pause while Text to Speech is still happening.  This always pauses
250     briefly to ensure that any preceeding request to speak has time to
251     begin.
252     """
253     logger.info("mycroft.utils.wait_while_speaking() is depreciated, use "
254                 "mycroft.audio.wait_while_speaking() instead.")
255     return mycroft.audio.wait_while_speaking()
256 
257 
258 def stop_speaking():
259     # TODO: Less hacky approach to this once Audio Manager is implemented
260     # Skills should only be able to stop speech they've initiated
261     logger.info("mycroft.utils.stop_speaking() is depreciated, use "
262                 "mycroft.audio.stop_speaking() instead.")
263     mycroft.audio.stop_speaking()
264
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mycroft/__init__.py b/mycroft/__init__.py
--- a/mycroft/__init__.py
+++ b/mycroft/__init__.py
@@ -1,3 +1,9 @@
+from mycroft.api import Api
+from mycroft.skills.core import MycroftSkill, FallbackSkill, \
+    intent_handler, intent_file_handler
+from mycroft.skills.context import adds_context, removes_context
+from mycroft.messagebus.message import Message
+
 from os.path import abspath, dirname, join
 
 __author__ = 'seanfitz'
diff --git a/mycroft/util/__init__.py b/mycroft/util/__init__.py
--- a/mycroft/util/__init__.py
+++ b/mycroft/util/__init__.py
@@ -15,6 +15,12 @@
 # You should have received a copy of the GNU General Public License
 # along with Mycroft Core.  If not, see <http://www.gnu.org/licenses/>.
 
+# Officially exported methods from this file:
+# play_wav, play_mp3, get_cache_directory,
+# resolve_resource_file, wait_while_speaking
+from mycroft.util.log import getLogger
+from mycroft.util.parse import extract_datetime, extractnumber, normalize
+from mycroft.util.format import nice_number, convert_number
 
 import socket
 import subprocess
@@ -26,7 +32,6 @@
 import time
 from stat import S_ISREG, ST_MTIME, ST_MODE, ST_SIZE
 import psutil
-from mycroft.util.log import getLogger
 from mycroft.util.signal import *
 import mycroft.configuration
 import mycroft.audio

{"golden_diff": "diff --git a/mycroft/__init__.py b/mycroft/__init__.py\n--- a/mycroft/__init__.py\n+++ b/mycroft/__init__.py\n@@ -1,3 +1,9 @@\n+from mycroft.api import Api\n+from mycroft.skills.core import MycroftSkill, FallbackSkill, \\\n+    intent_handler, intent_file_handler\n+from mycroft.skills.context import adds_context, removes_context\n+from mycroft.messagebus.message import Message\n+\n from os.path import abspath, dirname, join\n \n __author__ = 'seanfitz'\ndiff --git a/mycroft/util/__init__.py b/mycroft/util/__init__.py\n--- a/mycroft/util/__init__.py\n+++ b/mycroft/util/__init__.py\n@@ -15,6 +15,12 @@\n # You should have received a copy of the GNU General Public License\n # along with Mycroft Core.  If not, see <http://www.gnu.org/licenses/>.\n \n+# Officially exported methods from this file:\n+# play_wav, play_mp3, get_cache_directory,\n+# resolve_resource_file, wait_while_speaking\n+from mycroft.util.log import getLogger\n+from mycroft.util.parse import extract_datetime, extractnumber, normalize\n+from mycroft.util.format import nice_number, convert_number\n \n import socket\n import subprocess\n@@ -26,7 +32,6 @@\n import time\n from stat import S_ISREG, ST_MTIME, ST_MODE, ST_SIZE\n import psutil\n-from mycroft.util.log import getLogger\n from mycroft.util.signal import *\n import mycroft.configuration\n import mycroft.audio\n", "issue": "Import useful classes in mycroft package\nThis is open for discussion, but I think it is worth importing a few classes/functions in `mycroft/__init__.py` so that skills can do things like:\r\n```Python\r\nfrom mycroft import MycroftSkill  # vs. from mycroft.skills.core import MycroftSkil\r\nclass MySkill(MycroftSkill):\r\n# ...\r\n```\r\n\r\nOr:\r\n```Python\r\nfrom mycroft import FallbackSkill, play_wav\r\nclass MediaFallback(FallbackSkill):\r\n    def handle_fallback(self, message):\r\n        # ...\r\n        play_wav('my_song.wav')\r\n        # ...\n", "before_files": [{"content": "from os.path import abspath, dirname, join\n\n__author__ = 'seanfitz'\n\nMYCROFT_ROOT_PATH = abspath(join(dirname(__file__), '..'))\n", "path": "mycroft/__init__.py"}, {"content": "# Copyright 2016 Mycroft AI, Inc.\n#\n# This file is part of Mycroft Core.\n#\n# Mycroft Core is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Mycroft Core is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Mycroft Core.  If not, see <http://www.gnu.org/licenses/>.\n\n\nimport socket\nimport subprocess\nimport tempfile\nimport time\n\nimport os\nimport os.path\nimport time\nfrom stat import S_ISREG, ST_MTIME, ST_MODE, ST_SIZE\nimport psutil\nfrom mycroft.util.log import getLogger\nfrom mycroft.util.signal import *\nimport mycroft.configuration\nimport mycroft.audio\n\n__author__ = 'jdorleans'\n\nlogger = getLogger(__name__)\n\n\ndef resolve_resource_file(res_name):\n    \"\"\"Convert a resource into an absolute filename.\n\n    Resource names are in the form: 'filename.ext'\n    or 'path/filename.ext'\n\n    The system wil look for ~/.mycroft/res_name first, and\n    if not found will look at /opt/mycroft/res_name,\n    then finally it will look for res_name in the 'mycroft/res'\n    folder of the source code package.\n\n    Example:\n    With mycroft running as the user 'bob', if you called\n        resolve_resource_file('snd/beep.wav')\n    it would return either '/home/bob/.mycroft/snd/beep.wav' or\n    '/opt/mycroft/snd/beep.wav' or '.../mycroft/res/snd/beep.wav',\n    where the '...' is replaced by the path where the package has\n    been installed.\n\n    Args:\n        res_name (str): a resource path/name\n    \"\"\"\n\n    # First look for fully qualified file (e.g. a user setting)\n    if os.path.isfile(res_name):\n        return res_name\n\n    # Now look for ~/.mycroft/res_name (in user folder)\n    filename = os.path.expanduser(\"~/.mycroft/\" + res_name)\n    if os.path.isfile(filename):\n        return filename\n\n    # Next look for /opt/mycroft/res/res_name\n    filename = os.path.expanduser(\"/opt/mycroft/\" + res_name)\n    if os.path.isfile(filename):\n        return filename\n\n    # Finally look for it in the source package\n    filename = os.path.join(os.path.dirname(__file__), '..', 'res', res_name)\n    filename = os.path.abspath(os.path.normpath(filename))\n    if os.path.isfile(filename):\n        return filename\n\n    return None  # Resource cannot be resolved\n\n\ndef play_wav(uri):\n    config = mycroft.configuration.ConfigurationManager.instance()\n    play_cmd = config.get(\"play_wav_cmdline\")\n    play_wav_cmd = str(play_cmd).split(\" \")\n    for index, cmd in enumerate(play_wav_cmd):\n        if cmd == \"%1\":\n            play_wav_cmd[index] = (get_http(uri))\n    return subprocess.Popen(play_wav_cmd)\n\n\ndef play_mp3(uri):\n    config = mycroft.configuration.ConfigurationManager.instance()\n    play_cmd = config.get(\"play_mp3_cmdline\")\n    play_mp3_cmd = str(play_cmd).split(\" \")\n    for index, cmd in enumerate(play_mp3_cmd):\n        if cmd == \"%1\":\n            play_mp3_cmd[index] = (get_http(uri))\n    return subprocess.Popen(play_mp3_cmd)\n\n\ndef record(file_path, duration, rate, channels):\n    if duration > 0:\n        return subprocess.Popen(\n            [\"arecord\", \"-r\", str(rate), \"-c\", str(channels), \"-d\",\n             str(duration), file_path])\n    else:\n        return subprocess.Popen(\n            [\"arecord\", \"-r\", str(rate), \"-c\", str(channels), file_path])\n\n\ndef get_http(uri):\n    return uri.replace(\"https://\", \"http://\")\n\n\ndef remove_last_slash(url):\n    if url and url.endswith('/'):\n        url = url[:-1]\n    return url\n\n\ndef read_stripped_lines(filename):\n    with open(filename, 'r') as f:\n        return [line.strip() for line in f]\n\n\ndef read_dict(filename, div='='):\n    d = {}\n    with open(filename, 'r') as f:\n        for line in f:\n            (key, val) = line.split(div)\n            d[key.strip()] = val.strip()\n    return d\n\n\ndef connected(host=\"8.8.8.8\", port=53, timeout=3):\n    \"\"\"\n    Thanks to 7h3rAm on\n    Host: 8.8.8.8 (google-public-dns-a.google.com)\n    OpenPort: 53/tcp\n    Service: domain (DNS/TCP)\n\n    NOTE:\n    This is no longer in use by this version\n    New method checks for a connection using ConnectionError only when\n    a question is asked\n    \"\"\"\n    try:\n        socket.setdefaulttimeout(timeout)\n        socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))\n        return True\n    except IOError:\n        try:\n            socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(\n                (\"8.8.4.4\", port))\n            return True\n        except IOError:\n            return False\n\n\ndef curate_cache(dir, min_free_percent=5.0):\n    \"\"\"Clear out the directory if needed\n\n    This assumes all the files in the directory can be deleted as freely\n\n    Args:\n        dir (str): directory path that holds cached files\n        min_free_percent (float): percentage (0.0-100.0) of drive to keep free\n    \"\"\"\n\n    # Simpleminded implementation -- keep a certain percentage of the\n    # disk available.\n    # TODO: Would be easy to add more options, like whitelisted files, etc.\n    space = psutil.disk_usage(dir)\n\n    # space.percent = space.used/space.total*100.0\n    percent_free = 100.0-space.percent\n    if percent_free < min_free_percent:\n        # calculate how many bytes we need to delete\n        bytes_needed = (min_free_percent - percent_free) / 100.0 * space.total\n        bytes_needed = int(bytes_needed + 1.0)\n\n        # get all entries in the directory w/ stats\n        entries = (os.path.join(dir, fn) for fn in os.listdir(dir))\n        entries = ((os.stat(path), path) for path in entries)\n\n        # leave only regular files, insert modification date\n        entries = ((stat[ST_MTIME], stat[ST_SIZE], path)\n                   for stat, path in entries if S_ISREG(stat[ST_MODE]))\n\n        # delete files with oldest modification date until space is freed\n        space_freed = 0\n        for moddate, fsize, path in sorted(entries):\n            try:\n                os.remove(path)\n                space_freed += fsize\n            except:\n                pass\n\n            if space_freed > bytes_needed:\n                return  # deleted enough!\n\n\ndef get_cache_directory(domain=None):\n    \"\"\"Get a directory for caching data\n\n    This directory can be used to hold temporary caches of data to\n    speed up performance.  This directory will likely be part of a\n    small RAM disk and may be cleared at any time.  So code that\n    uses these cached files must be able to fallback and regenerate\n    the file.\n\n    Args:\n        domain (str): The cache domain.  Basically just a subdirectory.\n\n    Return:\n        str: a path to the directory where you can cache data\n    \"\"\"\n    config = mycroft.configuration.ConfigurationManager.instance()\n    dir = config.get(\"cache_path\")\n    if not dir:\n        # If not defined, use /tmp/mycroft/cache\n        dir = os.path.join(tempfile.gettempdir(), \"mycroft\", \"cache\")\n    return ensure_directory_exists(dir, domain)\n\n\ndef validate_param(value, name):\n    if not value:\n        raise ValueError(\"Missing or empty %s in mycroft.conf \" % name)\n\n\ndef is_speaking():\n    \"\"\"Determine if Text to Speech is occurring\n\n    Returns:\n        bool: True while still speaking\n    \"\"\"\n    logger.info(\"mycroft.utils.is_speaking() is depreciated, use \"\n                \"mycroft.audio.is_speaking() instead.\")\n    return mycroft.audio.is_speaking()\n\n\ndef wait_while_speaking():\n    \"\"\"Pause as long as Text to Speech is still happening\n\n    Pause while Text to Speech is still happening.  This always pauses\n    briefly to ensure that any preceeding request to speak has time to\n    begin.\n    \"\"\"\n    logger.info(\"mycroft.utils.wait_while_speaking() is depreciated, use \"\n                \"mycroft.audio.wait_while_speaking() instead.\")\n    return mycroft.audio.wait_while_speaking()\n\n\ndef stop_speaking():\n    # TODO: Less hacky approach to this once Audio Manager is implemented\n    # Skills should only be able to stop speech they've initiated\n    logger.info(\"mycroft.utils.stop_speaking() is depreciated, use \"\n                \"mycroft.audio.stop_speaking() instead.\")\n    mycroft.audio.stop_speaking()\n", "path": "mycroft/util/__init__.py"}], "after_files": [{"content": "from mycroft.api import Api\nfrom mycroft.skills.core import MycroftSkill, FallbackSkill, \\\n    intent_handler, intent_file_handler\nfrom mycroft.skills.context import adds_context, removes_context\nfrom mycroft.messagebus.message import Message\n\nfrom os.path import abspath, dirname, join\n\n__author__ = 'seanfitz'\n\nMYCROFT_ROOT_PATH = abspath(join(dirname(__file__), '..'))\n", "path": "mycroft/__init__.py"}, {"content": "# Copyright 2016 Mycroft AI, Inc.\n#\n# This file is part of Mycroft Core.\n#\n# Mycroft Core is free software: you can redistribute it and/or modify\n# it under the terms of the GNU General Public License as published by\n# the Free Software Foundation, either version 3 of the License, or\n# (at your option) any later version.\n#\n# Mycroft Core is distributed in the hope that it will be useful,\n# but WITHOUT ANY WARRANTY; without even the implied warranty of\n# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n# GNU General Public License for more details.\n#\n# You should have received a copy of the GNU General Public License\n# along with Mycroft Core.  If not, see <http://www.gnu.org/licenses/>.\n\n# Officially exported methods from this file:\n# play_wav, play_mp3, get_cache_directory,\n# resolve_resource_file, wait_while_speaking\nfrom mycroft.util.log import getLogger\nfrom mycroft.util.parse import extract_datetime, extractnumber, normalize\nfrom mycroft.util.format import nice_number, convert_number\n\nimport socket\nimport subprocess\nimport tempfile\nimport time\n\nimport os\nimport os.path\nimport time\nfrom stat import S_ISREG, ST_MTIME, ST_MODE, ST_SIZE\nimport psutil\nfrom mycroft.util.signal import *\nimport mycroft.configuration\nimport mycroft.audio\n\n__author__ = 'jdorleans'\n\nlogger = getLogger(__name__)\n\n\ndef resolve_resource_file(res_name):\n    \"\"\"Convert a resource into an absolute filename.\n\n    Resource names are in the form: 'filename.ext'\n    or 'path/filename.ext'\n\n    The system wil look for ~/.mycroft/res_name first, and\n    if not found will look at /opt/mycroft/res_name,\n    then finally it will look for res_name in the 'mycroft/res'\n    folder of the source code package.\n\n    Example:\n    With mycroft running as the user 'bob', if you called\n        resolve_resource_file('snd/beep.wav')\n    it would return either '/home/bob/.mycroft/snd/beep.wav' or\n    '/opt/mycroft/snd/beep.wav' or '.../mycroft/res/snd/beep.wav',\n    where the '...' is replaced by the path where the package has\n    been installed.\n\n    Args:\n        res_name (str): a resource path/name\n    \"\"\"\n\n    # First look for fully qualified file (e.g. a user setting)\n    if os.path.isfile(res_name):\n        return res_name\n\n    # Now look for ~/.mycroft/res_name (in user folder)\n    filename = os.path.expanduser(\"~/.mycroft/\" + res_name)\n    if os.path.isfile(filename):\n        return filename\n\n    # Next look for /opt/mycroft/res/res_name\n    filename = os.path.expanduser(\"/opt/mycroft/\" + res_name)\n    if os.path.isfile(filename):\n        return filename\n\n    # Finally look for it in the source package\n    filename = os.path.join(os.path.dirname(__file__), '..', 'res', res_name)\n    filename = os.path.abspath(os.path.normpath(filename))\n    if os.path.isfile(filename):\n        return filename\n\n    return None  # Resource cannot be resolved\n\n\ndef play_wav(uri):\n    config = mycroft.configuration.ConfigurationManager.instance()\n    play_cmd = config.get(\"play_wav_cmdline\")\n    play_wav_cmd = str(play_cmd).split(\" \")\n    for index, cmd in enumerate(play_wav_cmd):\n        if cmd == \"%1\":\n            play_wav_cmd[index] = (get_http(uri))\n    return subprocess.Popen(play_wav_cmd)\n\n\ndef play_mp3(uri):\n    config = mycroft.configuration.ConfigurationManager.instance()\n    play_cmd = config.get(\"play_mp3_cmdline\")\n    play_mp3_cmd = str(play_cmd).split(\" \")\n    for index, cmd in enumerate(play_mp3_cmd):\n        if cmd == \"%1\":\n            play_mp3_cmd[index] = (get_http(uri))\n    return subprocess.Popen(play_mp3_cmd)\n\n\ndef record(file_path, duration, rate, channels):\n    if duration > 0:\n        return subprocess.Popen(\n            [\"arecord\", \"-r\", str(rate), \"-c\", str(channels), \"-d\",\n             str(duration), file_path])\n    else:\n        return subprocess.Popen(\n            [\"arecord\", \"-r\", str(rate), \"-c\", str(channels), file_path])\n\n\ndef get_http(uri):\n    return uri.replace(\"https://\", \"http://\")\n\n\ndef remove_last_slash(url):\n    if url and url.endswith('/'):\n        url = url[:-1]\n    return url\n\n\ndef read_stripped_lines(filename):\n    with open(filename, 'r') as f:\n        return [line.strip() for line in f]\n\n\ndef read_dict(filename, div='='):\n    d = {}\n    with open(filename, 'r') as f:\n        for line in f:\n            (key, val) = line.split(div)\n            d[key.strip()] = val.strip()\n    return d\n\n\ndef connected(host=\"8.8.8.8\", port=53, timeout=3):\n    \"\"\"\n    Thanks to 7h3rAm on\n    Host: 8.8.8.8 (google-public-dns-a.google.com)\n    OpenPort: 53/tcp\n    Service: domain (DNS/TCP)\n\n    NOTE:\n    This is no longer in use by this version\n    New method checks for a connection using ConnectionError only when\n    a question is asked\n    \"\"\"\n    try:\n        socket.setdefaulttimeout(timeout)\n        socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))\n        return True\n    except IOError:\n        try:\n            socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect(\n                (\"8.8.4.4\", port))\n            return True\n        except IOError:\n            return False\n\n\ndef curate_cache(dir, min_free_percent=5.0):\n    \"\"\"Clear out the directory if needed\n\n    This assumes all the files in the directory can be deleted as freely\n\n    Args:\n        dir (str): directory path that holds cached files\n        min_free_percent (float): percentage (0.0-100.0) of drive to keep free\n    \"\"\"\n\n    # Simpleminded implementation -- keep a certain percentage of the\n    # disk available.\n    # TODO: Would be easy to add more options, like whitelisted files, etc.\n    space = psutil.disk_usage(dir)\n\n    # space.percent = space.used/space.total*100.0\n    percent_free = 100.0-space.percent\n    if percent_free < min_free_percent:\n        # calculate how many bytes we need to delete\n        bytes_needed = (min_free_percent - percent_free) / 100.0 * space.total\n        bytes_needed = int(bytes_needed + 1.0)\n\n        # get all entries in the directory w/ stats\n        entries = (os.path.join(dir, fn) for fn in os.listdir(dir))\n        entries = ((os.stat(path), path) for path in entries)\n\n        # leave only regular files, insert modification date\n        entries = ((stat[ST_MTIME], stat[ST_SIZE], path)\n                   for stat, path in entries if S_ISREG(stat[ST_MODE]))\n\n        # delete files with oldest modification date until space is freed\n        space_freed = 0\n        for moddate, fsize, path in sorted(entries):\n            try:\n                os.remove(path)\n                space_freed += fsize\n            except:\n                pass\n\n            if space_freed > bytes_needed:\n                return  # deleted enough!\n\n\ndef get_cache_directory(domain=None):\n    \"\"\"Get a directory for caching data\n\n    This directory can be used to hold temporary caches of data to\n    speed up performance.  This directory will likely be part of a\n    small RAM disk and may be cleared at any time.  So code that\n    uses these cached files must be able to fallback and regenerate\n    the file.\n\n    Args:\n        domain (str): The cache domain.  Basically just a subdirectory.\n\n    Return:\n        str: a path to the directory where you can cache data\n    \"\"\"\n    config = mycroft.configuration.ConfigurationManager.instance()\n    dir = config.get(\"cache_path\")\n    if not dir:\n        # If not defined, use /tmp/mycroft/cache\n        dir = os.path.join(tempfile.gettempdir(), \"mycroft\", \"cache\")\n    return ensure_directory_exists(dir, domain)\n\n\ndef validate_param(value, name):\n    if not value:\n        raise ValueError(\"Missing or empty %s in mycroft.conf \" % name)\n\n\ndef is_speaking():\n    \"\"\"Determine if Text to Speech is occurring\n\n    Returns:\n        bool: True while still speaking\n    \"\"\"\n    logger.info(\"mycroft.utils.is_speaking() is depreciated, use \"\n                \"mycroft.audio.is_speaking() instead.\")\n    return mycroft.audio.is_speaking()\n\n\ndef wait_while_speaking():\n    \"\"\"Pause as long as Text to Speech is still happening\n\n    Pause while Text to Speech is still happening.  This always pauses\n    briefly to ensure that any preceeding request to speak has time to\n    begin.\n    \"\"\"\n    logger.info(\"mycroft.utils.wait_while_speaking() is depreciated, use \"\n                \"mycroft.audio.wait_while_speaking() instead.\")\n    return mycroft.audio.wait_while_speaking()\n\n\ndef stop_speaking():\n    # TODO: Less hacky approach to this once Audio Manager is implemented\n    # Skills should only be able to stop speech they've initiated\n    logger.info(\"mycroft.utils.stop_speaking() is depreciated, use \"\n                \"mycroft.audio.stop_speaking() instead.\")\n    mycroft.audio.stop_speaking()\n", "path": "mycroft/util/__init__.py"}]}