-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'oa-next' into oa-master
- Loading branch information
Showing
41 changed files
with
1,322 additions
and
766 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,3 @@ | ||
# OA files | ||
mind/**/cache | ||
|
||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
Prerequisite: homebrew (https://brew.sh) | ||
|
||
# Basic System Dependencies | ||
|
||
## Install Python3 | ||
|
||
`brew install python` | ||
|
||
# Python Modules | ||
|
||
`pip3 install requests` | ||
|
||
# Open Assistant Modules | ||
|
||
## Speech Recognition | ||
|
||
### gstreamer | ||
|
||
note the options: python3 support, no python2 | ||
|
||
`brew install gst-python --with-python --without-python@2` | ||
|
||
support for autoaudiosrc | ||
|
||
`brew install gst-plugins-good` | ||
|
||
### sphinx | ||
|
||
Build tools | ||
|
||
`brew install autoconf libtool automake swig` | ||
|
||
sphinxbase | ||
|
||
`git clone https://github.com/cmusphinx/sphinxbase.git` | ||
`./autogen.sh && make install` | ||
|
||
pocketsphinx | ||
|
||
`git clone https://github.com/cmusphinx/pocketsphinx.git` | ||
`./autogen.sh && make install` |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
# OpenAssistant 0.04 | ||
# 2016 General Public License V3 | ||
# By Andrew Vavrek, Clayton G. Hobbs, Jezra | ||
|
||
import logging | ||
logging.basicConfig(level=logging.INFO) | ||
logger = logging.getLogger(__name__) | ||
|
||
|
||
if __name__ == '__main__': | ||
|
||
import sys, os | ||
|
||
# Parse command-line options, | ||
# use `Config` to load mind configuration | ||
# command-line overrides config file | ||
from .util.args import _parser as arg_parser | ||
args = arg_parser(sys.argv[1:]) | ||
if args.debug: | ||
logging.root.setLevel(logging.DEBUG) | ||
logger.debug("Arguments: {args}".format(args=args)) | ||
|
||
|
||
# A configured Assistant | ||
if args.agents_dir is not None: | ||
agents_path = os.path.realpath(args.agents_dir) | ||
logger.info("Agents Path: %s" % agents_path) | ||
sys.path.insert(0, agents_path) | ||
|
||
if args.agent is not None: | ||
import importlib | ||
A = importlib.import_module(args.agent) | ||
logger.info("Loading {}".format(A)) | ||
a = A.__call__() | ||
|
||
|
||
# | ||
# TODO: remove | ||
# | ||
|
||
from gi.repository import GObject | ||
|
||
# Initialize Gobject Threads | ||
GObject.threads_init() | ||
|
||
# Create Main Loop | ||
main_loop = GObject.MainLoop() | ||
|
||
# Handle Signal Interrupts | ||
import signal | ||
signal.signal(signal.SIGINT, signal.SIG_DFL) | ||
|
||
# Start Main Loop | ||
try: | ||
main_loop.run() | ||
|
||
except Exception as e: | ||
print(e) | ||
main_loop.quit() | ||
sys.exit() | ||
|
||
# | ||
# End Questionable dependencies | ||
# |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
from itertools import groupby | ||
|
||
from core import oa | ||
|
||
from abilities.core import info | ||
from abilities.interact import say | ||
|
||
def isNum(s): | ||
return s.replace('.', '').isdigit() | ||
|
||
def expr2str(): | ||
""" Convert a numerical expression into a string. """ | ||
ret = '' | ||
info(oa.sys.calc_opers.values()) | ||
for k, g in groupby(oa.sys.expr, lambda x: ((x in oa.sys.calc_opers.values()) and 1) or 2): | ||
l=list(g) | ||
if len(l) > 1: | ||
if k == 1: | ||
raise Exception('two opers') | ||
else: | ||
sr='(' + l[0] | ||
for x in l[1:]: | ||
if isNum(x): | ||
sr += '+' + x | ||
else: | ||
# 'hundreds, thousands so on' | ||
sr += x | ||
ret += sr + ')' | ||
else: | ||
ret += l[0] | ||
return ret | ||
|
||
def add2expr(s): | ||
# Check for calculator. Move to a numbers definition file. | ||
# For numbers, add sum operator. | ||
oa.sys.expr.append(s) | ||
|
||
def calculate(): | ||
ret = expr2str() | ||
info(oa.sys.expr) | ||
info('expr=' + ret) | ||
try: | ||
say(eval(ret)) | ||
except: | ||
say('Error. Wrong expression. ' + ret) | ||
# Clear the expression. | ||
oa.sys.expr = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import threading | ||
|
||
from core import oa, queue, Stub | ||
from core.util import isCallable, bytes2gb | ||
|
||
|
||
""" CORE FUNCTIONS """ | ||
|
||
def thread_name(): | ||
""" Return the current thread name. """ | ||
return threading.current_thread().name.split(' ')[0] | ||
|
||
def current_part(): | ||
""" Return the part name which is associated with the current thread. """ | ||
name = thread_name() | ||
ret = oa.core.parts.get(name, None) | ||
if ret is None: | ||
err = '%s Error: Cannot find a related part' %name | ||
info(err) | ||
raise Exception(err) | ||
return ret | ||
|
||
def call_function(func_or_value): | ||
""" A helper function. For Stubs, call `perform()`. | ||
For other functions, execute a direct call. """ | ||
if isCallable(func_or_value): | ||
if isinstance(func_or_value, Stub): | ||
return func_or_value.perform() | ||
else: | ||
return func_or_value() | ||
else: | ||
return func_or_value | ||
|
||
def info(*args, **kwargs): | ||
""" Display information to the screen. """ | ||
string = "[{}]".format(thread_name()) + ' ' | ||
if args: | ||
string += ' '.join([str(v) for v in args]) + '\n' | ||
if kwargs: | ||
string += '\n'.join([' %s: %s' %(str(k), str(v)) for k, v in kwargs.items()]) | ||
if oa.console and not oa.core.finished.is_set(): | ||
oa.console.wire_in.put(string) | ||
else: | ||
print(string) | ||
|
||
def get(part = None, timeout = .1): | ||
""" Get a message from the wire. If there is no part found, take a message from the current wire input thread. (No parameters. Thread safe) """ | ||
if part is None: | ||
part = current_part() | ||
while not oa.core.finished.is_set(): | ||
try: | ||
return part.wire_in.get(timeout = timeout) | ||
except queue.Empty: | ||
pass | ||
raise Exception('Open Assistant closed.') | ||
|
||
def put(part, value): | ||
""" Put a message on the wire. """ | ||
oa[part].wire_in.put(value) | ||
|
||
def empty(part = None): | ||
""" Remove all messages from `part.wire_in` input queue. | ||
(No parameters. Thread safe) """ | ||
if part is None: | ||
part = current_part() | ||
try: | ||
while True: | ||
part.wire_in.get(False) | ||
except queue.Empty: | ||
pass | ||
|
||
def quit_app(): | ||
quit(0) | ||
|
||
def close(): | ||
""" Close Open Assistant. """ | ||
quit() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import keyboard | ||
|
||
from core import oa | ||
from abilities.core import call_function, put | ||
from abilities.system import find_file | ||
|
||
|
||
def answer(text): | ||
""" Save the return function parameter and switch to previous mind. """ | ||
text = text.lower() | ||
func = oa.mind.user_choices.get(text, None) | ||
if func: | ||
call_function(func) | ||
oa.mind.switch_back() | ||
|
||
def yes_no(msg, func): | ||
""" Receive a yes or no answer from the user. """ | ||
say(msg) | ||
user_answer('yes_no', {'yes': func}) | ||
|
||
def user_answer(mind_for_answer, choices): | ||
""" Within any `mind` we will receive a one word answer command (voice, file path, etc, any) from the user. """ | ||
mind(mind_for_answer, 0) # No history. | ||
oa.mind.user_choices = choices | ||
|
||
def say(text): | ||
""" Text to speech using the `oa.audio.say` defined function. """ | ||
text = call_function(text) | ||
oa.sys.last_say = text | ||
|
||
# Put message into voice. | ||
put('voice', text) | ||
|
||
def keys(s): | ||
""" Hook and simulate keyboard events. """ | ||
if '+' in s: | ||
keyboard.press_and_release(s) | ||
else: | ||
keyboard.write(s) | ||
|
||
def play(fname): | ||
""" Play a sound file. """ | ||
put('sound', find_file(fname)) | ||
|
||
def mind(name, history = 1): | ||
""" Switch the current mind to `name`. """ | ||
oa.mind.set_mind(name, history) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
from core import oa | ||
|
||
from abilities.core import info, put | ||
from abilities.interact import say | ||
from abilities.system import find_file, sys_exec | ||
|
||
def activate(s): | ||
""" Activate a specific window. """ | ||
if oa.sys.os == 'win': | ||
w = WindowMgr() | ||
w.find_window_wildcard('.*' + s + '.*') | ||
w.set_foreground() | ||
else: | ||
raise Exception('`Activate` is unsupported.') | ||
|
||
def close(s): | ||
""" Close an application by a window or process name. | ||
A partial window name will work, for example: 'note*'. """ | ||
say('- Unable to close %s for now.' %s) | ||
pass | ||
|
||
def volume(move = 2): | ||
""" Change volume level. | ||
Positive `move`: Volume Up | ||
Negative `move`: Volume Down | ||
""" | ||
if oa.sys.os == 'win': | ||
# Up by 2. | ||
if move > 0: | ||
# Volume up. | ||
key = chr(175) | ||
else: | ||
move =- move | ||
key = chr(174) | ||
|
||
while move > 0: | ||
wshell.SendKeys(key) | ||
move -= 2 | ||
|
||
elif oa.sys.os in ('linux','mac'): | ||
if move > 0: | ||
sys_exec('pamixer --increase %d' %move) | ||
else: | ||
sys_exec('pamixer --decrease %d' %(-move)) | ||
else: | ||
info('Unknown operating system.') | ||
|
||
def mute(mute = True): | ||
""" Mute or unmute speakers. """ | ||
if oa.sys.os == 'win': | ||
wshell.SendKeys(chr(173)) | ||
elif oa.sys.os in ('linux', 'mac'): | ||
sys_exec('amixer set Master %smute' % (((not mute) and 'un') or '')) | ||
else: | ||
info('Unknown operating system.') | ||
|
||
def unmute(): | ||
""" Unmute speakers. """ | ||
mute(False) |
Oops, something went wrong.