mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-08-26 09:59:23 +00:00
Compare commits
18 Commits
snapshot11
...
snapshot12
Author | SHA1 | Date | |
---|---|---|---|
89985cf6bd | |||
cc4568b968 | |||
d7132ecaf6 | |||
720e0e6c24 | |||
9763d8b26c | |||
f512267b6d | |||
241de0264d | |||
5c7bce1258 | |||
e24543be12 | |||
422c780d0c | |||
![]() |
96a592a4f9 | ||
d4bf33ca6d | |||
e5b33160e0 | |||
c8d83ed9e7 | |||
16b2e16614 | |||
221d1d413b | |||
4391e3d3de | |||
c5e9e97c84 |
@@ -2,6 +2,14 @@
|
||||
|
||||
## changes in this version
|
||||
|
||||
* TWBlue can open a Tweet or user directly in Twitter. There is a new option in the context menu for people and tweet buffers, and also, the shortcut control+win+alt+Enter will open the focused item in Twitter.
|
||||
* Some keystrokes were remapped in the Windows 10 Keymap:
|
||||
* Read location of a tweet: Ctrl+Win+G. ([#177](https://github.com/manuelcortez/TWBlue/pull/177))
|
||||
* Open global settings dialogue: Ctrl+Win+Alt+O.
|
||||
* Mute/unmute current session: Control + Windows + Alt + M.
|
||||
* Fixed an error that was preventing TWBlue to load the direct messages buffer if an user who sent a message has been deleted.
|
||||
* Added support for playing audios posted in [AnyAudio.net](http://anyaudio.net) directly from TWBlue. Thanks to [Sam Tupy](http://www.samtupy.com/)
|
||||
* Custom buffer ordering will not be reset every time the application restarts after an account setting has been modified.
|
||||
* When adding or removing an user from a list, it is possible to press enter in the focused list instead of having to search for the "add" or "delete" button.
|
||||
* Quoted and long tweets are displayed properly in the sent tweets buffer after being send. ([#253](https://github.com/manuelcortez/TWBlue/issues/253))
|
||||
* Fixed an issue that was making the list manager keystroke unable to be shown in the keystroke editor. Now the keystroke is listed properly. ([#260](https://github.com/manuelcortez/TWBlue/issues/260))
|
||||
@@ -14,7 +22,6 @@
|
||||
* There is a new soundpack, called FreakyBlue (Thanks to [Andre Louis](https://twitter.com/FreakyFwoof)) as a new option in TWBlue. This pack can be the default in the next stable, so users can take a look and share their opinion in snapshot versions. ([#247](https://github.com/manuelcortez/TWBlue/issues/247))
|
||||
* There is a new option in the help menu that allows you to visit the soundpacks section in the TWBlue website. ([#247](https://github.com/manuelcortez/TWBlue/issues/247))
|
||||
* When reading location of a geotagged tweet, it will be translated for users of other languages. ([#251](https://github.com/manuelcortez/TWBlue/pull/251))
|
||||
* In the Windows 10 Keymap, the action to read location of a tweet has been remapped to Ctrl+Win+G. ([#177](https://github.com/manuelcortez/TWBlue/pull/177))
|
||||
* When there are no more items to retrieve in direct messages and people buffers, a message will announce it.
|
||||
* Fixed an issue reported by some users that was making them unable to load more items in their direct messages.
|
||||
* It is possible to add a tweet to the likes buffer from the menu bar again.
|
||||
|
@@ -21,6 +21,11 @@ chardet
|
||||
urllib3
|
||||
youtube-dl
|
||||
python-vlc
|
||||
pywin32
|
||||
pypiwin32
|
||||
certifi
|
||||
backports.functools_lru_cache
|
||||
git+https://github.com/manuelcortez/twython
|
||||
git+https://github.com/manuelcortez/libloader
|
||||
git+https://github.com/manuelcortez/platform_utils
|
||||
git+https://github.com/manuelcortez/accessible_output2
|
||||
git+https://github.com/chrisnorman7/sound_lib
|
@@ -1,33 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import ctypes
|
||||
import os
|
||||
import types
|
||||
from platform_utils import paths
|
||||
|
||||
def load_library(libname, cdll=False):
|
||||
if paths.is_frozen():
|
||||
libfile = os.path.join(paths.embedded_data_path(), 'accessible_output2', 'lib', libname)
|
||||
else:
|
||||
libfile = os.path.join(paths.module_path(), 'lib', libname)
|
||||
if cdll:
|
||||
return ctypes.cdll[libfile]
|
||||
else:
|
||||
return ctypes.windll[libfile]
|
||||
|
||||
def get_output_classes():
|
||||
from . import outputs
|
||||
module_type = types.ModuleType
|
||||
classes = [m.output_class for m in outputs.__dict__.values() if type(m) == module_type and hasattr(m, 'output_class')]
|
||||
return sorted(classes, key=lambda c: c.priority)
|
||||
|
||||
def find_datafiles():
|
||||
import os
|
||||
import platform
|
||||
from glob import glob
|
||||
import accessible_output2
|
||||
if platform.system() != 'Windows':
|
||||
return []
|
||||
path = os.path.join(accessible_output2.__path__[0], 'lib', '*.dll')
|
||||
results = glob(path)
|
||||
dest_dir = os.path.join('accessible_output2', 'lib')
|
||||
return [(dest_dir, results)]
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,20 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import platform
|
||||
if platform.system() == 'Windows':
|
||||
from . import nvda
|
||||
from . import jaws
|
||||
from . import sapi5
|
||||
from . import window_eyes
|
||||
from . import system_access
|
||||
from . import dolphin
|
||||
from . import pc_talker
|
||||
#import sapi4
|
||||
|
||||
if platform.system() == 'Darwin':
|
||||
from . import voiceover
|
||||
from . import say
|
||||
|
||||
if platform.system() == 'Linux':
|
||||
from . import e_speak
|
||||
|
||||
from . import auto
|
@@ -1,42 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import accessible_output2
|
||||
from .base import Output, OutputError
|
||||
|
||||
class Auto(Output):
|
||||
|
||||
def __init__(self):
|
||||
output_classes = accessible_output2.get_output_classes()
|
||||
self.outputs = []
|
||||
for output in output_classes:
|
||||
try:
|
||||
a=output()
|
||||
self.outputs.append(a)
|
||||
except:
|
||||
pass
|
||||
|
||||
def get_first_available_output(self):
|
||||
for output in self.outputs:
|
||||
if output.is_active():
|
||||
return output
|
||||
return None
|
||||
|
||||
def speak(self, *args, **kwargs):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
output.speak(*args, **kwargs)
|
||||
|
||||
def braille(self, *args, **kwargs):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
output.braille(*args, **kwargs)
|
||||
|
||||
def output(self, *args, **kwargs):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
output.speak(*args, **kwargs)
|
||||
output.braille(*args, **kwargs)
|
||||
|
||||
def is_system_output(self):
|
||||
output = self.get_first_available_output()
|
||||
if output:
|
||||
return output.is_system_output()
|
@@ -1,47 +0,0 @@
|
||||
from accessible_output2 import load_library
|
||||
import platform
|
||||
|
||||
class OutputError(Exception):
|
||||
pass
|
||||
|
||||
class Output(object):
|
||||
name = "Unnamed Output"
|
||||
lib32 = None
|
||||
lib64 = None
|
||||
argtypes = {}
|
||||
cdll = False
|
||||
priority = 100
|
||||
system_output = False
|
||||
|
||||
def __init__(self):
|
||||
self.is_32bit = platform.architecture()[0] == "32bit"
|
||||
if self.lib32 and self.is_32bit:
|
||||
self.lib = load_library(self.lib32, cdll=self.cdll)
|
||||
elif self.lib64:
|
||||
self.lib = load_library(self.lib64, cdll=self.cdll)
|
||||
else:
|
||||
self.lib = None
|
||||
if self.lib is not None:
|
||||
for func in self.argtypes:
|
||||
try:
|
||||
getattr(self.lib, func).argtypes = self.argtypes[func]
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def output(self, text, **options):
|
||||
output = False
|
||||
if self.speak(text, **options):
|
||||
output = True
|
||||
if self.braille(text, **options):
|
||||
output = True
|
||||
if not output:
|
||||
raise RuntimeError("Output %r does not have any method defined to output" % self)
|
||||
|
||||
def is_system_output(self):
|
||||
return self.system_output
|
||||
|
||||
def speak(self, **optiont):
|
||||
return False
|
||||
|
||||
def braille(self, *args, **options):
|
||||
return False
|
@@ -1,33 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import ctypes
|
||||
|
||||
from .base import Output
|
||||
|
||||
class Dolphin (Output):
|
||||
"""Supports dolphin products."""
|
||||
|
||||
name = 'Dolphin'
|
||||
lib32 = 'dolapi.dll'
|
||||
argtypes = {
|
||||
'DolAccess_Command': (ctypes.c_wchar_p, ctypes.c_int, ctypes.c_int),
|
||||
'DolAccess_Action': (ctypes.c_int,),
|
||||
}
|
||||
|
||||
def speak(self, text, interrupt=0):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
#If we don't call this, the API won't let us speak.
|
||||
if self.is_active():
|
||||
self.lib.DolAccess_Command(text, (len(text)*2)+2, 1)
|
||||
|
||||
def silence(self):
|
||||
self.lib.DolAccess_Action(141)
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
return self.lib.DolAccess_GetSystem() in (1, 4, 8)
|
||||
except:
|
||||
return False
|
||||
|
||||
output_class = Dolphin
|
@@ -1,31 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from .base import Output
|
||||
|
||||
try:
|
||||
import espeak.core
|
||||
except:
|
||||
raise RuntimeError("Cannot find espeak.core. Please install python-espeak")
|
||||
|
||||
class ESpeak(Output):
|
||||
"""Speech output supporting ESpeak on Linux
|
||||
Note this requires python-espeak to be installed
|
||||
This can be done on Debian distros by using apt-get install python-espeak
|
||||
Or through this tarball: https://launchpad.net/python-espeak
|
||||
"""
|
||||
name = "Linux ESpeak"
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
import espeak.core
|
||||
except:
|
||||
return False
|
||||
return True
|
||||
|
||||
def speak(self, text, interrupt = 0):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
espeak.core.synth(text)
|
||||
def silence(self):
|
||||
espeak.core.cancel()
|
||||
|
||||
output_class = ESpeak
|
@@ -1,34 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import win32gui
|
||||
from libloader.com import load_com
|
||||
import pywintypes
|
||||
|
||||
from .base import Output, OutputError
|
||||
|
||||
class Jaws (Output):
|
||||
"""Output supporting the Jaws for Windows screen reader."""
|
||||
|
||||
name = 'jaws'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super (Jaws, self).__init__(*args, **kwargs)
|
||||
try:
|
||||
self.object = load_com("FreedomSci.JawsApi", "jfwapi")
|
||||
except pywintypes.com_error:
|
||||
raise OutputError
|
||||
|
||||
def braille(self, text, **options):
|
||||
# HACK: replace " with ', Jaws doesn't seem to understand escaping them with \
|
||||
text = text.replace('"', "'")
|
||||
self.object.RunFunction("BrailleString(\"%s\")" % text)
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
self.object.SayString(' %s' % text, interrupt)
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
return self.object.SayString('',0) == True or win32gui.FindWindow("JFWUI2", "JAWS") != 0
|
||||
except:
|
||||
return False
|
||||
|
||||
output_class = Jaws
|
@@ -1,37 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import platform
|
||||
import ctypes
|
||||
|
||||
from platform_utils import paths
|
||||
from libloader import load_library
|
||||
from .base import Output
|
||||
|
||||
class NVDA(Output):
|
||||
"""Supports The NVDA screen reader"""
|
||||
name = "NVDA"
|
||||
lib32 = 'nvdaControllerClient32.dll'
|
||||
lib64 = 'nvdaControllerClient64.dll'
|
||||
argtypes = {
|
||||
'nvdaController_brailleMessage': (ctypes.c_wchar_p,),
|
||||
'nvdaController_speakText': (ctypes.c_wchar_p,),
|
||||
}
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
return self.lib.nvdaController_testIfRunning() == 0
|
||||
except:
|
||||
return False
|
||||
|
||||
def braille(self, text, **options):
|
||||
self.lib.nvdaController_brailleMessage(text)
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
self.lib.nvdaController_speakText(text)
|
||||
|
||||
def silence(self):
|
||||
self.lib.nvdaController_cancelSpeech()
|
||||
|
||||
output_class = NVDA
|
@@ -1,24 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import ctypes
|
||||
from .base import Output
|
||||
|
||||
class PCTalker(Output):
|
||||
lib32 = 'pctkusr.dll'
|
||||
lib64 = 'pctkusr64.dll'
|
||||
cdll = True
|
||||
argtypes = {
|
||||
'PCTKPRead': (ctypes.c_char_p, ctypes.c_int, ctypes.c_int)
|
||||
}
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
self.lib.PCTKPRead(text.encode('cp932', 'replace'), 0, 1)
|
||||
|
||||
def silence(self):
|
||||
self.lib.PCTKVReset()
|
||||
|
||||
def is_active(self):
|
||||
return self.lib.PCTKStatus() != 0
|
||||
|
||||
output_class = PCTalker
|
@@ -1,143 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from builtins import range
|
||||
from libloader.com import load_com
|
||||
from .base import Output
|
||||
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class Sapi4(Output):
|
||||
|
||||
name = 'sapi4'
|
||||
priority = 102
|
||||
|
||||
def __init__(self):
|
||||
sapi4 = load_com("{EEE78591-FE22-11D0-8BEF-0060081841DE}")
|
||||
self._voiceNo = sapi4.Find(0)
|
||||
sapi4.Select(self._voiceNo)
|
||||
sapi4.Speak(" ")
|
||||
self.__object = sapi4
|
||||
self._voice_list = self._available_voices()
|
||||
|
||||
def _set_capabilities(self):
|
||||
sapi4 = self.__object
|
||||
try:
|
||||
sapi4.Pitch = sapi4.Pitch
|
||||
self._min_pitch = sapi4.MinPitch
|
||||
self._max_pitch = sapi4.MaxPitch
|
||||
self._has_pitch = True
|
||||
except:
|
||||
self._min_pitch = 0
|
||||
self._max_pitch = 0
|
||||
self._has_pitch = False
|
||||
try:
|
||||
sapi4.Speed = sapi4.Speed
|
||||
self._min_rate = sapi4.MinSpeed
|
||||
self._max_rate = sapi4.MaxSpeed
|
||||
self._has_rate = True
|
||||
except:
|
||||
self._min_rate = 0
|
||||
self._max_rate = 0
|
||||
self._has_rate = False
|
||||
try:
|
||||
sapi4.VolumeLeft = sapi4.VolumeLeft
|
||||
self._min_volume = sapi4.MinVolumeLeft
|
||||
self._max_volume = sapi4.MaxVolumeLeft
|
||||
self._has_volume = True
|
||||
except:
|
||||
self._min_volume = 0
|
||||
self._max_volume = 0
|
||||
self._has_volume = False
|
||||
|
||||
def _available_voices(self):
|
||||
voice_list = []
|
||||
for voice_no in range(1, self.__object.CountEngines):
|
||||
voice_list.append(self.__object.ModeName(voice_no))
|
||||
return voice_list
|
||||
|
||||
@property
|
||||
def available_voices(self):
|
||||
return self._voice_list
|
||||
|
||||
def list_voices(self):
|
||||
return self.available_voices
|
||||
|
||||
def get_voice(self):
|
||||
return self.__object.ModeName(self._voice_no)
|
||||
|
||||
def set_voice(self, value):
|
||||
self._voice_no = self.list_voices().index(value) + 1
|
||||
self.__object.Select(self._voice_no)
|
||||
self.silence()
|
||||
self.__object.Speak(" ")
|
||||
self._set_capabilities()
|
||||
|
||||
def get_pitch(self):
|
||||
if self.has_pitch:
|
||||
return self.__object.Pitch
|
||||
|
||||
def set_pitch(self, value):
|
||||
if self.has_pitch:
|
||||
self.__object.Pitch = value
|
||||
|
||||
def get_rate(self):
|
||||
if self.has_rate:
|
||||
return self.__object.Speed
|
||||
|
||||
def set_rate(self, value):
|
||||
if self.has_rate:
|
||||
self.__object.Speed = value
|
||||
|
||||
def get_volume(self):
|
||||
if self.has_volume:
|
||||
return self.__object.VolumeLeft
|
||||
|
||||
def set_volume(self, value):
|
||||
if self.has_volume:
|
||||
self.__object.VolumeLeft = value
|
||||
|
||||
@property
|
||||
def has_pitch(self):
|
||||
return self._has_pitch
|
||||
|
||||
@property
|
||||
def has_rate(self):
|
||||
return self._has_rate
|
||||
|
||||
@property
|
||||
def has_volume(self):
|
||||
return self._has_volume
|
||||
|
||||
@property
|
||||
def min_pitch(self):
|
||||
return self._min_pitch
|
||||
|
||||
@property
|
||||
def max_pitch(self):
|
||||
return self._max_pitch
|
||||
|
||||
@property
|
||||
def min_rate(self):
|
||||
return self._min_rate
|
||||
|
||||
@property
|
||||
def max_rate(self):
|
||||
return self._max_rate
|
||||
|
||||
@property
|
||||
def min_volume(self):
|
||||
return self._min_volume
|
||||
|
||||
@property
|
||||
def max_volume(self):
|
||||
return self._max_volume
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
self.__object.Speak(text)
|
||||
|
||||
def silence(self):
|
||||
self.__object.AudioReset()
|
||||
|
||||
output_class = Sapi4
|
@@ -1,95 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from collections import OrderedDict
|
||||
from libloader.com import load_com
|
||||
from .base import Output, OutputError
|
||||
import pywintypes
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
SVSFDefault = 0
|
||||
SVSFlagsAsync = 1
|
||||
SVSFPurgeBeforeSpeak = 2
|
||||
SVSFIsFilename = 4
|
||||
SVSFIsXML = 8
|
||||
SVSFIsNotXML = 16
|
||||
SVSFPersistXML = 32
|
||||
|
||||
class SAPI5(Output):
|
||||
has_volume = True
|
||||
has_rate = True
|
||||
has_pitch = True
|
||||
min_pitch = -10
|
||||
max_pitch = 10
|
||||
min_rate = -10
|
||||
max_rate = 10
|
||||
min_volume = 0
|
||||
max_volume = 100
|
||||
name = "sapi5"
|
||||
priority = 101
|
||||
system_output = True
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
self.object = load_com("SAPI.SPVoice")
|
||||
self._voices = self._available_voices()
|
||||
except pywintypes.com_error:
|
||||
raise OutputError
|
||||
self._pitch = 0
|
||||
|
||||
def _available_voices(self):
|
||||
_voices = OrderedDict()
|
||||
for v in self.object.GetVoices():
|
||||
_voices[v.GetDescription()] = v
|
||||
return _voices
|
||||
|
||||
def list_voices(self):
|
||||
return list(self._voices.keys())
|
||||
|
||||
def get_voice(self):
|
||||
return self.object.Voice.GetDescription()
|
||||
|
||||
def set_voice(self, value):
|
||||
log.debug("Setting SAPI5 voice to \"%s\"" % value)
|
||||
self.object.Voice = self._voices[value]
|
||||
# For some reason SAPI5 does not reset audio after changing the voice
|
||||
# By setting the audio device after changing voices seems to fix this
|
||||
# This was noted from information at:
|
||||
# http://lists.nvaccess.org/pipermail/nvda-dev/2011-November/022464.html
|
||||
self.object.AudioOutput = self.object.AudioOutput
|
||||
|
||||
def get_pitch(self):
|
||||
return self._pitch
|
||||
|
||||
def set_pitch(self, value):
|
||||
log.debug("Setting pitch to %d" % value)
|
||||
self._pitch = value
|
||||
|
||||
def get_rate(self):
|
||||
return self.object.Rate
|
||||
|
||||
def set_rate(self, value):
|
||||
log.debug("Setting rate to %d" % value)
|
||||
self.object.Rate = value
|
||||
|
||||
def get_volume(self):
|
||||
return self.object.Volume
|
||||
|
||||
def set_volume(self, value):
|
||||
self.object.Volume = value
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
# We need to do the pitch in XML here
|
||||
textOutput = "<pitch absmiddle=\"%d\">%s</pitch>" % (round(self._pitch), text.replace("<", "<"))
|
||||
self.object.Speak(textOutput, SVSFlagsAsync | SVSFIsXML)
|
||||
|
||||
def silence(self):
|
||||
self.object.Speak("", SVSFlagsAsync | SVSFPurgeBeforeSpeak)
|
||||
|
||||
def is_active(self):
|
||||
if self.object:
|
||||
return True
|
||||
return False
|
||||
|
||||
output_class = SAPI5
|
@@ -1,21 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
from .base import Output
|
||||
|
||||
class AppleSay(Output):
|
||||
"""Speech output supporting the Apple Say subsystem."""
|
||||
name = 'Apple Say'
|
||||
def __init__(self, voice = 'Alex', rate = '300'):
|
||||
self.voice = voice
|
||||
self.rate = rate
|
||||
super(AppleSay, self).__init__()
|
||||
def is_active(self):
|
||||
return not os.system('which say')
|
||||
def speak(self, text, interrupt = 0):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
os.system('say -v %s -r %s "%s" &' % (self.voice, self.rate, text))
|
||||
def silence(self):
|
||||
os.system('killall say')
|
||||
|
||||
output_class = AppleSay
|
@@ -1,29 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import ctypes
|
||||
from .base import Output
|
||||
|
||||
class SystemAccess (Output):
|
||||
"""Supports System Access and System Access Mobile"""
|
||||
|
||||
name = "System Access"
|
||||
lib32 = 'saapi32.dll'
|
||||
argtypes = {
|
||||
'SA_BrlShowTextW': (ctypes.c_wchar_p,),
|
||||
'SA_SayW': (ctypes.c_wchar_p,),
|
||||
}
|
||||
priority = 99
|
||||
|
||||
def braille(self, text, **options):
|
||||
self.lib.SA_BrlShowTextW(text)
|
||||
|
||||
def speak(self, text, interrupt=False):
|
||||
if self.is_active():
|
||||
self.dll.SA_SayW(str(text))
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
return self.dll.SA_IsRunning()
|
||||
except:
|
||||
return False
|
||||
|
||||
output_class = SystemAccess
|
@@ -1 +0,0 @@
|
||||
from __future__ import absolute_import
|
@@ -1,33 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
import win32gui
|
||||
from libloader.com import load_com
|
||||
from .base import Output, OutputError
|
||||
import pywintypes
|
||||
|
||||
class WindowEyes (Output):
|
||||
"""Speech output supporting the WindowEyes screen reader"""
|
||||
|
||||
name = 'Window-Eyes'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(WindowEyes, self).__init__(*args, **kwargs)
|
||||
try:
|
||||
self.object = load_com("gwspeak.speak")
|
||||
except pywintypes.com_error:
|
||||
raise OutputError
|
||||
|
||||
def speak(self, text, interrupt=0):
|
||||
if interrupt:
|
||||
self.silence()
|
||||
self.object.SpeakString(text)
|
||||
|
||||
def silence (self):
|
||||
self.object.Silence()
|
||||
|
||||
def is_active(self):
|
||||
try:
|
||||
return win32gui.FindWindow("GWMExternalControl", "External Control") != 0
|
||||
except:
|
||||
return False
|
||||
|
||||
output_class = WindowEyes
|
@@ -8,7 +8,7 @@ if snapshot == False:
|
||||
update_url = 'https://twblue.es/updates/stable.php'
|
||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
||||
else:
|
||||
version = "11"
|
||||
version = "12"
|
||||
update_url = 'https://twblue.es/updates/snapshot.php'
|
||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
||||
authors = [u"Manuel Cortéz", u"José Manuel Delicado"]
|
||||
|
@@ -33,5 +33,12 @@ def convert_soundcloud (url):
|
||||
def convert_youtube_long (url):
|
||||
return youtube_utils.get_video_url(url)
|
||||
|
||||
@matches_url ('http://anyaudio.net/listen')
|
||||
def convert_anyaudio(url):
|
||||
values = url.split("audio=")
|
||||
if len(values) != 2:
|
||||
raise TypeError('%r is not streamable' % url)
|
||||
return "http://anyaudio.net/audiodownload?audio=%s" % (values[1],)
|
||||
|
||||
def convert_generic_audio(url):
|
||||
return url
|
||||
|
@@ -128,7 +128,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
tweetsList = []
|
||||
tweet_id = tweet["id"]
|
||||
message = None
|
||||
if tweet.has_key("message"):
|
||||
if "message" in tweet:
|
||||
message = tweet["message"]
|
||||
try:
|
||||
tweet = self.session.twitter.show_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended")
|
||||
@@ -241,7 +241,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
if self.name[:-9] in self.session.settings["other_buffers"]["timelines"]:
|
||||
self.session.settings["other_buffers"]["timelines"].remove(self.name[:-9])
|
||||
self.session.settings.write()
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
@@ -254,7 +254,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-9] in self.session.settings["other_buffers"]["favourites_timelines"]:
|
||||
self.session.settings["other_buffers"]["favourites_timelines"].remove(self.name[:-9])
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
self.session.settings.write()
|
||||
return True
|
||||
@@ -344,6 +344,8 @@ class baseBufferController(baseBuffers.buffer):
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove)
|
||||
if hasattr(menu, "openInBrowser"):
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.open_in_browser, menuitem=menu.openInBrowser)
|
||||
if pos != 0:
|
||||
self.buffer.PopupMenu(menu, pos)
|
||||
else:
|
||||
@@ -377,7 +379,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
|
||||
|
||||
def get_tweet(self):
|
||||
if self.session.db[self.name][self.buffer.list.get_selected()].has_key("retweeted_status"):
|
||||
if "retweeted_status" in self.session.db[self.name][self.buffer.list.get_selected()]:
|
||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]["retweeted_status"]
|
||||
else:
|
||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
|
||||
@@ -392,7 +394,7 @@ class baseBufferController(baseBuffers.buffer):
|
||||
tweet = self.get_right_tweet()
|
||||
screen_name = tweet["user"]["screen_name"]
|
||||
id = tweet["id"]
|
||||
twishort_enabled = tweet.has_key("twishort")
|
||||
twishort_enabled = "twishort" in tweet
|
||||
users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name")
|
||||
ids = utils.get_all_mentioned(tweet, self.session.db, field="id_str")
|
||||
# Build the window title
|
||||
@@ -489,9 +491,9 @@ class baseBufferController(baseBuffers.buffer):
|
||||
|
||||
def _retweet_with_comment(self, tweet, id, comment=''):
|
||||
# If quoting a retweet, let's quote the original tweet instead the retweet.
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if "retweeted_status" in tweet:
|
||||
tweet = tweet["retweeted_status"]
|
||||
if tweet.has_key("full_text"):
|
||||
if "full_text" in tweet:
|
||||
comments = tweet["full_text"]
|
||||
else:
|
||||
comments = tweet["text"]
|
||||
@@ -627,6 +629,12 @@ class baseBufferController(baseBuffers.buffer):
|
||||
except IndexError: pass
|
||||
return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"])
|
||||
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
tweet = self.get_tweet()
|
||||
output.speak(_(u"Opening item in web browser..."))
|
||||
url = "https://twitter.com/{screen_name}/status/{tweet_id}".format(screen_name=tweet["user"]["screen_name"], tweet_id=tweet["id"])
|
||||
webbrowser.open(url)
|
||||
|
||||
class directMessagesController(baseBufferController):
|
||||
|
||||
def get_more_items(self):
|
||||
@@ -719,11 +727,14 @@ class directMessagesController(baseBufferController):
|
||||
elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||
output.speak(_(u"{0} new direct messages.").format(number_of_items,))
|
||||
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
output.speak(_(u"This action is not supported in the buffer yet."))
|
||||
|
||||
class sentDirectMessagesController(directMessagesController):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(sentDirectMessagesController, self).__init__(*args, **kwargs)
|
||||
if self.session.db.has_key("sent_direct_messages") == False:
|
||||
if ("sent_direct_messages" in self.session.db) == False:
|
||||
self.session.db["sent_direct_messages"] = {"items": []}
|
||||
|
||||
def get_more_items(self):
|
||||
@@ -770,7 +781,7 @@ class listBufferController(baseBufferController):
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-5] in self.session.settings["other_buffers"]["lists"]:
|
||||
self.session.settings["other_buffers"]["lists"].remove(self.name[:-5])
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
self.session.settings.write()
|
||||
return True
|
||||
@@ -805,7 +816,7 @@ class peopleBufferController(baseBufferController):
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-10] in self.session.settings["other_buffers"]["followers_timelines"]:
|
||||
self.session.settings["other_buffers"]["followers_timelines"].remove(self.name[:-10])
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
self.session.settings.write()
|
||||
return True
|
||||
@@ -819,7 +830,7 @@ class peopleBufferController(baseBufferController):
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.name[:-8] in self.session.settings["other_buffers"]["friends_timelines"]:
|
||||
self.session.settings["other_buffers"]["friends_timelines"].remove(self.name[:-8])
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
self.session.settings.write()
|
||||
return True
|
||||
@@ -951,6 +962,8 @@ class peopleBufferController(baseBufferController):
|
||||
# widgetUtils.connect_event(menu, widgetUtils.MENU, self.lists, menuitem=menu.lists)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
|
||||
if hasattr(menu, "openInBrowser"):
|
||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.open_in_browser, menuitem=menu.openInBrowser)
|
||||
if pos != 0:
|
||||
self.buffer.PopupMenu(menu, pos)
|
||||
else:
|
||||
@@ -969,6 +982,12 @@ class peopleBufferController(baseBufferController):
|
||||
elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||
output.speak(_(u"{0} new followers.").format(number_of_items))
|
||||
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
tweet = self.get_tweet()
|
||||
output.speak(_(u"Opening item in web browser..."))
|
||||
url = "https://twitter.com/{screen_name}".format(screen_name=tweet["screen_name"])
|
||||
webbrowser.open(url)
|
||||
|
||||
class searchBufferController(baseBufferController):
|
||||
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||
# starts stream every 3 minutes.
|
||||
@@ -1000,7 +1019,7 @@ class searchBufferController(baseBufferController):
|
||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||
self.session.settings.write()
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
@@ -1051,7 +1070,7 @@ class searchPeopleBufferController(peopleBufferController):
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.function = function
|
||||
if self.kwargs.has_key("page") == False:
|
||||
if ("page" in self.kwargs) == False:
|
||||
self.kwargs["page"] = 1
|
||||
|
||||
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=True):
|
||||
@@ -1115,7 +1134,7 @@ class searchPeopleBufferController(peopleBufferController):
|
||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||
self.session.settings.write()
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
@@ -1188,7 +1207,7 @@ class trendsBufferController(baseBuffers.buffer):
|
||||
if self.name[:-3] in self.session.settings["other_buffers"]["trending_topic_buffers"]:
|
||||
self.session.settings["other_buffers"]["trending_topic_buffers"].remove(self.name[:-3])
|
||||
self.session.settings.write()
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
@@ -1243,6 +1262,9 @@ class trendsBufferController(baseBuffers.buffer):
|
||||
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
|
||||
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
output.speak(_(u"This action is not supported in the buffer, yet."))
|
||||
|
||||
class conversationBufferController(searchBufferController):
|
||||
|
||||
def start_stream(self, start=False, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||
@@ -1288,7 +1310,7 @@ class conversationBufferController(searchBufferController):
|
||||
else:
|
||||
dlg = widgetUtils.YES
|
||||
if dlg == widgetUtils.YES:
|
||||
if self.session.db.has_key(self.name):
|
||||
if self.name in self.session.db:
|
||||
self.session.db.pop(self.name)
|
||||
return True
|
||||
elif dlg == widgetUtils.NO:
|
||||
|
@@ -30,7 +30,7 @@ class filter(object):
|
||||
if i["name"] in langs:
|
||||
langcodes.append(i["code"])
|
||||
d = dict(in_buffer=self.buffer.name, word=term, regexp=regexp, in_lang=lang_option, languages=langcodes, if_word_exists=contains, allow_rts=allow_rts, allow_quotes=allow_quotes, allow_replies=allow_replies)
|
||||
if self.buffer.session.settings["filters"].has_key(title):
|
||||
if title in self.buffer.session.settings["filters"]:
|
||||
return commonMessageDialogs.existing_filter()
|
||||
self.buffer.session.settings["filters"][title] = d
|
||||
self.buffer.session.settings.write()
|
||||
|
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import platform
|
||||
system = platform.system()
|
||||
import application
|
||||
@@ -8,15 +9,15 @@ import arrow
|
||||
if system == "Windows":
|
||||
from update import updater
|
||||
from wxUI import (view, dialogs, commonMessageDialogs, sysTrayIcon)
|
||||
import settings
|
||||
from . import settings
|
||||
from extra import SoundsTutorial, ocr
|
||||
import keystrokeEditor
|
||||
from keyboard_handler.wx_handler import WXKeyboardHandler
|
||||
import userActionsController
|
||||
import trendingTopics
|
||||
import user
|
||||
import listsController
|
||||
import filterController
|
||||
from . import userActionsController
|
||||
from . import trendingTopics
|
||||
from . import user
|
||||
from . import listsController
|
||||
from . import filterController
|
||||
# from issueReporter import issueReporter
|
||||
elif system == "Linux":
|
||||
from gtkUI import (view, commonMessageDialogs)
|
||||
@@ -24,7 +25,7 @@ from sessions.twitter import utils, compose
|
||||
from sessionmanager import manager, sessionManager
|
||||
|
||||
from controller.buffers import baseBuffers, twitterBuffers
|
||||
import messages
|
||||
from . import messages
|
||||
import sessions
|
||||
from sessions.twitter import session as session_
|
||||
from pubsub import pub
|
||||
@@ -392,7 +393,7 @@ class Controller(object):
|
||||
def set_buffer_positions(self, session):
|
||||
"Sets positions for buffers if values exist in the database."
|
||||
for i in self.buffers:
|
||||
if i.account == session.db["user_name"] and session.db.has_key(i.name+"_pos") and hasattr(i.buffer,'list'):
|
||||
if i.account == session.db["user_name"] and i.name+"_pos" in session.db and hasattr(i.buffer,'list'):
|
||||
i.buffer.list.select_item(session.db[str(i.name+"_pos")])
|
||||
|
||||
def logout_account(self, session_id):
|
||||
@@ -655,6 +656,9 @@ class Controller(object):
|
||||
sessions.sessions[item].shelve()
|
||||
if system == "Windows":
|
||||
self.systrayIcon.RemoveIcon()
|
||||
pidpath = os.path.join(os.getenv("temp"), "{}.pid".format(application.name))
|
||||
if os.path.exists(pidpath):
|
||||
os.remove(pidpath)
|
||||
widgetUtils.exit_application()
|
||||
|
||||
def follow(self, *args, **kwargs):
|
||||
@@ -808,6 +812,11 @@ class Controller(object):
|
||||
non_tweet = buffer.get_formatted_message()
|
||||
msg = messages.viewTweet(non_tweet, [], False)
|
||||
|
||||
def view_in_browser(self, *args, **kwargs):
|
||||
buffer = self.get_current_buffer()
|
||||
if hasattr(buffer, "open_in_browser"):
|
||||
buffer.open_in_browser()
|
||||
|
||||
def open_favs_timeline(self, *args, **kwargs):
|
||||
self.open_timeline(default="favourites")
|
||||
|
||||
@@ -1563,7 +1572,7 @@ class Controller(object):
|
||||
output.speak(_(u"Invalid buffer"))
|
||||
return
|
||||
tweet = buffer.get_tweet()
|
||||
if tweet.has_key("entities") == False or tweet["entities"].has_key("media") == False:
|
||||
if ("entities" in tweet) == False or ("media" in tweet["entities"]) == False:
|
||||
output.speak(_(u"This tweet doesn't contain images"))
|
||||
return
|
||||
if len(tweet["entities"]["media"]) > 1:
|
||||
|
@@ -1,7 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import re
|
||||
import platform
|
||||
import attach
|
||||
from . import attach
|
||||
import arrow
|
||||
import languageHandler
|
||||
system = platform.system()
|
||||
@@ -206,25 +207,25 @@ class viewTweet(basicTweet):
|
||||
text = ""
|
||||
for i in xrange(0, len(tweetList)):
|
||||
# tweets with message keys are longer tweets, the message value is the full messaje taken from twishort.
|
||||
if tweetList[i].has_key("message") and tweetList[i]["is_quote_status"] == False:
|
||||
if "message" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
|
||||
value = "message"
|
||||
else:
|
||||
value = "full_text"
|
||||
if tweetList[i].has_key("retweeted_status") and tweetList[i]["is_quote_status"] == False:
|
||||
if tweetList[i].has_key("message") == False:
|
||||
if "retweeted_status" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
|
||||
if ("message" in tweetList[i]) == False:
|
||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["full_text"])
|
||||
else:
|
||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i][value])
|
||||
else:
|
||||
text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i][value])
|
||||
# tweets with extended_entities could include image descriptions.
|
||||
if tweetList[i].has_key("extended_entities") and tweetList[i]["extended_entities"].has_key("media"):
|
||||
if "extended_entities" in tweetList[i] and "media" in tweetList[i]["extended_entities"]:
|
||||
for z in tweetList[i]["extended_entities"]["media"]:
|
||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||
image_description.append(z["ext_alt_text"])
|
||||
if tweetList[i].has_key("retweeted_status") and tweetList[i]["retweeted_status"].has_key("extended_entities") and tweetList[i]["retweeted_status"]["extended_entities"].has_key("media"):
|
||||
if "retweeted_status" in tweetList[i] and "extended_entities" in tweetList[i]["retweeted_status"] and "media" in tweetList[i]["retweeted_status"]["extended_entities"]:
|
||||
for z in tweetList[i]["retweeted_status"]["extended_entities"]["media"]:
|
||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||
image_description.append(z["ext_alt_text"])
|
||||
# set rt and likes counters.
|
||||
rt_count = str(tweet["retweet_count"])
|
||||
@@ -234,25 +235,25 @@ class viewTweet(basicTweet):
|
||||
original_date = arrow.get(tweet["created_at"], "ddd MMM DD H:m:s Z YYYY", locale="en")
|
||||
date = original_date.replace(seconds=utc_offset).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
|
||||
if text == "":
|
||||
if tweet.has_key("message"):
|
||||
if "message" in tweet:
|
||||
value = "message"
|
||||
else:
|
||||
value = "full_text"
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if tweet.has_key("message") == False:
|
||||
if "retweeted_status" in tweet:
|
||||
if ("message" in tweet) == False:
|
||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["full_text"])
|
||||
else:
|
||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet[value])
|
||||
else:
|
||||
text = tweet[value]
|
||||
text = self.clear_text(text)
|
||||
if tweet.has_key("extended_entities") and tweet["extended_entities"].has_key("media"):
|
||||
if "extended_entities" in tweet and "media" in tweet["extended_entities"]:
|
||||
for z in tweet["extended_entities"]["media"]:
|
||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||
image_description.append(z["ext_alt_text"])
|
||||
if tweet.has_key("retweeted_status") and tweet["retweeted_status"].has_key("extended_entities") and tweet["retweeted_status"]["extended_entities"].has_key("media"):
|
||||
if "retweeted_status" in tweet and "extended_entities" in tweet["retweeted_status"] and "media" in tweet["retweeted_status"]["extended_entities"]:
|
||||
for z in tweet["retweeted_status"]["extended_entities"]["media"]:
|
||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||
image_description.append(z["ext_alt_text"])
|
||||
self.message = message.viewTweet(text, rt_count, favs_count, source.decode("utf-8"), date)
|
||||
self.message.set_title(len(text))
|
||||
|
@@ -18,7 +18,7 @@ import config_utils
|
||||
log = logging.getLogger("Settings")
|
||||
import keys
|
||||
from collections import OrderedDict
|
||||
from platform_utils.autostart import windows as autostart_windows
|
||||
from mysc import autostart as autostart_windows
|
||||
|
||||
class globalSettingsController(object):
|
||||
def __init__(self):
|
||||
@@ -211,7 +211,7 @@ class accountSettingsController(globalSettingsController):
|
||||
else:
|
||||
self.config["general"]["retweet_mode"] = "comment"
|
||||
buffers_list = self.dialog.buffers.get_list()
|
||||
if set(self.config["general"]["buffer_order"]) != set(buffers_list) or buffers_list != self.config["general"]["buffer_order"]:
|
||||
if buffers_list != self.config["general"]["buffer_order"]:
|
||||
self.needs_restart = True
|
||||
self.config["general"]["buffer_order"] = buffers_list
|
||||
self.config["reporting"]["speech_reporting"] = self.dialog.get_value("reporting", "speech_reporting")
|
||||
@@ -291,10 +291,14 @@ class accountSettingsController(globalSettingsController):
|
||||
all_buffers['muted']=_(u"Muted users")
|
||||
list_buffers = []
|
||||
hidden_buffers=[]
|
||||
for i in all_buffers.keys():
|
||||
if i in self.config["general"]["buffer_order"]:
|
||||
all_buffers_keys = all_buffers.keys()
|
||||
# Check buffers shown first.
|
||||
for i in self.config["general"]["buffer_order"]:
|
||||
if i in all_buffers_keys:
|
||||
list_buffers.append((i, all_buffers[i], True))
|
||||
else:
|
||||
# This second pass will retrieve all hidden buffers.
|
||||
for i in all_buffers_keys:
|
||||
if i not in self.config["general"]["buffer_order"]:
|
||||
hidden_buffers.append((i, all_buffers[i], False))
|
||||
list_buffers.extend(hidden_buffers)
|
||||
return list_buffers
|
||||
|
@@ -71,7 +71,7 @@ class userActionsController(object):
|
||||
|
||||
def ignore_client(self, user):
|
||||
tweet = self.buffer.get_right_tweet()
|
||||
if tweet.has_key("sender"):
|
||||
if "sender" in tweet:
|
||||
output.speak(_(u"You can't ignore direct messages"))
|
||||
return
|
||||
client = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||
|
@@ -16,10 +16,11 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
from __future__ import absolute_import
|
||||
import widgetUtils
|
||||
import wx_ui
|
||||
import wx_transfer_dialogs
|
||||
import transfer
|
||||
from . import wx_ui
|
||||
from . import wx_transfer_dialogs
|
||||
from . import transfer
|
||||
import output
|
||||
import tempfile
|
||||
import sound
|
||||
|
@@ -1,9 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import logging
|
||||
from utils import convert_bytes
|
||||
from .utils import convert_bytes
|
||||
from pubsub import pub
|
||||
log = logging.getLogger("extra.AudioUploader.transfer")
|
||||
from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncoderMonitor
|
||||
@@ -75,9 +76,9 @@ class Upload(object):
|
||||
data = self.response.json()
|
||||
except:
|
||||
return _("Error in file upload: {0}").format(self.data.content,)
|
||||
if data.has_key("url") and data["url"] != "0":
|
||||
if "url" in data and data["url"] != "0":
|
||||
return data["url"]
|
||||
elif data.has_key("error") and data["error"] != "0":
|
||||
elif "error" in data and data["error"] != "0":
|
||||
return data["error"]
|
||||
else:
|
||||
return _("Error in file upload: {0}").format(self.data.content,)
|
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import wx
|
||||
from utils import *
|
||||
from .utils import *
|
||||
import widgetUtils
|
||||
|
||||
class UploadDialog(widgetUtils.BaseDialog):
|
||||
|
@@ -1 +1,2 @@
|
||||
from soundsTutorial import soundsTutorial
|
||||
from __future__ import absolute_import
|
||||
from .soundsTutorial import soundsTutorial
|
||||
|
@@ -1,15 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import platform
|
||||
import widgetUtils
|
||||
import os
|
||||
import paths
|
||||
import logging
|
||||
log = logging.getLogger("extra.SoundsTutorial.soundsTutorial")
|
||||
import soundsTutorial_constants
|
||||
from . import soundsTutorial_constants
|
||||
if platform.system() == "Windows":
|
||||
import wx_ui as UI
|
||||
from . import wx_ui as UI
|
||||
elif platform.system() == "Linux":
|
||||
import gtk_ui as UI
|
||||
from . import gtk_ui as UI
|
||||
|
||||
class soundsTutorial(object):
|
||||
def __init__(self, sessionObject):
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#-*- coding: utf-8 -*-
|
||||
import reverse_sort
|
||||
from __future__ import absolute_import
|
||||
#-*- coding: utf-8 -*-
|
||||
from . import reverse_sort
|
||||
import application
|
||||
actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")),
|
||||
("create_timeline", _(u"User timeline buffer created.")),
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import spellchecker
|
||||
from __future__ import absolute_import
|
||||
from . import spellchecker
|
||||
import platform
|
||||
if platform.system() == "Windows":
|
||||
from wx_ui import *
|
||||
from .wx_ui import *
|
@@ -1,14 +1,15 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import logging
|
||||
import wx_ui
|
||||
from . import wx_ui
|
||||
import widgetUtils
|
||||
import output
|
||||
import config
|
||||
import languageHandler
|
||||
import enchant
|
||||
import paths
|
||||
import twitterFilter
|
||||
from . import twitterFilter
|
||||
from enchant.checker import SpellChecker
|
||||
from enchant.errors import DictNotFoundError
|
||||
from enchant import tokenize
|
||||
@@ -52,7 +53,7 @@ class spellChecker(object):
|
||||
|
||||
def check(self):
|
||||
try:
|
||||
self.checker.next()
|
||||
next(self.checker)
|
||||
textToSay = _(u"Misspelled word: %s") % (self.checker.word,)
|
||||
context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10))
|
||||
self.dialog.set_title(textToSay)
|
||||
|
@@ -1,2 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import completion, settings
|
||||
from __future__ import absolute_import
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import completion, settings
|
@@ -1,7 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import output
|
||||
import storage
|
||||
import wx_menu
|
||||
from . import storage
|
||||
from . import wx_menu
|
||||
|
||||
class autocompletionUsers(object):
|
||||
def __init__(self, window, session_id):
|
||||
|
@@ -1,7 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import storage
|
||||
from __future__ import absolute_import
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import storage
|
||||
import widgetUtils
|
||||
import wx_manage
|
||||
from . import wx_manage
|
||||
from wxUI import commonMessageDialogs
|
||||
|
||||
class autocompletionManage(object):
|
||||
|
@@ -1,8 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import storage
|
||||
from __future__ import absolute_import
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import storage
|
||||
import widgetUtils
|
||||
import wx_settings
|
||||
import manage
|
||||
from . import wx_settings
|
||||
from . import manage
|
||||
import output
|
||||
from mysc.thread_utils import call_threaded
|
||||
|
||||
|
@@ -1,2 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import OCRSpace
|
||||
from __future__ import absolute_import
|
||||
# -*- coding: utf-8 -*-
|
||||
from . import OCRSpace
|
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import translator
|
||||
from __future__ import absolute_import
|
||||
from . import translator
|
||||
import platform
|
||||
if platform.system() == "Windows":
|
||||
import wx_ui as gui
|
||||
from . import wx_ui as gui
|
||||
|
@@ -16,7 +16,26 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
import translator
|
||||
from __future__ import absolute_import
|
||||
# -*- coding: utf-8 -*-
|
||||
############################################################
|
||||
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
from . import translator
|
||||
import wx
|
||||
from wxUI.dialogs import baseDialog
|
||||
|
||||
|
@@ -1,15 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" This module contains some bugfixes for packages used in TWBlue."""
|
||||
from __future__ import absolute_import
|
||||
import sys
|
||||
import fix_arrow # A few new locales for Three languages in arrow.
|
||||
import fix_urllib3_warnings # Avoiding some SSL warnings related to Twython.
|
||||
import fix_win32com
|
||||
import fix_requests #fix cacert.pem location for TWBlue binary copies
|
||||
from . import fix_arrow # A few new locales for Three languages in arrow.
|
||||
from . import fix_libloader # Regenerates comcache properly.
|
||||
from . import fix_urllib3_warnings # Avoiding some SSL warnings related to Twython.
|
||||
from . import fix_win32com
|
||||
from . import fix_requests #fix cacert.pem location for TWBlue binary copies
|
||||
def setup():
|
||||
fix_arrow.fix()
|
||||
if hasattr(sys, "frozen"):
|
||||
fix_win32com.fix()
|
||||
fix_requests.fix(True)
|
||||
fix_libloader.fix()
|
||||
else:
|
||||
fix_requests.fix(False)
|
||||
fix_urllib3_warnings.fix()
|
36
src/fixes/fix_libloader.py
Normal file
36
src/fixes/fix_libloader.py
Normal file
@@ -0,0 +1,36 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import win32com
|
||||
import paths
|
||||
win32com.__gen_path__=paths.com_path()
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.join(win32com.__gen_path__, "."))
|
||||
from win32com.client import gencache
|
||||
from pywintypes import com_error
|
||||
from libloader import com
|
||||
|
||||
fixed=False
|
||||
|
||||
def patched_getmodule(modname):
|
||||
mod=__import__(modname)
|
||||
return sys.modules[modname]
|
||||
|
||||
def load_com(*names):
|
||||
global fixed
|
||||
if fixed==False:
|
||||
gencache._GetModule=patched_getmodule
|
||||
com.prepare_gencache()
|
||||
fixed=True
|
||||
result = None
|
||||
for name in names:
|
||||
try:
|
||||
result = gencache.EnsureDispatch(name)
|
||||
break
|
||||
except com_error:
|
||||
continue
|
||||
if result is None:
|
||||
raise com_error("Unable to load any of the provided com objects.")
|
||||
return result
|
||||
|
||||
def fix():
|
||||
com.load_com = load_com
|
@@ -33,4 +33,5 @@ list_manager = string(default="control+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
||||
update_buffer = string(default="control+win+shift+u")
|
||||
ocr_image = string(default="win+alt+o")
|
||||
ocr_image = string(default="win+alt+o")
|
||||
open_in_browser = string(default="alt+control+win+return")
|
@@ -52,4 +52,5 @@ list_manager = string(default="control+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
||||
update_buffer = string(default="control+win+shift+u")
|
||||
ocr_image = string(default="win+alt+o")
|
||||
ocr_image = string(default="win+alt+o")
|
||||
open_in_browser = string(default="alt+control+win+return")
|
@@ -39,7 +39,7 @@ copy_to_clipboard = string(default="alt+win+shift+c")
|
||||
add_to_list = string(default="alt+win+a")
|
||||
remove_from_list = string(default="alt+win+shift+a")
|
||||
toggle_buffer_mute = string(default="alt+win+shift+m")
|
||||
toggle_session_mute = string(default="alt+win+m")
|
||||
toggle_session_mute = string(default="control+alt+win+m")
|
||||
toggle_autoread = string(default="alt+win+e")
|
||||
search = string(default="alt+win+-")
|
||||
edit_keystrokes = string(default="alt+win+k")
|
||||
@@ -50,7 +50,8 @@ view_reverse_geocode = string(default="alt+win+shift+g")
|
||||
get_trending_topics = string(default="control+win+t")
|
||||
check_for_updates = string(default="alt+win+u")
|
||||
list_manager = string(default="alt+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
configuration = string(default="control+win+alt+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
||||
update_buffer = string(default="control+alt+shift+u")
|
||||
ocr_image = string(default="win+alt+o")
|
||||
ocr_image = string(default="win+alt+o")
|
||||
open_in_browser = string(default="alt+control+win+return")
|
@@ -54,4 +54,5 @@ check_for_updates = string(default="control+win+u")
|
||||
list_manager = string(default="control+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
||||
update_buffer = string(default="control+win+shift+u")
|
||||
update_buffer = string(default="control+win+shift+u")
|
||||
open_in_browser = string(default="alt+control+win+return")
|
@@ -55,4 +55,5 @@ list_manager = string(default="control+win+shift+l")
|
||||
configuration = string(default="control+win+o")
|
||||
accountConfiguration = string(default="control+win+shift+o")
|
||||
update_buffer = string(default="control+win+shift+u")
|
||||
ocr_image = string(default="win+alt+o")
|
||||
ocr_image = string(default="win+alt+o")
|
||||
open_in_browser = string(default="alt+control+win+return")
|
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from builtins import object
|
||||
import application
|
||||
import platform
|
||||
import exceptions
|
||||
|
@@ -1 +1,2 @@
|
||||
from keystrokeEditor import KeystrokeEditor
|
||||
from __future__ import absolute_import
|
||||
from .keystrokeEditor import KeystrokeEditor
|
@@ -1,8 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import widgetUtils
|
||||
import config
|
||||
import wx_ui
|
||||
import constants
|
||||
from . import wx_ui
|
||||
from . import constants
|
||||
from pubsub import pub
|
||||
|
||||
class KeystrokeEditor(object):
|
||||
|
@@ -32,7 +32,7 @@ class keystrokeEditorDialog(baseDialog.BaseWXDialog):
|
||||
selection = self.keys.get_selected()
|
||||
self.keys.clear()
|
||||
for i in keystrokes:
|
||||
if actions.has_key(i) == False:
|
||||
if (i in actions) == False:
|
||||
continue
|
||||
action = actions[i]
|
||||
self.actions.append(i)
|
||||
|
@@ -1,7 +0,0 @@
|
||||
from .libloader import *
|
||||
|
||||
__version__ = 0.1
|
||||
__author__ = 'Christopher Toth <q@q-continuum.net>'
|
||||
__doc__ = """
|
||||
Quickly and easily load shared libraries from various platforms. Also includes a libloader.com module for loading com modules on Windows.
|
||||
"""
|
@@ -1,35 +0,0 @@
|
||||
from pywintypes import com_error
|
||||
import win32com
|
||||
import paths
|
||||
win32com.__gen_path__=paths.com_path()
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.join(win32com.__gen_path__, "."))
|
||||
from win32com.client import gencache
|
||||
fixed=False
|
||||
|
||||
def prepare_gencache():
|
||||
gencache.is_readonly = False
|
||||
gencache.GetGeneratePath()
|
||||
|
||||
def patched_getmodule(modname):
|
||||
mod=__import__(modname)
|
||||
return sys.modules[modname]
|
||||
|
||||
def load_com(*names):
|
||||
global fixed
|
||||
if fixed==False:
|
||||
gencache._GetModule=patched_getmodule
|
||||
prepare_gencache()
|
||||
fixed=True
|
||||
result = None
|
||||
for name in names:
|
||||
try:
|
||||
result = gencache.EnsureDispatch(name)
|
||||
break
|
||||
except com_error:
|
||||
continue
|
||||
if result is None:
|
||||
raise com_error("Unable to load any of the provided com objects.")
|
||||
return result
|
||||
|
@@ -1,56 +0,0 @@
|
||||
import ctypes
|
||||
import collections
|
||||
import platform
|
||||
import os
|
||||
|
||||
TYPES = {
|
||||
'Linux': {
|
||||
'loader': ctypes.CDLL,
|
||||
'functype': ctypes.CFUNCTYPE,
|
||||
'prefix': 'lib',
|
||||
'extension': '.so'
|
||||
},
|
||||
'Darwin': {
|
||||
'loader': ctypes.CDLL,
|
||||
'functype': ctypes.CFUNCTYPE,
|
||||
'prefix': 'lib',
|
||||
'extension': '.dylib'
|
||||
},
|
||||
}
|
||||
if platform.system() == 'Windows':
|
||||
TYPES['Windows'] = {
|
||||
'loader': ctypes.WinDLL,
|
||||
'functype': ctypes.WINFUNCTYPE,
|
||||
'prefix': "",
|
||||
'extension': '.dll'
|
||||
}
|
||||
|
||||
class LibraryLoadError(OSError): pass
|
||||
|
||||
def load_library(library, x86_path='.', x64_path='.', *args, **kwargs):
|
||||
lib = find_library_path(library, x86_path=x86_path, x64_path=x64_path)
|
||||
loaded = _do_load(str(lib), *args, **kwargs)
|
||||
if loaded is not None:
|
||||
return loaded
|
||||
raise LibraryLoadError('unable to load %r. Provided library path: %r' % (library, lib))
|
||||
|
||||
def _do_load(file, *args, **kwargs):
|
||||
loader = TYPES[platform.system()]['loader']
|
||||
return loader(file, *args, **kwargs)
|
||||
|
||||
def find_library_path(libname, x86_path='.', x64_path='.'):
|
||||
libname = '%s%s' % (TYPES[platform.system()]['prefix'], libname)
|
||||
if platform.architecture()[0] == '64bit':
|
||||
path = os.path.join(x64_path, libname)
|
||||
else:
|
||||
path = os.path.join(x86_path, libname)
|
||||
ext = get_library_extension()
|
||||
path = '%s%s' % (path, ext)
|
||||
return os.path.abspath(path)
|
||||
|
||||
|
||||
def get_functype():
|
||||
return TYPES[platform.system()]['functype']
|
||||
|
||||
def get_library_extension():
|
||||
return TYPES[platform.system()]['extension']
|
25
src/main.py
25
src/main.py
@@ -1,5 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import platform
|
||||
from win32com.client import GetObject
|
||||
|
||||
""" there are lots of things not implemented for Gtk+ yet.
|
||||
We've started this effort 1 Apr 2015 so it isn't fully functional. We will remove the ifs statements when are no needed"""
|
||||
|
||||
@@ -86,6 +88,7 @@ def setup():
|
||||
if hasattr(sm.view, "destroy"):
|
||||
sm.view.destroy()
|
||||
del sm
|
||||
check_pid()
|
||||
r = mainController.Controller()
|
||||
r.view.show()
|
||||
r.do_work()
|
||||
@@ -102,4 +105,26 @@ def donation():
|
||||
webbrowser.open_new_tab(_("https://twblue.es/donate"))
|
||||
config.app["app-settings"]["donation_dialog_displayed"] = True
|
||||
|
||||
def is_running(pid):
|
||||
"Check if the process with ID pid is running. Adapted from https://stackoverflow.com/a/568589"
|
||||
WMI = GetObject('winmgmts:')
|
||||
processes = WMI.InstancesOf('Win32_Process')
|
||||
return [process.Properties_('ProcessID').Value for process in processes if process.Properties_('ProcessID').Value == pid]
|
||||
|
||||
def check_pid():
|
||||
"Insures that only one copy of the application is running at a time."
|
||||
pidpath = os.path.join(os.getenv("temp"), "{}.pid".format(application.name))
|
||||
if os.path.exists(pidpath):
|
||||
with open(pidpath) as fin:
|
||||
pid = int(fin.read())
|
||||
if is_running(pid):
|
||||
# Display warning dialog
|
||||
commonMessageDialogs.common_error(_(u"{0} is already running. Close the other instance before starting this one. If you're sure that {0} isn't running, try deleting the file at {1}. If you're unsure of how to do this, contact the {0} developers.").format(application.name, pidpath))
|
||||
sys.exit(1)
|
||||
else:
|
||||
commonMessageDialogs.dead_pid()
|
||||
# Write the new PID
|
||||
with open(pidpath,"w") as cam:
|
||||
cam.write(str(os.getpid()))
|
||||
|
||||
setup()
|
||||
|
@@ -1 +1,2 @@
|
||||
import widgets
|
||||
from __future__ import absolute_import
|
||||
from . import widgets
|
@@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" A cross platform notification system.
|
||||
Under Linux, the wx.NotificationMessage does not show a notification on the taskbar, so we decided to use dbus for showing notifications for linux and wx for Windows."""
|
||||
from __future__ import absolute_import
|
||||
import platform
|
||||
|
||||
notify = None
|
||||
@@ -8,10 +9,10 @@ notify = None
|
||||
def setup():
|
||||
global notify
|
||||
if platform.system() == "Windows":
|
||||
import windows
|
||||
from . import windows
|
||||
notify = windows.notification()
|
||||
elif platform.system() == "Linux":
|
||||
import linux
|
||||
from . import linux
|
||||
notify = linux.notification()
|
||||
|
||||
def send(title, text):
|
||||
|
@@ -1,16 +0,0 @@
|
||||
# Replacement for py2exe distributed module
|
||||
# Avoids the use of the standard py2exe console.
|
||||
# Just import this file and it should go away
|
||||
|
||||
import sys
|
||||
if hasattr(sys,"frozen"): # true only if we are running as a py2exe app
|
||||
class Blackhole(object):
|
||||
def write(self,text):
|
||||
pass
|
||||
def flush(self):
|
||||
pass
|
||||
sys.stdout = Blackhole()
|
||||
sys.stderr = Blackhole()
|
||||
del Blackhole
|
||||
del sys
|
||||
|
@@ -1,51 +0,0 @@
|
||||
import ctypes
|
||||
import collections
|
||||
import platform
|
||||
import os
|
||||
|
||||
TYPES = {
|
||||
'Linux': {
|
||||
'loader': ctypes.CDLL,
|
||||
'functype': ctypes.CFUNCTYPE,
|
||||
'prefix': 'lib',
|
||||
'extension': '.so'
|
||||
},
|
||||
'Darwin': {
|
||||
'loader': ctypes.CDLL,
|
||||
'functype': ctypes.CFUNCTYPE,
|
||||
'prefix': 'lib',
|
||||
'extension': '.dylib'
|
||||
},
|
||||
}
|
||||
if platform.system() == 'Windows':
|
||||
TYPES['Windows'] = {
|
||||
'loader': ctypes.WinDLL,
|
||||
'functype': ctypes.WINFUNCTYPE,
|
||||
'prefix': "",
|
||||
'extension': '.dll'
|
||||
}
|
||||
|
||||
class LibraryLoadError(Exception): pass
|
||||
|
||||
def load_library(library, x86_path='.', x64_path='.', *args, **kwargs):
|
||||
lib = find_library_path(library, x86_path=x86_path, x64_path=x64_path)
|
||||
loaded = _do_load(lib, *args, **kwargs)
|
||||
if loaded is not None:
|
||||
return loaded
|
||||
raise LibraryLoadError('unable to load %r. Provided library path: %r' % (library, lib))
|
||||
|
||||
def _do_load(file, *args, **kwargs):
|
||||
loader = TYPES[platform.system()]['loader']
|
||||
return loader(file, *args, **kwargs)
|
||||
|
||||
def find_library_path(libname, x86_path='.', x64_path='.'):
|
||||
libname = '%s%s' % (TYPES[platform.system()]['prefix'], libname)
|
||||
if platform.machine() == 'x86_64':
|
||||
path = os.path.join(x64_path, libname)
|
||||
else:
|
||||
path = os.path.join(x86_path, libname)
|
||||
ext = TYPES[platform.system()]['extension']
|
||||
return '%s%s' % (path, ext)
|
||||
|
||||
def get_functype():
|
||||
return TYPES[platform.system()]['functype']
|
@@ -1,114 +0,0 @@
|
||||
import inspect
|
||||
import platform
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
import string
|
||||
import unicodedata
|
||||
|
||||
|
||||
def app_data_path(app_name=None):
|
||||
"""Cross-platform method for determining where to put application data."""
|
||||
"""Requires the name of the application"""
|
||||
plat = platform.system()
|
||||
if plat == 'Windows':
|
||||
import winpaths
|
||||
path = winpaths.get_appdata()
|
||||
elif plat == 'Darwin':
|
||||
path = os.path.join(os.path.expanduser('~'), 'Library', 'Application Support')
|
||||
elif plat == 'Linux':
|
||||
path = os.path.expanduser('~')
|
||||
app_name = '.%s' % app_name.replace(' ', '_')
|
||||
return os.path.join(path, app_name)
|
||||
|
||||
def prepare_app_data_path(app_name):
|
||||
"""Creates the application's data directory, given its name."""
|
||||
dir = app_data_path(app_name)
|
||||
return ensure_path(dir)
|
||||
|
||||
def embedded_data_path():
|
||||
if platform.system() == 'Darwin' and is_frozen():
|
||||
return os.path.abspath(os.path.join(executable_directory(), '..', 'Resources'))
|
||||
return app_path()
|
||||
|
||||
def is_frozen():
|
||||
"""Return a bool indicating if application is compressed"""
|
||||
import imp
|
||||
return hasattr(sys, 'frozen') or imp.is_frozen("__main__")
|
||||
|
||||
def get_executable():
|
||||
"""Returns the full executable path/name if frozen, or the full path/name of the main module if not."""
|
||||
if is_frozen():
|
||||
if platform.system() != 'Darwin':
|
||||
return sys.executable
|
||||
#On darwin, sys.executable points to python. We want the full path to the exe we ran.
|
||||
exedir = os.path.abspath(os.path.dirname(sys.executable))
|
||||
items = os.listdir(exedir)
|
||||
items.remove('python')
|
||||
return os.path.join(exedir, items[0])
|
||||
#Not frozen
|
||||
try:
|
||||
import __main__
|
||||
return os.path.abspath(__main__.__file__)
|
||||
except AttributeError:
|
||||
return sys.argv[0]
|
||||
|
||||
def get_module(level=2):
|
||||
"""Hacky method for deriving the caller of this function's module."""
|
||||
return inspect.getmodule(inspect.stack()[level][0]).__file__
|
||||
|
||||
def executable_directory():
|
||||
"""Always determine the directory of the executable, even when run with py2exe or otherwise frozen"""
|
||||
executable = get_executable()
|
||||
path = os.path.abspath(os.path.dirname(executable))
|
||||
return path
|
||||
|
||||
def app_path():
|
||||
"""Return the root of the application's directory"""
|
||||
path = executable_directory()
|
||||
if is_frozen() and platform.system() == 'Darwin':
|
||||
path = os.path.abspath(os.path.join(path, '..', '..'))
|
||||
return path
|
||||
|
||||
def module_path(level=2):
|
||||
return os.path.abspath(os.path.dirname(get_module(level)))
|
||||
|
||||
def documents_path():
|
||||
"""On windows, returns the path to My Documents. On OSX, returns the user's Documents folder. For anything else, returns the user's home directory."""
|
||||
plat = platform.system()
|
||||
if plat == 'Windows':
|
||||
import winpaths
|
||||
path = winpaths.get_my_documents()
|
||||
elif plat == 'Darwin':
|
||||
path = os.path.join(os.path.expanduser('~'), 'Documents')
|
||||
else:
|
||||
path = os.path.expanduser('~')
|
||||
return path
|
||||
|
||||
def safe_filename(filename):
|
||||
"""Given a filename, returns a safe version with no characters that would not work on different platforms."""
|
||||
SAFE_FILE_CHARS = "'-_.()[]{}!@#$%^&+=`~ "
|
||||
filename = unicode(filename)
|
||||
new_filename = ''.join(c for c in filename if c in SAFE_FILE_CHARS or c.isalnum())
|
||||
#Windows doesn't like directory names ending in space, macs consider filenames beginning with a dot as hidden, and windows removes dots at the ends of filenames.
|
||||
return new_filename.strip(' .')
|
||||
|
||||
def ensure_path(path):
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
return path
|
||||
|
||||
def start_file(path):
|
||||
if platform.system() == 'Windows':
|
||||
os.startfile(path)
|
||||
else:
|
||||
subprocess.Popen(['open', path])
|
||||
|
||||
def get_applications_path():
|
||||
"""Return the directory where applications are commonly installed on the system."""
|
||||
plat = platform.system()
|
||||
if plat == 'Windows':
|
||||
import winpaths
|
||||
return winpaths.get_program_files()
|
||||
elif plat == 'Darwin':
|
||||
return '/Applications'
|
@@ -1,27 +0,0 @@
|
||||
import platform
|
||||
import ctypes
|
||||
import os
|
||||
import signal
|
||||
|
||||
|
||||
def kill_windows_process(pid):
|
||||
PROCESS_TERMINATE = 1
|
||||
SYNCHRONIZE=1048576
|
||||
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, False, pid)
|
||||
ctypes.windll.kernel32.TerminateProcess(handle, -1)
|
||||
ctypes.windll.kernel32.WaitForSingleObject(handle, 1000)
|
||||
ctypes.windll.kernel32.CloseHandle(handle)
|
||||
|
||||
def kill_unix_process(pid):
|
||||
try:
|
||||
os.kill(pid, signal.SIGKILL)
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
def kill_process(pid):
|
||||
if pid < 0:
|
||||
return
|
||||
if platform.system() == 'Windows':
|
||||
kill_windows_process(pid)
|
||||
else:
|
||||
kill_unix_process(pid)
|
@@ -1,10 +0,0 @@
|
||||
import _winreg
|
||||
|
||||
SHELL_REGKEY = ur"Directory\shell"
|
||||
|
||||
def context_menu_integrate(item_key_name, item_display_text, item_command):
|
||||
app_menu_key = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, SHELL_REGKEY, 0, _winreg.KEY_WRITE)
|
||||
menu_item_key = _winreg.CreateKey(app_menu_key, item_key_name)
|
||||
_winreg.SetValueEx(menu_item_key, None, None, _winreg.REG_SZ, item_display_text)
|
||||
item_command_key = _winreg.CreateKey(menu_item_key, 'command')
|
||||
_winreg.SetValueEx(item_command_key, None, None, _winreg.REG_SZ, item_command)
|
@@ -1,9 +0,0 @@
|
||||
import platform
|
||||
import webbrowser
|
||||
|
||||
def open(url):
|
||||
if platform.system() == 'Windows':
|
||||
browser = webbrowser.get('windows-default')
|
||||
else:
|
||||
browser = webbrowser
|
||||
browser.open_new_tab(url)
|
@@ -1,20 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import shutil
|
||||
import widgetUtils
|
||||
import platform
|
||||
import output
|
||||
if platform.system() == "Windows":
|
||||
import wxUI as view
|
||||
from . import wxUI as view
|
||||
from controller import settings
|
||||
elif platform.system() == "Linux":
|
||||
import gtkUI as view
|
||||
from . import gtkUI as view
|
||||
import paths
|
||||
import time
|
||||
import os
|
||||
import logging
|
||||
import sessions
|
||||
from sessions.twitter import session
|
||||
import manager
|
||||
from . import manager
|
||||
import config_utils
|
||||
import config
|
||||
|
||||
@@ -77,7 +78,7 @@ class sessionManagerController(object):
|
||||
def do_ok(self):
|
||||
log.debug("Starting sessions...")
|
||||
for i in self.sessions:
|
||||
if sessions.sessions.has_key(i) == True: continue
|
||||
if (i in sessions.sessions) == True: continue
|
||||
s = session.Session(i)
|
||||
s.get_configuration()
|
||||
if i not in config.app["sessions"]["ignored_sessions"]:
|
||||
|
@@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" A base class to be derived in possible new sessions for TWBlue and services."""
|
||||
from __future__ import absolute_import
|
||||
import paths
|
||||
import output
|
||||
import time
|
||||
@@ -9,7 +10,7 @@ import config_utils
|
||||
import shelve
|
||||
import application
|
||||
import os
|
||||
import session_exceptions as Exceptions
|
||||
from . import session_exceptions as Exceptions
|
||||
log = logging.getLogger("sessionmanager.session")
|
||||
|
||||
class baseSession(object):
|
||||
|
@@ -1,7 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import platform
|
||||
system = platform.system()
|
||||
import utils
|
||||
from . import utils
|
||||
import re
|
||||
import htmlentitydefs
|
||||
import time
|
||||
@@ -10,7 +11,7 @@ import languageHandler
|
||||
import arrow
|
||||
import logging
|
||||
import config
|
||||
from long_tweets import twishort, tweets
|
||||
from .long_tweets import twishort, tweets
|
||||
log = logging.getLogger("compose")
|
||||
|
||||
def StripChars(s):
|
||||
@@ -38,13 +39,13 @@ def compose_tweet(tweet, db, relative_times, show_screen_names=False, session=No
|
||||
ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage())
|
||||
else:
|
||||
ts = tweet["created_at"]
|
||||
if tweet.has_key("message"):
|
||||
if "message" in tweet:
|
||||
value = "message"
|
||||
elif tweet.has_key("full_text"):
|
||||
elif "full_text" in tweet:
|
||||
value = "full_text"
|
||||
else:
|
||||
value = "text"
|
||||
if tweet.has_key("retweeted_status") and value != "message":
|
||||
if "retweeted_status" in tweet and value != "message":
|
||||
text = StripChars(tweet["retweeted_status"][value])
|
||||
else:
|
||||
text = StripChars(tweet[value])
|
||||
@@ -53,16 +54,16 @@ def compose_tweet(tweet, db, relative_times, show_screen_names=False, session=No
|
||||
else:
|
||||
user = tweet["user"]["name"]
|
||||
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if tweet.has_key("message") == False and tweet["retweeted_status"]["is_quote_status"] == False:
|
||||
if "retweeted_status" in tweet:
|
||||
if ("message" in tweet) == False and tweet["retweeted_status"]["is_quote_status"] == False:
|
||||
text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text)
|
||||
elif tweet["retweeted_status"]["is_quote_status"]:
|
||||
text = "%s" % (text)
|
||||
else:
|
||||
text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text)
|
||||
if tweet.has_key("message") == False:
|
||||
if ("message" in tweet) == False:
|
||||
urls = utils.find_urls_in_text(text)
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if "retweeted_status" in tweet:
|
||||
for url in range(0, len(urls)):
|
||||
try:
|
||||
text = text.replace(urls[url], tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"])
|
||||
@@ -110,14 +111,14 @@ def compose_direct_message(item, db, relative_times, show_screen_names=False, se
|
||||
|
||||
def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False, session=None):
|
||||
""" It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is."""
|
||||
if quoted_tweet.has_key("retweeted_status"):
|
||||
if quoted_tweet["retweeted_status"].has_key("full_text"):
|
||||
if "retweeted_status" in quoted_tweet:
|
||||
if "full_text" in quoted_tweet["retweeted_status"]:
|
||||
value = "full_text"
|
||||
else:
|
||||
value = "text"
|
||||
text = StripChars(quoted_tweet["retweeted_status"][value])
|
||||
else:
|
||||
if quoted_tweet.has_key("full_text"):
|
||||
if "full_text" in quoted_tweet:
|
||||
value = "full_text"
|
||||
else:
|
||||
value = "text"
|
||||
@@ -127,13 +128,13 @@ def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False,
|
||||
else:
|
||||
quoting_user = quoted_tweet["user"]["name"]
|
||||
source = re.sub(r"(?s)<.*?>", "", quoted_tweet["source"])
|
||||
if quoted_tweet.has_key("retweeted_status"):
|
||||
if "retweeted_status" in quoted_tweet:
|
||||
text = "rt @%s: %s" % (quoted_tweet["retweeted_status"]["user"]["screen_name"], text)
|
||||
if text[-1] in chars: text=text+"."
|
||||
original_user = original_tweet["user"]["screen_name"]
|
||||
if original_tweet.has_key("message"):
|
||||
if "message" in original_tweet:
|
||||
original_text = original_tweet["message"]
|
||||
elif original_tweet.has_key("full_text"):
|
||||
elif "full_text" in original_tweet:
|
||||
original_text = StripChars(original_tweet["full_text"])
|
||||
else:
|
||||
original_text = StripChars(original_tweet["text"])
|
||||
@@ -151,7 +152,7 @@ def compose_followers_list(tweet, db, relative_times=True, show_screen_names=Fal
|
||||
ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage())
|
||||
else:
|
||||
ts = tweet["created_at"]
|
||||
if tweet.has_key("status"):
|
||||
if "status" in tweet:
|
||||
if len(tweet["status"]) > 4 and system == "Windows":
|
||||
original_date2 = arrow.get(tweet["status"]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
|
||||
if relative_times:
|
||||
|
@@ -22,9 +22,9 @@ def is_long(tweet):
|
||||
""" Check if the passed tweet contains a quote in its metadata.
|
||||
tweet dict: a tweet dictionary.
|
||||
returns True if a quote is detected, False otherwise."""
|
||||
if tweet.has_key("quoted_status_id") and tweet.has_key("quoted_status"):
|
||||
if "quoted_status_id" in tweet and "quoted_status" in tweet:
|
||||
return tweet["quoted_status_id"]
|
||||
elif tweet.has_key("retweeted_status") and tweet["retweeted_status"].has_key("quoted_status_id") and tweet["retweeted_status"].has_key("quoted_status"):
|
||||
elif "retweeted_status" in tweet and "quoted_status_id" in tweet["retweeted_status"] and "quoted_status" in tweet["retweeted_status"]:
|
||||
return tweet["retweeted_status"]["quoted_status_id"]
|
||||
return False
|
||||
|
||||
@@ -32,8 +32,8 @@ def clear_url(tweet):
|
||||
""" Reads data from a quoted tweet and removes the link to the Status from the tweet's text.
|
||||
tweet dict: a tweet dictionary.
|
||||
returns a tweet dictionary without the URL to the status ID in its text to display."""
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if tweet["retweeted_status"].has_key("full_text"):
|
||||
if "retweeted_status" in tweet:
|
||||
if "full_text" in tweet["retweeted_status"]:
|
||||
value = "full_text"
|
||||
else:
|
||||
value = "text"
|
||||
@@ -41,7 +41,7 @@ def clear_url(tweet):
|
||||
try: tweet["message"] = tweet["message"].replace(urls[-1], "")
|
||||
except IndexError: pass
|
||||
else:
|
||||
if tweet.has_key("full_text"):
|
||||
if "full_text" in tweet:
|
||||
value = "full_text"
|
||||
else:
|
||||
value = "text"
|
||||
|
@@ -16,6 +16,7 @@
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
from __future__ import print_function
|
||||
import logging
|
||||
import requests
|
||||
import keys
|
||||
@@ -47,7 +48,7 @@ def is_long(tweet):
|
||||
# see https://github.com/manuelcortez/TWBlue/issues/103
|
||||
except TypeError:
|
||||
pass
|
||||
if long == False and tweet.has_key("retweeted_status"):
|
||||
if long == False and "retweeted_status" in tweet:
|
||||
for url in range(0, len(tweet["retweeted_status"]["entities"]["urls"])):
|
||||
try:
|
||||
if tweet["retweeted_status"]["entities"]["urls"][url] != None and "twishort.com" in tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"]:
|
||||
@@ -97,5 +98,5 @@ def create_tweet(user_token, user_secret, text, media=0):
|
||||
try:
|
||||
return response.json()["text_to_tweet"]
|
||||
except:
|
||||
print "There was a problem creating a long tweet"
|
||||
print("There was a problem creating a long tweet")
|
||||
return 0
|
@@ -1,5 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" This is the main session needed to access all Twitter Features."""
|
||||
from __future__ import absolute_import
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
@@ -15,7 +16,7 @@ from keys import keyring
|
||||
from sessions import base
|
||||
from sessions.twitter import utils, compose
|
||||
from sessions.twitter.long_tweets import tweets, twishort
|
||||
from wxUI import authorisationDialog
|
||||
from .wxUI import authorisationDialog
|
||||
|
||||
log = logging.getLogger("sessions.twitterSession")
|
||||
|
||||
@@ -30,9 +31,9 @@ class Session(base.baseSession):
|
||||
returns the number of items that have been added in this execution"""
|
||||
num = 0
|
||||
last_id = None
|
||||
if self.db.has_key(name) == False:
|
||||
if (name in self.db) == False:
|
||||
self.db[name] = []
|
||||
if self.db.has_key("users") == False:
|
||||
if ("users" in self.db) == False:
|
||||
self.db["users"] = {}
|
||||
if ignore_older and len(self.db[name]) > 0:
|
||||
if self.settings["general"]["reverse_timelines"] == False:
|
||||
@@ -51,8 +52,8 @@ class Session(base.baseSession):
|
||||
if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
|
||||
else: self.db[name].insert(0, i)
|
||||
num = num+1
|
||||
if i.has_key("user") == True:
|
||||
if self.db["users"].has_key(i["user"]["id"]) == False:
|
||||
if ("user" in i) == True:
|
||||
if (i["user"]["id"] in self.db["users"]) == False:
|
||||
self.db["users"][i["user"]["id"]] = i["user"]
|
||||
return num
|
||||
|
||||
@@ -66,7 +67,7 @@ class Session(base.baseSession):
|
||||
if name == "direct_messages":
|
||||
return self.order_direct_messages(data)
|
||||
num = 0
|
||||
if self.db.has_key(name) == False:
|
||||
if (name in self.db) == False:
|
||||
self.db[name] = {}
|
||||
self.db[name]["items"] = []
|
||||
for i in data:
|
||||
@@ -82,12 +83,12 @@ class Session(base.baseSession):
|
||||
returns the number of incoming messages processed in this execution, and sends an event with data regarding amount of sent direct messages added."""
|
||||
incoming = 0
|
||||
sent = 0
|
||||
if self.db.has_key("direct_messages") == False:
|
||||
if ("direct_messages" in self.db) == False:
|
||||
self.db["direct_messages"] = {}
|
||||
self.db["direct_messages"]["items"] = []
|
||||
for i in data:
|
||||
if i["message_create"]["sender_id"] == self.db["user_id"]:
|
||||
if self.db.has_key("sent_direct_messages") and utils.find_item(i["id"], self.db["sent_direct_messages"]["items"]) == None:
|
||||
if "sent_direct_messages" in self.db and utils.find_item(i["id"], self.db["sent_direct_messages"]["items"]) == None:
|
||||
if self.settings["general"]["reverse_timelines"] == False: self.db["sent_direct_messages"]["items"].append(i)
|
||||
else: self.db["sent_direct_messages"]["items"].insert(0, i)
|
||||
sent = sent+1
|
||||
@@ -164,13 +165,13 @@ class Session(base.baseSession):
|
||||
users, dm bool: If any of these is set to True, the function will treat items as users or dm (they need different handling).
|
||||
name str: name of the database item to put new element in."""
|
||||
results = []
|
||||
if kwargs.has_key("cursor") and kwargs["cursor"] == 0:
|
||||
if "cursor" in kwargs and kwargs["cursor"] == 0:
|
||||
output.speak(_(u"There are no more items to retrieve in this buffer."))
|
||||
return
|
||||
data = getattr(self.twitter, update_function)(*args, **kwargs)
|
||||
if users == True:
|
||||
if type(data) == dict and data.has_key("next_cursor"):
|
||||
if data.has_key("next_cursor"): # There are more objects to retrieve.
|
||||
if type(data) == dict and "next_cursor" in data:
|
||||
if "next_cursor" in data: # There are more objects to retrieve.
|
||||
self.db[name]["cursor"] = data["next_cursor"]
|
||||
else: # Set cursor to 0, wich means no more items available.
|
||||
self.db[name]["cursor"] = 0
|
||||
@@ -178,7 +179,7 @@ class Session(base.baseSession):
|
||||
elif type(data) == list:
|
||||
results.extend(data[1:])
|
||||
elif dm == True:
|
||||
if data.has_key("next_cursor"): # There are more objects to retrieve.
|
||||
if "next_cursor" in data: # There are more objects to retrieve.
|
||||
self.db[name]["cursor"] = data["next_cursor"]
|
||||
else: # Set cursor to 0, wich means no more items available.
|
||||
self.db[name]["cursor"] = 0
|
||||
@@ -289,7 +290,7 @@ class Session(base.baseSession):
|
||||
name str: Name to save items to the database.
|
||||
function str: A function to get the items."""
|
||||
last_id = -1
|
||||
if self.db.has_key(name):
|
||||
if name in self.db:
|
||||
try:
|
||||
if self.db[name][0]["id"] > self.db[name][-1]["id"]:
|
||||
last_id = self.db[name][0]["id"]
|
||||
@@ -309,7 +310,7 @@ class Session(base.baseSession):
|
||||
returns number of items retrieved."""
|
||||
items_ = []
|
||||
try:
|
||||
if self.db[name].has_key("cursor") and get_previous:
|
||||
if "cursor" in self.db[name] and get_previous:
|
||||
cursor = self.db[name]["cursor"]
|
||||
else:
|
||||
cursor = -1
|
||||
@@ -322,7 +323,7 @@ class Session(base.baseSession):
|
||||
tl[items].reverse()
|
||||
num = self.order_cursored_buffer(name, tl[items])
|
||||
# Recently, Twitter's new endpoints have cursor if there are more results.
|
||||
if tl.has_key("next_cursor"):
|
||||
if "next_cursor" in tl:
|
||||
self.db[name]["cursor"] = tl["next_cursor"]
|
||||
else:
|
||||
self.db[name]["cursor"] = 0
|
||||
@@ -352,7 +353,7 @@ class Session(base.baseSession):
|
||||
def get_quoted_tweet(self, tweet):
|
||||
""" Process a tweet and extract all information related to the quote."""
|
||||
quoted_tweet = tweet
|
||||
if tweet.has_key("full_text"):
|
||||
if "full_text" in tweet:
|
||||
value = "full_text"
|
||||
else:
|
||||
value = "text"
|
||||
@@ -360,16 +361,16 @@ class Session(base.baseSession):
|
||||
for url in range(0, len(urls)):
|
||||
try: quoted_tweet[value] = quoted_tweet[value].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
|
||||
except IndexError: pass
|
||||
if quoted_tweet.has_key("quoted_status"):
|
||||
if "quoted_status" in quoted_tweet:
|
||||
original_tweet = quoted_tweet["quoted_status"]
|
||||
elif quoted_tweet.has_key("retweeted_status") and quoted_tweet["retweeted_status"].has_key("quoted_status"):
|
||||
elif "retweeted_status" in quoted_tweet and "quoted_status" in quoted_tweet["retweeted_status"]:
|
||||
original_tweet = quoted_tweet["retweeted_status"]["quoted_status"]
|
||||
else:
|
||||
return quoted_tweet
|
||||
original_tweet = self.check_long_tweet(original_tweet)
|
||||
if original_tweet.has_key("full_text"):
|
||||
if "full_text" in original_tweet:
|
||||
value = "full_text"
|
||||
elif original_tweet.has_key("message"):
|
||||
elif "message" in original_tweet:
|
||||
value = "message"
|
||||
else:
|
||||
value = "text"
|
||||
@@ -386,13 +387,13 @@ class Session(base.baseSession):
|
||||
long = twishort.is_long(tweet)
|
||||
if long != False and config.app["app-settings"]["handle_longtweets"]:
|
||||
message = twishort.get_full_text(long)
|
||||
if tweet.has_key("quoted_status"):
|
||||
if "quoted_status" in tweet:
|
||||
tweet["quoted_status"]["message"] = message
|
||||
if tweet["quoted_status"]["message"] == False: return False
|
||||
tweet["quoted_status"]["twishort"] = True
|
||||
for i in tweet["quoted_status"]["entities"]["user_mentions"]:
|
||||
if "@%s" % (i["screen_name"]) not in tweet["quoted_status"]["message"] and i["screen_name"] != tweet["user"]["screen_name"]:
|
||||
if tweet["quoted_status"].has_key("retweeted_status") and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
|
||||
if "retweeted_status" in tweet["quoted_status"] and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
|
||||
continue
|
||||
tweet["quoted_status"]["message"] = u"@%s %s" % (i["screen_name"], tweet["message"])
|
||||
else:
|
||||
@@ -401,7 +402,7 @@ class Session(base.baseSession):
|
||||
tweet["twishort"] = True
|
||||
for i in tweet["entities"]["user_mentions"]:
|
||||
if "@%s" % (i["screen_name"]) not in tweet["message"] and i["screen_name"] != tweet["user"]["screen_name"]:
|
||||
if tweet.has_key("retweeted_status") and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
|
||||
if "retweeted_status" in tweet and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
|
||||
continue
|
||||
return tweet
|
||||
|
||||
@@ -409,8 +410,12 @@ class Session(base.baseSession):
|
||||
""" Returns an user object associated with an ID.
|
||||
id str: User identifier, provided by Twitter.
|
||||
returns an user dict."""
|
||||
if self.db.has_key("users") == False or self.db["users"].has_key(id) == False:
|
||||
user = self.twitter.show_user(id=id)
|
||||
if ("users" in self.db) == False or (id in self.db["users"]) == False:
|
||||
try:
|
||||
user = self.twitter.show_user(id=id)
|
||||
except TwythonError:
|
||||
user = dict(screen_name="deleted_account", name="Deleted account")
|
||||
return user
|
||||
self.db["users"][user["id_str"]] = user
|
||||
return user
|
||||
else:
|
||||
@@ -420,7 +425,7 @@ class Session(base.baseSession):
|
||||
""" Returns an user identifier associated with a screen_name.
|
||||
screen_name str: User name, such as tw_blue2, provided by Twitter.
|
||||
returns an user ID."""
|
||||
if self.db.has_key("users") == False:
|
||||
if ("users" in self.db) == False:
|
||||
user = utils.if_user_exists(self.twitter, screen_name)
|
||||
self.db["users"][user["id_str"]] = user
|
||||
return user["id_str"]
|
||||
|
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import print_function
|
||||
import url_shortener, re
|
||||
import output
|
||||
from twython import TwythonError
|
||||
@@ -24,32 +25,32 @@ def find_urls_in_text(text):
|
||||
def find_urls (tweet):
|
||||
urls = []
|
||||
# Let's add URLS from tweet entities.
|
||||
if tweet.has_key("message_create"):
|
||||
if "message_create" in tweet:
|
||||
entities = tweet["message_create"]["message_data"]["entities"]
|
||||
else:
|
||||
entities = tweet["entities"]
|
||||
for i in entities["urls"]:
|
||||
if i["expanded_url"] not in urls:
|
||||
urls.append(i["expanded_url"])
|
||||
if tweet.has_key("quoted_status"):
|
||||
if "quoted_status" in tweet:
|
||||
for i in tweet["quoted_status"]["entities"]["urls"]:
|
||||
if i["expanded_url"] not in urls:
|
||||
urls.append(i["expanded_url"])
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if "retweeted_status" in tweet:
|
||||
for i in tweet["retweeted_status"]["entities"]["urls"]:
|
||||
if i["expanded_url"] not in urls:
|
||||
urls.append(i["expanded_url"])
|
||||
if tweet["retweeted_status"].has_key("quoted_status"):
|
||||
if "quoted_status" in tweet["retweeted_status"]:
|
||||
for i in tweet["retweeted_status"]["quoted_status"]["entities"]["urls"]:
|
||||
if i["expanded_url"] not in urls:
|
||||
urls.append(i["expanded_url"])
|
||||
if tweet.has_key("message"):
|
||||
if "message" in tweet:
|
||||
i = "message"
|
||||
elif tweet.has_key("full_text"):
|
||||
elif "full_text" in tweet:
|
||||
i = "full_text"
|
||||
else:
|
||||
i = "text"
|
||||
if tweet.has_key("message_create"):
|
||||
if "message_create" in tweet:
|
||||
extracted_urls = find_urls_in_text(tweet["message_create"]["message_data"]["text"])
|
||||
else:
|
||||
extracted_urls = find_urls_in_text(tweet[i])
|
||||
@@ -82,7 +83,7 @@ def is_audio(tweet):
|
||||
try:
|
||||
if len(find_urls(tweet)) < 1:
|
||||
return False
|
||||
if tweet.has_key("message_create"):
|
||||
if "message_create" in tweet:
|
||||
entities = tweet["message_create"]["message_data"]["entities"]
|
||||
else:
|
||||
entities = tweet["entities"]
|
||||
@@ -91,22 +92,22 @@ def is_audio(tweet):
|
||||
if i["text"] == "audio":
|
||||
return True
|
||||
except IndexError:
|
||||
print tweet["entities"]["hashtags"]
|
||||
print(tweet["entities"]["hashtags"])
|
||||
log.exception("Exception while executing is_audio hashtag algorithm")
|
||||
|
||||
def is_geocoded(tweet):
|
||||
if tweet.has_key("coordinates") and tweet["coordinates"] != None:
|
||||
if "coordinates" in tweet and tweet["coordinates"] != None:
|
||||
return True
|
||||
|
||||
def is_media(tweet):
|
||||
if tweet.has_key("message_create"):
|
||||
if "message_create" in tweet:
|
||||
entities = tweet["message_create"]["message_data"]["entities"]
|
||||
else:
|
||||
entities = tweet["entities"]
|
||||
if entities.has_key("media") == False:
|
||||
if ("media" in entities) == False:
|
||||
return False
|
||||
for i in entities["media"]:
|
||||
if i.has_key("type") and i["type"] == "photo":
|
||||
if "type" in i and i["type"] == "photo":
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -121,10 +122,10 @@ def get_all_mentioned(tweet, conf, field="screen_name"):
|
||||
|
||||
def get_all_users(tweet, conf):
|
||||
string = []
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if "retweeted_status" in tweet:
|
||||
string.append(tweet["user"]["screen_name"])
|
||||
tweet = tweet["retweeted_status"]
|
||||
if tweet.has_key("sender"):
|
||||
if "sender" in tweet:
|
||||
string.append(tweet["sender"]["screen_name"])
|
||||
else:
|
||||
if tweet["user"]["screen_name"] != conf["user_name"]:
|
||||
@@ -161,16 +162,16 @@ def api_call(parent=None, call_name=None, preexec_message="", success="", succes
|
||||
|
||||
def is_allowed(tweet, settings, buffer_name):
|
||||
clients = settings["twitter"]["ignored_clients"]
|
||||
if tweet.has_key("sender"): return True
|
||||
if "sender" in tweet: return True
|
||||
allowed = True
|
||||
tweet_data = {}
|
||||
if tweet.has_key("retweeted_status"):
|
||||
if "retweeted_status" in tweet:
|
||||
tweet_data["retweet"] = True
|
||||
if tweet["in_reply_to_status_id_str"] != None:
|
||||
tweet_data["reply"] = True
|
||||
if tweet.has_key("quoted_status"):
|
||||
if "quoted_status" in tweet:
|
||||
tweet_data["quote"] = True
|
||||
if tweet.has_key("retweeted_status"): tweet = tweet["retweeted_status"]
|
||||
if "retweeted_status" in tweet: tweet = tweet["retweeted_status"]
|
||||
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||
for i in clients:
|
||||
if i.lower() == source.lower():
|
||||
@@ -178,7 +179,7 @@ def is_allowed(tweet, settings, buffer_name):
|
||||
return filter_tweet(tweet, tweet_data, settings, buffer_name)
|
||||
|
||||
def filter_tweet(tweet, tweet_data, settings, buffer_name):
|
||||
if tweet.has_key("full_text"):
|
||||
if "full_text" in tweet:
|
||||
value = "full_text"
|
||||
else:
|
||||
value = "text"
|
||||
@@ -187,23 +188,23 @@ def filter_tweet(tweet, tweet_data, settings, buffer_name):
|
||||
regexp = settings["filters"][i]["regexp"]
|
||||
word = settings["filters"][i]["word"]
|
||||
# Added if/else for compatibility reasons.
|
||||
if settings["filters"][i].has_key("allow_rts"):
|
||||
if "allow_rts" in settings["filters"][i]:
|
||||
allow_rts = settings["filters"][i]["allow_rts"]
|
||||
else:
|
||||
allow_rts = "True"
|
||||
if settings["filters"][i].has_key("allow_quotes"):
|
||||
if "allow_quotes" in settings["filters"][i]:
|
||||
allow_quotes = settings["filters"][i]["allow_quotes"]
|
||||
else:
|
||||
allow_quotes = "True"
|
||||
if settings["filters"][i].has_key("allow_replies"):
|
||||
if "allow_replies" in settings["filters"][i]:
|
||||
allow_replies = settings["filters"][i]["allow_replies"]
|
||||
else:
|
||||
allow_replies = "True"
|
||||
if allow_rts == "False" and tweet_data.has_key("retweet"):
|
||||
if allow_rts == "False" and "retweet" in tweet_data:
|
||||
return False
|
||||
if allow_quotes == "False" and tweet_data.has_key("quote"):
|
||||
if allow_quotes == "False" and "quote" in tweet_data:
|
||||
return False
|
||||
if allow_replies == "False" and tweet_data.has_key("reply"):
|
||||
if allow_replies == "False" and "reply" in tweet_data:
|
||||
return False
|
||||
if word != "" and settings["filters"][i]["if_word_exists"]:
|
||||
if word in tweet[value]:
|
||||
|
21
src/sound.py
21
src/sound.py
@@ -1,16 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
import url_shortener
|
||||
import audio_services
|
||||
import os
|
||||
import logging as original_logger
|
||||
log = original_logger.getLogger("sound")
|
||||
import paths
|
||||
import sound_lib
|
||||
import sys
|
||||
import subprocess
|
||||
import platform
|
||||
import tempfile
|
||||
import glob
|
||||
import url_shortener
|
||||
import audio_services
|
||||
import paths
|
||||
import sound_lib
|
||||
import output
|
||||
import youtube_utils
|
||||
import application
|
||||
system = platform.system()
|
||||
if system=="Windows" and not hasattr(sys, 'frozen'): # We are running from source on Windows
|
||||
current_dir=os.getcwd()
|
||||
@@ -18,13 +20,14 @@ if system=="Windows" and not hasattr(sys, 'frozen'): # We are running from sourc
|
||||
import vlc
|
||||
if system=="Windows" and not hasattr(sys, 'frozen'): # Restore the original folder
|
||||
os.chdir(current_dir)
|
||||
import sound_lib.output, sound_lib.input, sound_lib.stream
|
||||
from mysc.repeating_timer import RepeatingTimer
|
||||
from mysc.thread_utils import call_threaded
|
||||
import application
|
||||
import tempfile
|
||||
import glob
|
||||
|
||||
URLPlayer = None
|
||||
|
||||
log = original_logger.getLogger("sound")
|
||||
|
||||
def setup():
|
||||
global URLPlayer
|
||||
if not URLPlayer:
|
||||
|
@@ -1,25 +0,0 @@
|
||||
import output, input, recording, stream
|
||||
|
||||
__author__ = 'Christopher Toth'
|
||||
__version__ = 0.73
|
||||
|
||||
def find_datafiles():
|
||||
from glob import glob
|
||||
import os
|
||||
import platform
|
||||
import sound_lib
|
||||
path = os.path.join(sound_lib.__path__[0], 'lib')
|
||||
system = platform.system()
|
||||
if system == 'Windows':
|
||||
file_ext = '*.dll'
|
||||
elif system == 'Darwin':
|
||||
file_ext = '*.dylib'
|
||||
else:
|
||||
file_ext = '*.so'
|
||||
if platform.architecture()[0] == '32bit' or platform.system() == 'Darwin':
|
||||
arch = 'x86'
|
||||
else:
|
||||
arch = 'x64'
|
||||
dest_dir = os.path.join('sound_lib', 'lib', arch)
|
||||
source = glob(os.path.join(path, arch, file_ext))
|
||||
return [(dest_dir, source)]
|
@@ -1,285 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from .external.pybass import *
|
||||
from .main import bass_call, bass_call_0, BassError, update_3d_system, FlagObject
|
||||
from ctypes import pointer, c_float, c_long, c_ulong, c_buffer
|
||||
|
||||
class Channel (FlagObject):
|
||||
"""A "channel" can be a sample playback channel (HCHANNEL), a sample stream (HSTREAM), a MOD music (HMUSIC), or a recording (HRECORD). Each "Channel" function can be used with one or more of these channel types."""
|
||||
|
||||
def __init__ (self, handle):
|
||||
self.handle = handle
|
||||
self.attribute_mapping = {
|
||||
'eaxmix': BASS_ATTRIB_EAXMIX,
|
||||
'frequency': BASS_ATTRIB_FREQ,
|
||||
'pan': BASS_ATTRIB_PAN,
|
||||
'volume': BASS_ATTRIB_VOL
|
||||
}
|
||||
|
||||
def add_attributes_to_mapping(self, **attrs):
|
||||
self.attribute_mapping.update(**attrs)
|
||||
|
||||
def play (self, restart=False):
|
||||
"""Starts (or resumes) playback of a sample, stream, MOD music, or recording."""
|
||||
return bass_call(BASS_ChannelPlay, self.handle, restart)
|
||||
|
||||
def play_blocking(self, restart=False):
|
||||
self.play(restart=restart)
|
||||
while self.is_playing:
|
||||
pass
|
||||
|
||||
def pause (self):
|
||||
return bass_call(BASS_ChannelPause, self.handle)
|
||||
|
||||
def is_active (self):
|
||||
"Checks if a sample, stream, or MOD music is active (playing) or stalled. Can also check if a recording is in progress."""
|
||||
return bass_call_0(BASS_ChannelIsActive, self.handle)
|
||||
|
||||
@property
|
||||
def is_playing(self):
|
||||
return self.is_active() == BASS_ACTIVE_PLAYING
|
||||
|
||||
@property
|
||||
def is_paused(self):
|
||||
return self.is_active() == BASS_ACTIVE_PAUSED
|
||||
|
||||
@property
|
||||
def is_stopped(self):
|
||||
return self.is_active() == BASS_ACTIVE_STOPPED
|
||||
|
||||
@property
|
||||
def is_stalled(self):
|
||||
return self.is_active() == BASS_ACTIVE_STALLED
|
||||
|
||||
def get_position (self, mode=BASS_POS_BYTE):
|
||||
"""Retrieves the playback position of a sample, stream, or MOD music. Can also be used with a recording channel."""
|
||||
return bass_call_0(BASS_ChannelGetPosition, self.handle, mode)
|
||||
|
||||
def set_position (self, pos, mode=BASS_POS_BYTE):
|
||||
"""Sets the playback position of a sample, MOD music, or stream."""
|
||||
return bass_call(BASS_ChannelSetPosition, self.handle, pos, mode)
|
||||
|
||||
position = property(get_position, set_position)
|
||||
|
||||
def stop (self):
|
||||
"""Stops a sample, stream, MOD music, or recording."""
|
||||
return bass_call(BASS_ChannelStop, self.handle)
|
||||
|
||||
def update (self, length=0):
|
||||
"""Updates the playback buffer of a stream or MOD music."""
|
||||
return bass_call(BASS_ChannelUpdate, self.handle, length)
|
||||
|
||||
def get_length (self, mode=BASS_POS_BYTE):
|
||||
return bass_call_0(BASS_ChannelGetLength, self.handle, mode)
|
||||
|
||||
__len__ = get_length
|
||||
|
||||
def __bool__(self):
|
||||
return True
|
||||
|
||||
def get_device(self):
|
||||
"""Retrieves the device that a channel is using."""
|
||||
return bass_call_0( BASS_ChannelGetDevice, self.handle)
|
||||
|
||||
def set_device (self, device):
|
||||
"""Changes the device that a stream, MOD music or sample is using."""
|
||||
bass_call(BASS_ChannelSetDevice, self.handle, device)
|
||||
|
||||
device = property(get_device, set_device)
|
||||
|
||||
def set_fx(self, type, priority=0):
|
||||
"""Sets an effect on a stream, MOD music, or recording channel."""
|
||||
return SoundEffect(bass_call(BASS_ChannelSetFX, type, priority))
|
||||
|
||||
def bytes_to_seconds(self, position=None):
|
||||
"""Translates a byte position into time (seconds), based on a channel's format."""
|
||||
position = position or self.position
|
||||
return bass_call_0(BASS_ChannelBytes2Seconds, self.handle, position)
|
||||
|
||||
def length_in_seconds(self):
|
||||
return self.bytes_to_seconds(self.get_length())
|
||||
|
||||
|
||||
def seconds_to_bytes(self, position):
|
||||
"""Translates a time (seconds) position into bytes, based on a channel's format."""
|
||||
return bass_call_0(BASS_ChannelSeconds2Bytes, self.handle, position)
|
||||
|
||||
def get_attribute(self, attribute):
|
||||
"""Retrieves the value of a channel's attribute."""
|
||||
value = pointer(c_float())
|
||||
if attribute in self.attribute_mapping:
|
||||
attribute = self.attribute_mapping[attribute]
|
||||
bass_call(BASS_ChannelGetAttribute, self.handle, attribute, value)
|
||||
return value.contents.value
|
||||
|
||||
def set_attribute(self, attribute, value):
|
||||
"""Sets the value of a channel's attribute."""
|
||||
if attribute in self.attribute_mapping:
|
||||
attribute = self.attribute_mapping[attribute]
|
||||
return bass_call(BASS_ChannelSetAttribute, self.handle, attribute, value)
|
||||
|
||||
def slide_attribute(self, attribute, value, time):
|
||||
"""Slides a channel's attribute from its current value to a new value."""
|
||||
if attribute in self.attribute_mapping:
|
||||
attribute = self.attribute_mapping[attribute]
|
||||
return bass_call(BASS_ChannelSlideAttribute, self.handle, attribute, value, time*1000)
|
||||
|
||||
def is_sliding (self, attribute=None):
|
||||
"""Checks if an attribute (or any attribute) of a sample, stream, or MOD music is sliding."""
|
||||
return bass_call_0(BASS_ChannelIsSliding, self.handle, attribute)
|
||||
|
||||
def get_info(self):
|
||||
"""Retrieves information on a channel."""
|
||||
value = pointer(BASS_CHANNELINFO())
|
||||
bass_call(BASS_ChannelGetInfo, self.handle, value)
|
||||
return value[0]
|
||||
|
||||
def get_level(self):
|
||||
"""Retrieves the level (peak amplitude) of a stream, MOD music or recording channel."""
|
||||
return bass_call_0(BASS_ChannelGetLevel, self.handle)
|
||||
|
||||
def lock(self):
|
||||
"""Locks a stream, MOD music or recording channel to the current thread."""
|
||||
return bass_call(BASS_ChannelLock, self.handle, True)
|
||||
|
||||
def unlock(self):
|
||||
"""Unlocks a stream, MOD music or recording channel from the current thread."""
|
||||
return bass_call(BASS_ChannelLock, self.handle, False)
|
||||
|
||||
def get_3d_attributes(self):
|
||||
"""Retrieves the 3D attributes of a sample, stream, or MOD music channel with 3D functionality."""
|
||||
answer = dict(mode=c_ulong(), min=c_float(), max=c_float(), iangle=c_ulong(), oangle=c_ulong(), outvol=c_float())
|
||||
bass_call(BASS_ChannelGet3DAttributes, self.handle, pointer(answer['mode']), pointer(answer['min']), pointer(answer['max']), pointer(answer['iangle']), pointer(answer['oangle']), pointer(answer['outvol']))
|
||||
for k in answer:
|
||||
answer[k] = answer[k].value()
|
||||
return answer
|
||||
|
||||
@update_3d_system
|
||||
def set_3d_attributes(self, mode=-1, min=0.0, max=0.0, iangle=-1, oangle=-1, outvol=-1):
|
||||
"""Sets the 3D attributes of a sample, stream, or MOD music channel with 3D functionality."""
|
||||
return bass_call(BASS_ChannelSet3DAttributes, self.handle, mode, min, max, iangle, oangle, outvol)
|
||||
|
||||
def get_3d_position(self):
|
||||
"""Retrieves the 3D position of a sample, stream, or MOD music channel with 3D functionality."""
|
||||
answer = dict(position=BASS_3DVECTOR(), orientation=BASS_3DVECTOR(), velocity=BASS_3DVECTOR())
|
||||
bass_call(BASS_ChannelGet3DPosition, self.handle, pointer(answer['position']), pointer(answer['orientation']), pointer(answer['velocity']))
|
||||
return answer
|
||||
|
||||
@update_3d_system
|
||||
def set_3d_position(self, position=None, orientation=None, velocity=None):
|
||||
"""Sets the 3D position of a sample, stream, or MOD music channel with 3D functionality."""
|
||||
if position:
|
||||
position = pointer(position)
|
||||
if orientation:
|
||||
orientation = pointer(orientation)
|
||||
if velocity:
|
||||
velocity = pointer(velocity)
|
||||
return bass_call(BASS_ChannelSet3DPosition, self.handle, position, orientation, velocity)
|
||||
|
||||
def set_link(self, handle):
|
||||
"""Links two MOD music or stream channels together."""
|
||||
bass_call(BASS_ChannelSetLink, self.handle, handle)
|
||||
|
||||
def remove_link(self, handle):
|
||||
"""Removes a link between two MOD music or stream channels."""
|
||||
return bass_call(BASS_ChannelRemoveLink, self.handle, handle)
|
||||
|
||||
def __iadd__(self, other):
|
||||
"""Convenience method to link this channel to another. Calls set_link on the passed in item's handle"""
|
||||
self.set_link(other.handle)
|
||||
return self
|
||||
|
||||
def __isub__(self, other):
|
||||
"""Convenience method to unlink this channel from another. Calls remove_link on the passed in item's handle"""
|
||||
self.remove_link(other.handle)
|
||||
return self
|
||||
|
||||
def get_frequency(self):
|
||||
return self.get_attribute(BASS_ATTRIB_FREQ )
|
||||
|
||||
def set_frequency(self, frequency):
|
||||
self.set_attribute(BASS_ATTRIB_FREQ, frequency)
|
||||
|
||||
frequency = property(fget=get_frequency, fset=set_frequency)
|
||||
|
||||
def get_pan(self):
|
||||
return self.get_attribute(BASS_ATTRIB_PAN)
|
||||
|
||||
def set_pan(self, pan):
|
||||
return self.set_attribute(BASS_ATTRIB_PAN, pan)
|
||||
|
||||
pan = property(fget=get_pan, fset=set_pan)
|
||||
|
||||
def get_volume(self):
|
||||
return self.get_attribute(BASS_ATTRIB_VOL)
|
||||
|
||||
def set_volume(self, volume):
|
||||
self.set_attribute(BASS_ATTRIB_VOL, volume)
|
||||
|
||||
volume = property(fget=get_volume, fset=set_volume)
|
||||
|
||||
def get_data(self, length=16384):
|
||||
buf = c_buffer(length)
|
||||
bass_call_0(BASS_ChannelGetData, self.handle, pointer(buf), length)
|
||||
return buf
|
||||
|
||||
|
||||
#This is less and less of a one-to-one mapping,
|
||||
#But I feel that it's better to be consistent with ourselves
|
||||
#Than with the library. We won't punish ourselves
|
||||
#For their bad decisions
|
||||
|
||||
def get_looping(self):
|
||||
return bass_call_0(BASS_ChannelFlags, self.handle, BASS_SAMPLE_LOOP, 0) == 20
|
||||
|
||||
def set_looping(self, looping):
|
||||
if looping:
|
||||
return bass_call_0(BASS_ChannelFlags, self.handle, BASS_SAMPLE_LOOP, BASS_SAMPLE_LOOP)
|
||||
return bass_call_0(BASS_ChannelFlags, self.handle, 0, BASS_SAMPLE_LOOP)
|
||||
|
||||
looping = property(fget=get_looping, fset=set_looping)
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
self.free()
|
||||
except:
|
||||
pass
|
||||
|
||||
def get_x(self):
|
||||
return self.get_3d_position()['position'].x
|
||||
|
||||
def set_x(self, val):
|
||||
pos = self.get_3d_position()
|
||||
pos['position'].x = val
|
||||
self.set_3d_position(**pos)
|
||||
|
||||
x = property(fget=get_x, fset=set_x)
|
||||
|
||||
def get_y(self):
|
||||
return self.get_3d_position()['position'].y
|
||||
|
||||
def set_y(self, val):
|
||||
pos = self.get_3d_position()
|
||||
pos['position'].y = val
|
||||
self.set_3d_position(**pos)
|
||||
|
||||
y = property(fget=get_y, fset=set_y)
|
||||
|
||||
def get_z(self):
|
||||
return self.get_3d_position()['position'].z
|
||||
|
||||
def set_z(self, val):
|
||||
pos = self.get_3d_position()
|
||||
pos['position'].z = val
|
||||
self.set_3d_position(**pos)
|
||||
|
||||
z = property(fget=get_z, fset=set_z)
|
||||
|
||||
def get_attributes(self):
|
||||
"""Retrieves all values of all attributes from this object and displays them in a dictionary whose keys are determined by this object's attribute_mapping"""
|
||||
res = {}
|
||||
for k in self.attribute_mapping:
|
||||
try:
|
||||
res[k] = self.get_attribute(k)
|
||||
except BassError:
|
||||
pass
|
||||
return res
|
@@ -1,57 +0,0 @@
|
||||
import collections
|
||||
import ctypes
|
||||
from sound_lib.external import pybass
|
||||
from sound_lib.main import bass_call, bass_call_0
|
||||
|
||||
class BassConfig(collections.Mapping):
|
||||
config_map = {
|
||||
'3d_algorithm': pybass.BASS_CONFIG_3DALGORITHM,
|
||||
'buffer': pybass.BASS_CONFIG_BUFFER ,
|
||||
'curve_vol': pybass.BASS_CONFIG_CURVE_VOL,
|
||||
'curve_pan': pybass.BASS_CONFIG_CURVE_PAN,
|
||||
'dev_buffer': pybass.BASS_CONFIG_DEV_BUFFER,
|
||||
'dev_default': pybass.BASS_CONFIG_DEV_DEFAULT,
|
||||
'float_dsp': pybass.BASS_CONFIG_FLOATDSP,
|
||||
'gvol_music': pybass.BASS_CONFIG_GVOL_MUSIC,
|
||||
'gvol_sample': pybass.BASS_CONFIG_GVOL_SAMPLE,
|
||||
'gvol_stream': pybass.BASS_CONFIG_GVOL_STREAM,
|
||||
'music_virtual': pybass.BASS_CONFIG_MUSIC_VIRTUAL,
|
||||
'net_agent': pybass.BASS_CONFIG_NET_AGENT,
|
||||
'net_buffer': pybass.BASS_CONFIG_NET_BUFFER,
|
||||
'net_passive': pybass.BASS_CONFIG_NET_PASSIVE,
|
||||
'net_playlist': pybass.BASS_CONFIG_NET_PLAYLIST,
|
||||
'net_prebuf': pybass.BASS_CONFIG_NET_PREBUF,
|
||||
'net_proxy': pybass.BASS_CONFIG_NET_PROXY,
|
||||
'net_read_timeout': pybass.BASS_CONFIG_NET_READTIMEOUT,
|
||||
'net_timeout': pybass.BASS_CONFIG_NET_TIMEOUT,
|
||||
'pause_no_play': pybass.BASS_CONFIG_PAUSE_NOPLAY,
|
||||
'rec_buffer': pybass.BASS_CONFIG_REC_BUFFER,
|
||||
'src': pybass.BASS_CONFIG_SRC,
|
||||
'src_sample': pybass.BASS_CONFIG_SRC_SAMPLE,
|
||||
'unicode': pybass.BASS_CONFIG_UNICODE,
|
||||
'update_period': pybass.BASS_CONFIG_UPDATEPERIOD,
|
||||
'update_threads': pybass.BASS_CONFIG_UPDATETHREADS,
|
||||
'verify': pybass.BASS_CONFIG_VERIFY,
|
||||
'vista_speakers': pybass.BASS_CONFIG_VISTA_SPEAKERS,
|
||||
}
|
||||
|
||||
ptr_config = (pybass.BASS_CONFIG_NET_AGENT, pybass.BASS_CONFIG_NET_PROXY)
|
||||
|
||||
def __getitem__(self, key):
|
||||
key = self.config_map.get(key, key)
|
||||
if key in self.ptr_config:
|
||||
return ctypes.string_at(bass_call(pybass.BASS_GetConfigPtr, key))
|
||||
return bass_call_0(pybass.BASS_GetConfig, key)
|
||||
|
||||
def __setitem__(self, key, val):
|
||||
key = self.config_map.get(key, key)
|
||||
if key in self.ptr_config:
|
||||
return bass_call(pybass.BASS_SetConfigPtr, key, ctypes.create_string_buffer(val))
|
||||
return bass_call(pybass.BASS_SetConfig, key, val)
|
||||
|
||||
def __iter__(self):
|
||||
for key in self.config_map.keys():
|
||||
yield key
|
||||
|
||||
def __len__(self):
|
||||
return len(self.config_map)
|
@@ -1 +0,0 @@
|
||||
from .tempo import Tempo
|
@@ -1,39 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from sound_lib.external import pybass
|
||||
from .effect import SoundEffect
|
||||
|
||||
class Chorus(SoundEffect):
|
||||
effect_type = pybass.BASS_FX_DX8_CHORUS
|
||||
struct = pybass.BASS_DX8_CHORUS
|
||||
|
||||
class Echo(SoundEffect):
|
||||
effect_type = pybass.BASS_FX_DX8_ECHO
|
||||
struct = pybass.BASS_DX8_ECHO
|
||||
|
||||
class Compressor(SoundEffect):
|
||||
effect_type = pybass.BASS_FX_DX8_COMPRESSOR
|
||||
struct = pybass.BASS_DX8_COMPRESSOR
|
||||
|
||||
class Reverb(SoundEffect):
|
||||
effect_type = pybass.BASS_FX_DX8_REVERB
|
||||
struct = pybass.BASS_DX8_REVERB
|
||||
|
||||
class Distortion(SoundEffect):
|
||||
effect_type = pybass.BASS_FX_DX8_DISTORTION
|
||||
struct = pybass.BASS_DX8_DISTORTION
|
||||
|
||||
class Flanger(SoundEffect):
|
||||
effect_type = pybass.BASS_FX_DX8_FLANGER
|
||||
struct = pybass.BASS_DX8_FLANGER
|
||||
|
||||
class Gargle(SoundEffect):
|
||||
effect_type = pybass.BASS_FX_DX8_GARGLE
|
||||
struct = pybass.BASS_DX8_GARGLE
|
||||
|
||||
class I3DL2Reverb(SoundEffect):
|
||||
effect_type = pybass.BASS_FX_DX8_I3DL2REVERB
|
||||
struct = pybass.BASS_DX8_I3DL2REVERB
|
||||
|
||||
class ParamEq(SoundEffect):
|
||||
effect_type = pybass.BASS_FX_DX8_PARAMEQ
|
||||
struct = pybass.BASS_DX8_PARAMEQ
|
@@ -1,14 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from sound_lib.external import pybass_fx
|
||||
from .effect import SoundEffect
|
||||
|
||||
class Volume(SoundEffect):
|
||||
effect_type = pybass_fx.BASS_FX_BFX_VOLUME
|
||||
struct = pybass_fx.BASS_BFX_VOLUME
|
||||
|
||||
class PeakEq(SoundEffect):
|
||||
effect_type = pybass_fx.BASS_FX_BFX_PEAKEQ
|
||||
struct = pybass_fx.BASS_BFX_PEAKEQ
|
||||
class DAmp(SoundEffect):
|
||||
effect_type = pybass_fx.BASS_FX_BFX_DAMP
|
||||
struct = pybass_fx.BASS_BFX_DAMP
|
@@ -1,71 +0,0 @@
|
||||
from future.builtins import object
|
||||
from sound_lib.main import bass_call
|
||||
import ctypes
|
||||
from sound_lib.external import pybass
|
||||
import string #for the alphabet!
|
||||
|
||||
class SoundEffect(object):
|
||||
|
||||
def __init__(self, channel, type=None, priority=0):
|
||||
self.original_channel = channel
|
||||
if hasattr(channel, 'handle'):
|
||||
channel = channel.handle
|
||||
if type is None:
|
||||
type = self.effect_type
|
||||
self.effect_type = type
|
||||
self.priority = priority
|
||||
self.handle = bass_call(pybass.BASS_ChannelSetFX, channel, type, priority)
|
||||
|
||||
def get_parameters(self):
|
||||
"""Retrieves the parameters of an effect."""
|
||||
res = {}
|
||||
params = self.struct()
|
||||
bass_call(pybass.BASS_FXGetParameters, self.handle, ctypes.pointer(params))
|
||||
for f in params._fields_:
|
||||
res[f[0]] = getattr(params, f[0])
|
||||
return res
|
||||
|
||||
def set_parameters(self, parameters):
|
||||
params = self.struct()
|
||||
for p, v in parameters.items():
|
||||
setattr(params, p, v)
|
||||
bass_call(pybass.BASS_FXSetParameters, self.handle, ctypes.pointer(params))
|
||||
|
||||
def __dir__(self):
|
||||
res = dir(self.__class__)
|
||||
return res + self._get_pythonic_effect_fields()
|
||||
|
||||
def _get_effect_fields(self):
|
||||
return [i[0] for i in self.struct._fields_]
|
||||
|
||||
def _get_pythonic_effect_fields(self):
|
||||
return [self._bass_to_python(i) for i in self._get_effect_fields() if not i.startswith('_') ]
|
||||
|
||||
def _bass_to_python(self, func):
|
||||
for c in string.ascii_lowercase:
|
||||
func = func.replace(c.upper(), '_%s' % c)
|
||||
if func.startswith('_'):
|
||||
func = func[1:]
|
||||
return func[2:]
|
||||
|
||||
def _python_to_bass(self, func):
|
||||
for c in string.ascii_lowercase:
|
||||
func = func.replace('_%s' % c, c.upper())
|
||||
func = '%s%s' % (func[0].upper(), func[1:])
|
||||
for f in self._get_effect_fields():
|
||||
if f.endswith(func):
|
||||
func = f
|
||||
return func
|
||||
|
||||
def __getattr__(self, attr):
|
||||
return self.get_parameters()[self._python_to_bass(attr)]
|
||||
|
||||
def __setattr__(self, attr, val):
|
||||
if attr not in self._get_pythonic_effect_fields():
|
||||
return super(SoundEffect, self).__setattr__(attr, val)
|
||||
params = self.get_parameters()
|
||||
key = self._python_to_bass(attr)
|
||||
if key not in params:
|
||||
raise AttributeError('Unable to set attribute, suspect issue with base name-munging code')
|
||||
params[key] = val
|
||||
self.set_parameters(params)
|
@@ -1,65 +0,0 @@
|
||||
import ctypes
|
||||
from sound_lib.external import pybass, pybass_fx
|
||||
from sound_lib.stream import BaseStream
|
||||
from sound_lib.channel import Channel
|
||||
from sound_lib.main import bass_call, bass_call_0
|
||||
|
||||
class Tempo(BaseStream):
|
||||
|
||||
def __init__(self, channel, flags=0, loop=False, software=False, three_d=False, sample_fx=False, autofree=False, decode=False, free_source=False):
|
||||
flags = flags | self.flags_for(loop=False, software=False, three_d=False, sample_fx=False, autofree=False, decode=False, free_source=False)
|
||||
self.channel = channel
|
||||
if isinstance(channel, Channel):
|
||||
channel = channel.handle
|
||||
handle = bass_call(pybass_fx.BASS_FX_TempoCreate, channel, flags)
|
||||
super(Tempo, self).__init__(handle)
|
||||
self.add_attributes_to_mapping(
|
||||
tempo=pybass_fx.BASS_ATTRIB_TEMPO,
|
||||
tempo_pitch=pybass_fx.BASS_ATTRIB_TEMPO_PITCH,
|
||||
tempo_freq=pybass_fx.BASS_ATTRIB_TEMPO_FREQ,
|
||||
)
|
||||
|
||||
|
||||
@property
|
||||
def tempo(self):
|
||||
"""The tempo of a channel."""
|
||||
return self.get_attribute(pybass_fx.BASS_ATTRIB_TEMPO)
|
||||
|
||||
@tempo.setter
|
||||
def tempo(self, val):
|
||||
self.set_attribute('tempo', val)
|
||||
|
||||
@property
|
||||
def tempo_pitch(self):
|
||||
return self.get_attribute('tempo_pitch')
|
||||
|
||||
@tempo_pitch.setter
|
||||
def tempo_pitch(self, val):
|
||||
self.set_attribute('tempo_pitch', val)
|
||||
|
||||
@property
|
||||
def tempo_freq(self):
|
||||
return self.get_attribute('tempo_freq')
|
||||
|
||||
@tempo_freq.setter
|
||||
def tempo_freq(self, val):
|
||||
self.set_attribute('tempo_freq', val)
|
||||
|
||||
def setup_flag_mapping(self):
|
||||
super(Tempo, self).setup_flag_mapping()
|
||||
self.flag_mapping.update({
|
||||
'free_source': pybass_fx.BASS_FX_FREESOURCE,
|
||||
})
|
||||
|
||||
def get_source(self):
|
||||
source = pybass_fx.BASS_FX_TempoGetSource(self.handle)
|
||||
if source == self.channel.handle:
|
||||
source = self.channel
|
||||
return source
|
||||
|
||||
source = property(fget=get_source)
|
||||
|
||||
def get_rate_ratio(self):
|
||||
return bass_call(pybass_fx.BASS_FX_TempoGetRateRatio, self.handle)
|
||||
|
||||
rate_ratio = property(fget=get_rate_ratio)
|
@@ -1,81 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from .external import pybass, pybassenc
|
||||
from .main import bass_call, bass_call_0, FlagObject
|
||||
|
||||
class Encoder(FlagObject):
|
||||
|
||||
def setup_flag_mapping(self):
|
||||
#super(Encoder, self).setup_flag_mapping()
|
||||
self.flag_mapping = {
|
||||
'pcm': pybassenc.BASS_ENCODE_PCM,
|
||||
'no_header': pybassenc.BASS_ENCODE_NOHEAD,
|
||||
'rf64': pybassenc.BASS_ENCODE_RF64,
|
||||
'big_endian': pybassenc.BASS_ENCODE_BIGEND,
|
||||
'fp_8bit': pybassenc.BASS_ENCODE_FP_8BIT,
|
||||
'fp_16bit': pybassenc.BASS_ENCODE_FP_16BIT,
|
||||
'fp_24bit': pybassenc.BASS_ENCODE_FP_24BIT,
|
||||
'fp_32bit': pybassenc.BASS_ENCODE_FP_32BIT,
|
||||
'queue': pybassenc.BASS_ENCODE_QUEUE,
|
||||
'limit': pybassenc.BASS_ENCODE_LIMIT,
|
||||
'no_limit': pybassenc.BASS_ENCODE_CAST_NOLIMIT,
|
||||
'pause': pybassenc.BASS_ENCODE_PAUSE,
|
||||
'autofree': pybassenc.BASS_ENCODE_AUTOFREE,
|
||||
'unicode': pybass.BASS_UNICODE,
|
||||
}
|
||||
|
||||
def __init__(self, source, command_line, pcm=False, no_header=False, rf64=False, big_endian=False, fp_8bit=False, fp_16bit=False, fp_24bit=False, fp_32bit=False, queue=False, limit=False, no_limit=False, pause=True, autofree=False, callback=None, user=None):
|
||||
self.setup_flag_mapping()
|
||||
flags = self.flags_for(pcm=pcm, no_header=no_header, rf64=rf64, big_endian=big_endian, fp_8bit=fp_8bit, fp_16bit=fp_16bit, fp_24bit=fp_24bit, fp_32bit=fp_32bit, queue=queue, limit=limit, no_limit=no_limit, pause=pause, autofree=autofree) #fwiw!
|
||||
self.source = source
|
||||
source_handle = source.handle
|
||||
if callback is None:
|
||||
callback = lambda *a: None
|
||||
callback = pybassenc.ENCODEPROC(callback)
|
||||
self.callback = callback
|
||||
self.handle = bass_call(pybassenc.BASS_Encode_Start, source_handle, command_line, flags, callback, user)
|
||||
|
||||
@property
|
||||
def paused(self):
|
||||
return bass_call_0(pybassenc.BASS_Encode_IsActive, self.handle) == pybass.BASS_ACTIVE_PAUSED
|
||||
|
||||
@paused.setter
|
||||
def paused(self, paused):
|
||||
return bass_call(pybassenc.BASS_Encode_SetPaused, self.handle, paused)
|
||||
|
||||
def is_stopped(self):
|
||||
return bass_call_0(pybassenc.BASS_Encode_IsActive, self.handle) == pybass.BASS_ACTIVE_STOPPED
|
||||
|
||||
|
||||
def stop(self):
|
||||
return bass_call(pybassenc.BASS_Encode_Stop, self.handle)
|
||||
|
||||
class BroadcastEncoder(Encoder):
|
||||
|
||||
def __init__(self, source_encoder, server, password, content, name=None, url=None, genre=None, description=None, headers=None, bitrate=0, public=False):
|
||||
contents = {
|
||||
'mp3': pybassenc.BASS_ENCODE_TYPE_MP3,
|
||||
'ogg': pybassenc.BASS_ENCODE_TYPE_OGG,
|
||||
'aac': pybassenc.BASS_ENCODE_TYPE_AAC
|
||||
}
|
||||
if content in contents:
|
||||
content = contents[content]
|
||||
self.source_encoder = source_encoder
|
||||
handle = source_encoder.handle
|
||||
self.server = server
|
||||
self.password = password
|
||||
self.status = bass_call(pybassenc.BASS_Encode_CastInit, handle, server, password, content, name, url, genre, description, headers, bitrate, public)
|
||||
|
||||
def set_title(self, title=None, url=None):
|
||||
return bass_call(pybassenc.BASS_Encode_CastSetTitle, self.source_encoder.handle, title, url)
|
||||
|
||||
def get_stats(self, type, password=None):
|
||||
types = {
|
||||
'shoutcast': pybassenc.BASS_ENCODE_STATS_SHOUT,
|
||||
'icecast': pybassenc.BASS_ENCODE_STATS_ICE,
|
||||
'icecast_server': pybassenc.BASS_ENCODE_STATS_ICESERV,
|
||||
}
|
||||
if type in types:
|
||||
type = types[type]
|
||||
if password is None:
|
||||
password = self.password
|
||||
return bass_call(pybassenc.BASS_Encode_CastGetStats, self.handle, type, password)
|
9
src/sound_lib/external/__init__.py
vendored
9
src/sound_lib/external/__init__.py
vendored
@@ -1,9 +0,0 @@
|
||||
import platform
|
||||
#if platform.system() == 'Windows':
|
||||
# import sound_lib.external.pybasswma
|
||||
if platform.system() != 'Darwin':
|
||||
import sound_lib.external.pybass_aac
|
||||
import sound_lib.external.pybass_alac
|
||||
import sound_lib.external.pybassopus
|
||||
import sound_lib.external.pybassflac
|
||||
import sound_lib.external.pybassmidi
|
9
src/sound_lib/external/paths.py
vendored
9
src/sound_lib/external/paths.py
vendored
@@ -1,9 +0,0 @@
|
||||
import os
|
||||
from platform_utils.paths import module_path, is_frozen, embedded_data_path
|
||||
|
||||
if is_frozen():
|
||||
x86_path = os.path.join(embedded_data_path(), 'sound_lib', 'lib', 'x86')
|
||||
x64_path = os.path.join(embedded_data_path(), 'sound_lib', 'lib', 'x64')
|
||||
else:
|
||||
x86_path = os.path.join(module_path(), '..', 'lib', 'x86')
|
||||
x64_path = os.path.join(module_path(), '..', 'lib', 'x64')
|
1120
src/sound_lib/external/pybass.py
vendored
1120
src/sound_lib/external/pybass.py
vendored
File diff suppressed because it is too large
Load Diff
54
src/sound_lib/external/pybass_aac.py
vendored
54
src/sound_lib/external/pybass_aac.py
vendored
@@ -1,54 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
# Copyright(c) Max Kolosov 2009 maxkolosov@inbox.ru
|
||||
# http://vosolok2008.narod.ru
|
||||
# BSD license
|
||||
|
||||
__version__ = '0.1'
|
||||
__versionTime__ = '2009-11-15'
|
||||
__author__ = 'Max Kolosov <maxkolosov@inbox.ru>'
|
||||
__doc__ = '''
|
||||
pybass_aac.py - is ctypes python module for
|
||||
BASS_AAC - extension to the BASS audio library that enables the playback
|
||||
of Advanced Audio Coding and MPEG-4 streams (http://www.maresweb.de).
|
||||
'''
|
||||
|
||||
import os, sys, ctypes
|
||||
from . import pybass
|
||||
from .paths import x86_path, x64_path
|
||||
import libloader
|
||||
|
||||
bass_aac_module = libloader.load_library('bass_aac', x86_path=x86_path, x64_path=x64_path)
|
||||
func_type = libloader.get_functype()
|
||||
#Register the plugin with the Bass plugin system.
|
||||
pybass.BASS_PluginLoad(libloader.find_library_path('bass_aac', x86_path=x86_path, x64_path=x64_path), 0)
|
||||
|
||||
QWORD = pybass.QWORD
|
||||
HSTREAM = pybass.HSTREAM
|
||||
DOWNLOADPROC = pybass.DOWNLOADPROC
|
||||
BASS_FILEPROCS = pybass.BASS_FILEPROCS
|
||||
|
||||
|
||||
# Additional BASS_SetConfig options
|
||||
BASS_CONFIG_MP4_VIDEO = 0x10700 # play the audio from MP4 videos
|
||||
|
||||
# Additional tags available from BASS_StreamGetTags (for MP4 files)
|
||||
BASS_TAG_MP4 = 7 # MP4/iTunes metadata
|
||||
|
||||
BASS_AAC_STEREO = 0x400000 # downmatrix to stereo
|
||||
|
||||
# BASS_CHANNELINFO type
|
||||
BASS_CTYPE_STREAM_AAC = 0x10b00 # AAC
|
||||
BASS_CTYPE_STREAM_MP4 = 0x10b01 # MP4
|
||||
|
||||
|
||||
#HSTREAM BASSAACDEF(BASS_AAC_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags);
|
||||
BASS_AAC_StreamCreateFile = func_type(HSTREAM, ctypes.c_byte, ctypes.c_void_p, QWORD, QWORD, ctypes.c_ulong)(('BASS_AAC_StreamCreateFile', bass_aac_module))
|
||||
#HSTREAM BASSAACDEF(BASS_AAC_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user);
|
||||
BASS_AAC_StreamCreateURL = func_type(HSTREAM, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_ulong, DOWNLOADPROC, ctypes.c_void_p)(('BASS_AAC_StreamCreateURL', bass_aac_module))
|
||||
#HSTREAM BASSAACDEF(BASS_AAC_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *procs, void *user);
|
||||
BASS_AAC_StreamCreateFileUser = func_type(HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_FILEPROCS), ctypes.c_void_p)(('BASS_AAC_StreamCreateFileUser', bass_aac_module))
|
||||
#HSTREAM BASSAACDEF(BASS_MP4_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags);
|
||||
BASS_MP4_StreamCreateFile = func_type(HSTREAM, ctypes.c_byte, ctypes.c_void_p, QWORD, QWORD, ctypes.c_ulong)(('BASS_MP4_StreamCreateFile', bass_aac_module))
|
||||
#HSTREAM BASSAACDEF(BASS_MP4_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *procs, void *user);
|
||||
BASS_MP4_StreamCreateFileUser = func_type(HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_FILEPROCS), ctypes.c_void_p)(('BASS_MP4_StreamCreateFileUser', bass_aac_module))
|
||||
|
24
src/sound_lib/external/pybass_alac.py
vendored
24
src/sound_lib/external/pybass_alac.py
vendored
@@ -1,24 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
"BASS_ALAC wrapper by Christopher Toth"""
|
||||
|
||||
import ctypes
|
||||
import os
|
||||
from . import pybass
|
||||
from .paths import x86_path, x64_path
|
||||
import libloader
|
||||
|
||||
bass_fx_module = libloader.load_library('bass_alac', x86_path=x86_path, x64_path=x64_path)
|
||||
func_type = libloader.get_functype()
|
||||
|
||||
pybass.BASS_PluginLoad(libloader.find_library_path('bass_alac', x86_path=x86_path, x64_path=x64_path), 0)
|
||||
|
||||
BASS_TAG_MP4 = 7
|
||||
BASS_CTYPE_STREAM_ALAC = 0x10e00
|
||||
|
||||
|
||||
#HSTREAM BASSALACDEF(BASS_ALAC_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags);
|
||||
BASS_ALAC_StreamCreateFile = func_type(pybass.HSTREAM, ctypes.c_byte, ctypes.c_void_p, pybass.QWORD, pybass.QWORD, ctypes.c_ulong)
|
||||
|
||||
#HSTREAM BASSALACDEF(BASS_ALAC_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *procs, void *user);
|
||||
BASS_ALAC_StreamCreateFileUser = func_type(pybass.HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_void_p)
|
||||
|
384
src/sound_lib/external/pybass_fx.py
vendored
384
src/sound_lib/external/pybass_fx.py
vendored
@@ -1,384 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from future.builtins import range
|
||||
"BASS_FX wrapper by Christopher Toth"""
|
||||
|
||||
import ctypes
|
||||
import os
|
||||
from . import pybass
|
||||
from .paths import x86_path, x64_path
|
||||
import libloader
|
||||
|
||||
bass_fx_module = libloader.load_library('bass_fx', x86_path=x86_path, x64_path=x64_path)
|
||||
func_type = libloader.get_functype()
|
||||
|
||||
|
||||
#Error codes returned by BASS_ErrorGetCode
|
||||
BASS_ERROR_FX_NODECODE = 4000
|
||||
BASS_ERROR_FX_BPMINUSE = 4001
|
||||
|
||||
#Tempo / Reverse / BPM / Beat flag
|
||||
BASS_FX_FREESOURCE = 0x10000
|
||||
|
||||
#BASS_FX Version
|
||||
BASS_FX_GetVersion = func_type(ctypes.c_ulong)(('BASS_FX_GetVersion', bass_fx_module))
|
||||
|
||||
|
||||
"""D S P (Digital Signal Processing)"""
|
||||
|
||||
"""
|
||||
Multi-channel order of each channel is as follows:
|
||||
3 channels left-front, right-front, center.
|
||||
4 channels left-front, right-front, left-rear/side, right-rear/side.
|
||||
6 channels (5.1) left-front, right-front, center, LFE, left-rear/side, right-rear/side.
|
||||
8 channels (7.1) left-front, right-front, center, LFE, left-rear/side, right-rear/side, left-rear center, right-rear center.
|
||||
"""
|
||||
|
||||
#DSP channels flags
|
||||
BASS_BFX_CHANALL = -1 #all channels at once (as by default)
|
||||
BASS_BFX_CHANNONE = 0 #disable an effect for all channels
|
||||
BASS_BFX_CHAN1 = 1 #left-front channel
|
||||
BASS_BFX_CHAN2 = 2 #right-front channel
|
||||
BASS_BFX_CHAN3 = 4 #see above info
|
||||
BASS_BFX_CHAN4 = 8 #see above info
|
||||
BASS_BFX_CHAN5 = 16
|
||||
BASS_BFX_CHAN6 = 32
|
||||
BASS_BFX_CHAN7 = 64
|
||||
BASS_BFX_CHAN8 = 128
|
||||
|
||||
#DSP effects
|
||||
(
|
||||
BASS_FX_BFX_ROTATE,
|
||||
BASS_FX_BFX_ECHO,
|
||||
BASS_FX_BFX_FLANGER,
|
||||
BASS_FX_BFX_VOLUME,
|
||||
BASS_FX_BFX_PEAKEQ,
|
||||
BASS_FX_BFX_REVERB,
|
||||
BASS_FX_BFX_LPF,
|
||||
BASS_FX_BFX_MIX,
|
||||
BASS_FX_BFX_DAMP,
|
||||
BASS_FX_BFX_AUTOWAH,
|
||||
BASS_FX_BFX_ECHO2,
|
||||
BASS_FX_BFX_PHASER,
|
||||
BASS_FX_BFX_ECHO3,
|
||||
BASS_FX_BFX_CHORUS,
|
||||
BASS_FX_BFX_APF,
|
||||
BASS_FX_BFX_COMPRESSOR,
|
||||
BASS_FX_BFX_DISTORTION,
|
||||
BASS_FX_BFX_COMPRESSOR2,
|
||||
BASS_FX_BFX_VOLUME_ENV,
|
||||
BASS_FX_BFX_BQF,
|
||||
) = range(0x10000, 0x10000+20)
|
||||
|
||||
#BiQuad filters
|
||||
(
|
||||
BASS_BFX_BQF_LOWPASS,
|
||||
BASS_BFX_BQF_HIGHPASS,
|
||||
BASS_BFX_BQF_BANDPASS, #constant 0 dB peak gain
|
||||
BASS_BFX_BQF_BANDPASS_Q, #constant skirt gain, peak gain = Q
|
||||
BASS_BFX_BQF_NOTCH,
|
||||
BASS_BFX_BQF_ALLPASS,
|
||||
BASS_BFX_BQF_PEAKINGEQ,
|
||||
BASS_BFX_BQF_LOWSHELF,
|
||||
BASS_BFX_BQF_HIGHSHELF,
|
||||
) = range(9)
|
||||
|
||||
#Echo
|
||||
class BASS_BFX_ECHO(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fLevel', ctypes.c_float), #[0....1....n] linear
|
||||
('lDelay', ctypes.c_int), #[1200..30000]
|
||||
]
|
||||
|
||||
#Flanger
|
||||
class BASS_BFX_FLANGER(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fWetDry', ctypes.c_float), #[0....1....n] linear
|
||||
('fSpeed', ctypes.c_float), #[0......0.09]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#volume
|
||||
class BASS_BFX_VOLUME(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s or 0 for global volume control
|
||||
('fVolume', ctypes.c_float), #[0....1....n] linear
|
||||
]
|
||||
|
||||
#Peaking Equalizer
|
||||
class BASS_BFX_PEAKEQ(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('lBand', ctypes.c_int), #[0...............n] more bands means more memory & cpu usage
|
||||
('fBandwidth', ctypes.c_float), #[0.1...........<10] in octaves - fQ is not in use (Bandwidth has a priority over fQ)
|
||||
('fQ', ctypes.c_float), #[0...............1] the EE kinda definition (linear) (if Bandwidth is not in use)
|
||||
('fCenter', ctypes.c_float), #[1Hz..<info.freq/2] in Hz
|
||||
('fGain', ctypes.c_float), #[-15dB...0...+15dB] in dB
|
||||
('lChannel', ctypes.c_float), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Reverb
|
||||
class BASS_BFX_REVERB(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fLevel', ctypes.c_float), #[0....1....n] linear
|
||||
('lDelay', ctypes.c_int), #[1200..10000]
|
||||
]
|
||||
|
||||
#Low Pass Filter
|
||||
class BASS_BFX_LPF(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fResonance', ctypes.c_float), #[0.01...........10]
|
||||
('fCutOffFreq', ctypes.c_float), #[1Hz...info.freq/2] cutoff frequency
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Swap, remap and mix
|
||||
class BASS_BFX_MIX(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('lChannel', ctypes.c_int), #an array of channels to mix using BASS_BFX_CHANxxx flag/s (lChannel[0] is left channel...)
|
||||
]
|
||||
|
||||
#Dynamic Amplification
|
||||
class BASS_BFX_DAMP(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fTarget', ctypes.c_float), #target volume level [0<......1] linear
|
||||
('fQuiet', ctypes.c_float), #quiet volume level [0.......1] linear
|
||||
('fRate', ctypes.c_float), #amp adjustment rate [0.......1] linear
|
||||
('fGain', ctypes.c_float), #amplification level [0...1...n] linear
|
||||
('fDelay', ctypes.c_float), #delay in seconds before increasing level [0.......n] linear
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Auto WAH
|
||||
class BASS_BFX_AUTOWAH(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fDryMix', ctypes.c_float), #dry (unaffected) signal mix [-2......2]
|
||||
('fWetMix', ctypes.c_float), #wet (affected) signal mix [-2......2]
|
||||
('fFeedback', ctypes.c_float), #feedback [-1......1]
|
||||
('fRate', ctypes.c_float), #rate of sweep in cycles per second [0<....<10]
|
||||
('fRange', ctypes.c_float), #sweep range in octaves [0<....<10]
|
||||
('fFreq', ctypes.c_float), #base frequency of sweep Hz [0<...1000]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Echo 2
|
||||
class BASS_BFX_ECHO2(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fDryMix', ctypes.c_float), #dry (unaffected) signal mix [-2......2]
|
||||
('fWetMix', ctypes.c_float), #wet (affected) signal mix [-2......2]
|
||||
('fFeedback', ctypes.c_float), #feedback [-1......1]
|
||||
('fDelay', ctypes.c_float), #delay sec [0<......n]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Phaser
|
||||
class BASS_BFX_PHASER(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fDryMix', ctypes.c_float), #dry (unaffected) signal mix [-2......2]
|
||||
('fWetMix', ctypes.c_float), #wet (affected) signal mix [-2......2]
|
||||
('fFeedback', ctypes.c_float), #feedback [-1......1]
|
||||
('fRate', ctypes.c_float), #rate of sweep in cycles per second [0<....<10]
|
||||
('fRange', ctypes.c_float), #sweep range in octaves [0<....<10]
|
||||
('fFreq', ctypes.c_float), #base frequency of sweep [0<...1000]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Echo 3
|
||||
class BASS_BFX_ECHO3(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fDryMix', ctypes.c_float), #dry (unaffected) signal mix [-2......2]
|
||||
('fWetMix', ctypes.c_float), #wet (affected) signal mix [-2......2]
|
||||
('fDelay', ctypes.c_float), #delay sec [0<......n]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Chorus
|
||||
class BASS_BFX_CHORUS(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fDryMix', ctypes.c_float), #dry (unaffected) signal mix [-2......2]
|
||||
('fWetMix', ctypes.c_float), #wet (affected) signal mix [-2......2]
|
||||
('fFeedback', ctypes.c_float), #feedback [-1......1]
|
||||
('fMinSweep', ctypes.c_float), #minimal delay ms [0<...6000]
|
||||
('fMaxSweep', ctypes.c_float), #maximum delay ms [0<...6000]
|
||||
('fRate', ctypes.c_float), #rate ms/s [0<...1000]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#All Pass Filter
|
||||
class BASS_BFX_APF(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fGain', ctypes.c_float), #reverberation time [-1=<..<=1]
|
||||
('fDelay', ctypes.c_float), #delay sec [0<....<=n]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Compressor
|
||||
class BASS_BFX_COMPRESSOR(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fThreshold', ctypes.c_float), #compressor threshold [0<=...<=1]
|
||||
('fAttacktime', ctypes.c_float), #attack time ms [0<.<=1000]
|
||||
('fReleasetime', ctypes.c_float), #release time ms [0<.<=5000]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Distortion
|
||||
class BASS_BFX_DISTORTION(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fDrive', ctypes.c_float), #distortion drive [0<=...<=5]
|
||||
('fDryMix', ctypes.c_float), #dry (unaffected) signal mix [-5<=..<=5]
|
||||
('fWetMix', ctypes.c_float), #wet (affected) signal mix [-5<=..<=5]
|
||||
('fFeedback', ctypes.c_float), #feedback [-1<=..<=1]
|
||||
('fVolume', ctypes.c_float), #distortion volume [0=<...<=2]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
#Compressor 2
|
||||
class BASS_BFX_COMPRESSOR2(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('fGain', ctypes.c_float), #output gain of signal after compression [-60....60] in dB
|
||||
('fThreshold', ctypes.c_float), #point at which compression begins [-60.....0] in dB
|
||||
('fRatio', ctypes.c_float), #compression ratio [1.......n]
|
||||
('fAttack', ctypes.c_float), #attack time in ms [0.01.1000]
|
||||
('fRelease', ctypes.c_float), #release time in ms [0.01.5000]
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
class BASS_BFX_ENV_NODE(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('pos', ctypes.c_long), #node position in seconds (1st envelope node must be at position 0)
|
||||
('val', ctypes.c_float), #node value
|
||||
]
|
||||
|
||||
#Volume envelope
|
||||
class BASS_BFX_VOLUME_ENV(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
('lNodeCount', ctypes.c_int), #number of nodes
|
||||
('pNodes', BASS_BFX_ENV_NODE), #the nodes
|
||||
('bFollow', ctypes.c_bool), #follow source position
|
||||
]
|
||||
|
||||
#BiQuad Filters
|
||||
|
||||
class BASS_BFX_BQF(ctypes.Structure):
|
||||
_fields_ = [
|
||||
('lFilter', ctypes.c_int), #BASS_BFX_BQF_xxx filter types
|
||||
('fCenter', ctypes.c_float), #[1Hz..<info.freq/2] Cutoff (central) frequency in Hz
|
||||
('fGain', ctypes.c_float), #[-15dB...0...+15dB] Used only for PEAKINGEQ and Shelving filters in dB
|
||||
('fBandwidth', ctypes.c_float), #[0.1...........<10] Bandwidth in octaves (fQ is not in use (fBandwidth has a priority over fQ))
|
||||
#(between -3 dB frequencies for BANDPASS and NOTCH or between midpoint
|
||||
#(fGgain/2) gain frequencies for PEAKINGEQ)
|
||||
('fQ', ctypes.c_float), #[0.1.............1] The EE kinda definition (linear) (if fBandwidth is not in use)
|
||||
('fS', ctypes.c_float), #[0.1.............1] A "shelf slope" parameter (linear) (used only with Shelving filters)
|
||||
#when fS = 1, the shelf slope is as steep as you can get it and remain monotonically
|
||||
#increasing or decreasing gain with frequency.
|
||||
('lChannel', ctypes.c_int), #BASS_BFX_CHANxxx flag/s
|
||||
]
|
||||
|
||||
"""TEMPO / PITCH SCALING / SAMPLERATE"""
|
||||
|
||||
"""NOTES: 1. Supported only - mono / stereo - channels
|
||||
2. Enable Tempo supported flags in BASS_FX_TempoCreate and the others to source handle.
|
||||
tempo attributes (BASS_ChannelSet/GetAttribute)"""
|
||||
|
||||
(
|
||||
BASS_ATTRIB_TEMPO,
|
||||
BASS_ATTRIB_TEMPO_PITCH,
|
||||
BASS_ATTRIB_TEMPO_FREQ,
|
||||
) = range(0x10000, 0x10000+3)
|
||||
|
||||
#tempo attributes options
|
||||
#[option] [value]
|
||||
|
||||
(
|
||||
BASS_ATTRIB_TEMPO_OPTION_USE_AA_FILTER, #TRUE (default) / FALSE
|
||||
BASS_ATTRIB_TEMPO_OPTION_AA_FILTER_LENGTH, #32 default (8 .. 128 taps)
|
||||
BASS_ATTRIB_TEMPO_OPTION_USE_QUICKALGO, #TRUE / FALSE (default)
|
||||
BASS_ATTRIB_TEMPO_OPTION_SEQUENCE_MS, #82 default, 0 = automatic
|
||||
BASS_ATTRIB_TEMPO_OPTION_SEEKWINDOW_MS, #28 default, 0 = automatic
|
||||
BASS_ATTRIB_TEMPO_OPTION_OVERLAP_MS, #8 default
|
||||
BASS_ATTRIB_TEMPO_OPTION_PREVENT_CLICK, #TRUE / FALSE (default)
|
||||
) = range(0x10000, 0x10000+7)
|
||||
|
||||
#HSTREAM BASS_FXDEF(BASS_FX_TempoCreate)(DWORD chan, DWORD flags);
|
||||
BASS_FX_TempoCreate = func_type(pybass.HSTREAM, ctypes.c_ulong, ctypes.c_ulong)(('BASS_FX_TempoCreate', bass_fx_module))
|
||||
|
||||
#DWORD BASS_FXDEF(BASS_FX_TempoGetSource)(HSTREAM chan);
|
||||
BASS_FX_TempoGetSource = func_type(ctypes.c_ulong, pybass.HSTREAM)(('BASS_FX_TempoGetSource', bass_fx_module))
|
||||
|
||||
#float BASS_FXDEF(BASS_FX_TempoGetRateRatio)(HSTREAM chan);
|
||||
BASS_FX_TempoGetRateRatio = func_type(ctypes.c_float, pybass.HSTREAM)(('BASS_FX_TempoGetRateRatio', bass_fx_module))
|
||||
|
||||
"""R E V E R S E"""
|
||||
"""NOTES: 1. MODs won't load without BASS_MUSIC_PRESCAN flag.
|
||||
2. Enable Reverse supported flags in BASS_FX_ReverseCreate and the others to source handle."""
|
||||
|
||||
#reverse attribute (BASS_ChannelSet/GetAttribute)
|
||||
BASS_ATTRIB_REVERSE_DIR = 0x11000
|
||||
|
||||
#playback directions
|
||||
BASS_FX_RVS_REVERSE = -1
|
||||
BASS_FX_RVS_FORWARD = 1
|
||||
|
||||
#HSTREAM BASS_FXDEF(BASS_FX_ReverseCreate)(DWORD chan, float dec_block, DWORD flags);
|
||||
BASS_FX_ReverseCreate = func_type(pybass.HSTREAM, ctypes.c_ulong, ctypes.c_float, ctypes.c_ulong)(('BASS_FX_ReverseCreate', bass_fx_module))
|
||||
|
||||
#DWORD BASS_FXDEF(BASS_FX_ReverseGetSource)(HSTREAM chan);
|
||||
BASS_FX_ReverseGetSource = func_type(ctypes.c_ulong, pybass.HSTREAM)(('BASS_FX_ReverseGetSource', bass_fx_module))
|
||||
|
||||
"""B P M (Beats Per Minute)"""
|
||||
|
||||
#bpm flags
|
||||
BASS_FX_BPM_BKGRND = 1 #if in use, then you can do other processing while detection's in progress. Not available in MacOSX yet. (BPM/Beat)
|
||||
BASS_FX_BPM_MULT2 = 2 #if in use, then will auto multiply bpm by 2 (if BPM < minBPM*2)
|
||||
|
||||
#translation options
|
||||
(
|
||||
BASS_FX_BPM_TRAN_X2, #multiply the original BPM value by 2 (may be called only once & will change the original BPM as well!)
|
||||
BASS_FX_BPM_TRAN_2FREQ, #BPM value to Frequency
|
||||
BASS_FX_BPM_TRAN_FREQ2, #Frequency to BPM value
|
||||
BASS_FX_BPM_TRAN_2PERCENT, #BPM value to Percents
|
||||
BASS_FX_BPM_TRAN_PERCENT2 , #Percents to BPM value
|
||||
) = range(5)
|
||||
|
||||
#typedef void (CALLBACK BPMPROCESSPROC)(DWORD chan, float percent);
|
||||
BPMPROCESSPROC = func_type(None, ctypes.c_float)
|
||||
|
||||
#typedef void (CALLBACK BPMPROC)(DWORD chan, float bpm, void *user);
|
||||
BPMPROC = func_type(None, ctypes.c_long, ctypes.c_float, ctypes.c_void_p)
|
||||
|
||||
#float BASS_FXDEF(BASS_FX_BPM_DecodeGet)(DWORD chan, double startSec, double endSec, DWORD minMaxBPM, DWORD flags, BPMPROCESSPROC *proc);
|
||||
BASS_FX_BPM_DecodeGet = func_type(ctypes.c_float, ctypes.c_ulong, ctypes.c_double, ctypes.c_double, ctypes.c_ulong, ctypes.c_ulong, BPMPROCESSPROC)(('BASS_FX_BPM_DecodeGet', bass_fx_module))
|
||||
|
||||
#BOOL BASS_FXDEF(BASS_FX_BPM_CallbackSet)(DWORD handle, BPMPROC *proc, double period, DWORD minMaxBPM, DWORD flags, void *user);
|
||||
BASS_FX_BPM_CallbackSet = func_type(ctypes.c_bool, ctypes.c_ulong, BPMPROC, ctypes.c_double, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p)(('BASS_FX_BPM_CallbackSet', bass_fx_module))
|
||||
|
||||
#BOOL BASS_FXDEF(BASS_FX_BPM_CallbackReset)(DWORD handle);
|
||||
BASS_FX_BPM_CallbackReset = func_type(ctypes.c_bool, ctypes.c_ulong)(('BASS_FX_BPM_CallbackReset', bass_fx_module))
|
||||
|
||||
#float BASS_FXDEF(BASS_FX_BPM_Translate)(DWORD handle, float val2tran, DWORD trans);
|
||||
BASS_FX_BPM_Translate = func_type(ctypes.c_float, ctypes.c_ulong, ctypes.c_float, ctypes.c_ulong)(('BASS_FX_BPM_Translate', bass_fx_module))
|
||||
|
||||
#BOOL BASS_FXDEF(BASS_FX_BPM_Free)(DWORD handle);
|
||||
BASS_FX_BPM_Free = func_type(ctypes.c_bool, ctypes.c_ulong)(('BASS_FX_BPM_Free', bass_fx_module))
|
||||
|
||||
""" Beat """
|
||||
|
||||
#typedef void (CALLBACK BPMBEATPROC)(DWORD chan, double beatpos, void *user);
|
||||
BPMBEATPROC = func_type(None, ctypes.c_ulong, ctypes.c_double, ctypes.c_void_p)
|
||||
|
||||
#BOOL BASS_FXDEF(BASS_FX_BPM_BeatCallbackSet)(DWORD handle, BPMBEATPROC *proc, void *user);
|
||||
BASS_FX_BPM_BeatCallbackSet = func_type(ctypes.c_bool, ctypes.c_ulong, ctypes.c_void_p)(('BASS_FX_BPM_BeatCallbackSet', bass_fx_module))
|
||||
|
||||
#BOOL BASS_FXDEF(BASS_FX_BPM_BeatCallbackReset)(DWORD handle);
|
||||
BASS_FX_BPM_BeatCallbackReset = func_type(ctypes.c_bool, ctypes.c_ulong)(('BASS_FX_BPM_BeatCallbackReset', bass_fx_module))
|
||||
|
||||
#BOOL BASS_FXDEF(BASS_FX_BPM_BeatDecodeGet)(DWORD chan, double startSec, double endSec, DWORD flags, BPMBEATPROC *proc, void *user);
|
||||
BASS_FX_BPM_BeatDecodeGet = func_type(ctypes.c_bool, ctypes.c_ulong, ctypes.c_double, ctypes.c_double, ctypes.c_ulong, BPMBEATPROC, ctypes.c_void_p)(('BASS_FX_BPM_BeatDecodeGet', bass_fx_module))
|
||||
|
||||
#BOOL BASS_FXDEF(BASS_FX_BPM_BeatSetParameters)(DWORD handle, float bandwidth, float centerfreq, float beat_rtime);
|
||||
BASS_FX_BPM_BeatSetParameters = func_type(ctypes.c_bool, ctypes.c_ulong, ctypes.c_float, ctypes.c_float, ctypes.c_float)(('BASS_FX_BPM_BeatSetParameters', bass_fx_module))
|
||||
|
||||
#BOOL BASS_FXDEF(BASS_FX_BPM_BeatGetParameters)(DWORD handle, float *bandwidth, float *centerfreq, float *beat_rtime);
|
||||
BASS_FX_BPM_BeatGetParameters = func_type(ctypes.c_bool, ctypes.c_ulong, ctypes.c_float, ctypes.c_float, ctypes.c_float)(('BASS_FX_BPM_BeatGetParameters', bass_fx_module))
|
||||
|
||||
#BOOL BASS_FXDEF(BASS_FX_BPM_BeatFree)(DWORD handle);
|
||||
BASS_FX_BPM_BeatFree = func_type(ctypes.c_bool, ctypes.c_ulong)(('BASS_FX_BPM_BeatFree', bass_fx_module))
|
170
src/sound_lib/external/pybassenc.py
vendored
170
src/sound_lib/external/pybassenc.py
vendored
@@ -1,170 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
from future.builtins import range
|
||||
"BASSENC wrapper by Christopher Toth"""
|
||||
|
||||
import ctypes
|
||||
import os
|
||||
import platform
|
||||
from . import pybass
|
||||
from .paths import x86_path, x64_path
|
||||
import libloader
|
||||
|
||||
bassenc_module = libloader.load_library('bassenc', x86_path=x86_path, x64_path=x64_path)
|
||||
func_type = libloader.get_functype()
|
||||
|
||||
HENCODE = ctypes.c_ulong #encoder handle
|
||||
|
||||
#Additional error codes returned by BASS_ErrorGetCode
|
||||
BASS_ERROR_ACM_CANCEL = 2000 #ACM codec selection cancelled
|
||||
pybass.error_descriptions[BASS_ERROR_ACM_CANCEL] = "ACM codec selection cancelled"
|
||||
BASS_ERROR_CAST_DENIED = 2100 #access denied (invalid password)
|
||||
pybass.error_descriptions[BASS_ERROR_CAST_DENIED] = "access denied (invalid password)"
|
||||
|
||||
#Additional BASS_SetConfig options
|
||||
BASS_CONFIG_ENCODE_PRIORITY = 0x10300
|
||||
BASS_CONFIG_ENCODE_QUEUE = 0x10301
|
||||
BASS_CONFIG_ENCODE_CAST_TIMEOUT = 0x10310
|
||||
|
||||
#Additional BASS_SetConfigPtr options
|
||||
BASS_CONFIG_ENCODE_CAST_PROXY = 0x10311
|
||||
|
||||
#BASS_Encode_Start flags
|
||||
BASS_ENCODE_NOHEAD = 1 #don't send a WAV header to the encoder
|
||||
BASS_ENCODE_FP_8BIT = 2 #convert floating-point sample data to 8-bit integer
|
||||
BASS_ENCODE_FP_16BIT = 4 #convert floating-point sample data to 16-bit integer
|
||||
BASS_ENCODE_FP_24BIT = 6#convert floating-point sample data to 24-bit integer
|
||||
BASS_ENCODE_FP_32BIT = 8 #convert floating-point sample data to 32-bit integer
|
||||
BASS_ENCODE_BIGEND = 16 #big-endian sample data
|
||||
BASS_ENCODE_PAUSE = 32 #start encoding paused
|
||||
BASS_ENCODE_PCM = 64 #write PCM sample data (no encoder)
|
||||
BASS_ENCODE_RF64 = 128 #send an RF64 header
|
||||
BASS_ENCODE_MONO = 256 #convert to mono (if not already)
|
||||
BASS_ENCODE_QUEUE = 512 #queue data to feed encoder asynchronously
|
||||
BASS_ENCODE_CAST_NOLIMIT = 0x1000 #don't limit casting data rate
|
||||
BASS_ENCODE_LIMIT = 0x2000 #limit data rate to real-time
|
||||
BASS_ENCODE_AUTOFREE = 0x40000 #free the encoder when the channel is freed
|
||||
|
||||
#BASS_Encode_GetACMFormat flags
|
||||
BASS_ACM_DEFAULT = 1 #use the format as default selection
|
||||
BASS_ACM_RATE = 2 #only list formats with same sample rate as the source channel
|
||||
BASS_ACM_CHANS = 4 #only list formats with same number of channels (eg. mono/stereo)
|
||||
BASS_ACM_SUGGEST = 8 #suggest a format (HIWORD=format tag)
|
||||
|
||||
#BASS_Encode_GetCount counts
|
||||
|
||||
(
|
||||
BASS_ENCODE_COUNT_IN, #sent to encoder
|
||||
BASS_ENCODE_COUNT_OUT, #received from encoder
|
||||
BASS_ENCODE_COUNT_CAST, #sent to cast server
|
||||
BASS_ENCODE_COUNT_QUEUE, #queued
|
||||
BASS_ENCODE_COUNT_QUEUE_LIMIT, #queue limit
|
||||
BASS_ENCODE_COUNT_QUEUE_FAIL, #failed to queue
|
||||
) = range(6)
|
||||
|
||||
#BASS_Encode_CastInit content MIME types
|
||||
|
||||
BASS_ENCODE_TYPE_MP3 = "audio/mpeg"
|
||||
BASS_ENCODE_TYPE_OGG = "application/ogg"
|
||||
BASS_ENCODE_TYPE_AAC = "audio/aacp"
|
||||
|
||||
#BASS_Encode_CastGetStats types
|
||||
|
||||
BASS_ENCODE_STATS_SHOUT = 0 #Shoutcast stats
|
||||
BASS_ENCODE_STATS_ICE = 1 #Icecast mount-point stats
|
||||
BASS_ENCODE_STATS_ICESERV = 2 #Icecast server stats
|
||||
|
||||
#typedef void (CALLBACK ENCODEPROC)(HENCODE handle, DWORD channel, const void *buffer, DWORD length, void *user);
|
||||
ENCODEPROC = func_type(None, HENCODE, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_void_p)
|
||||
|
||||
#typedef void (CALLBACK ENCODEPROCEX)(HENCODE handle, DWORD channel, const void *buffer, DWORD length, QWORD offset, void *user);
|
||||
ENCODEPROCEX = func_type(None, HENCODE, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, pybass.QWORD, ctypes.c_void_p)
|
||||
|
||||
#typedef BOOL (CALLBACK ENCODECLIENTPROC)(HENCODE handle, BOOL connect, const char *client, char *headers, void *user);
|
||||
ENCODECLIENTPROC = func_type(ctypes.c_byte, HENCODE, ctypes.c_byte, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p)
|
||||
|
||||
#typedef void (CALLBACK ENCODENOTIFYPROC)(HENCODE handle, DWORD status, void *user);
|
||||
ENCODENOTIFYPROC = func_type(None, HENCODE, ctypes.c_ulong, ctypes.c_void_p)
|
||||
|
||||
#Encoder notifications
|
||||
BASS_ENCODE_NOTIFY_ENCODER = 1 #encoder died
|
||||
BASS_ENCODE_NOTIFY_CAST = 2 #cast server connection died
|
||||
BASS_ENCODE_NOTIFY_CAST_TIMEOUT = 0x10000 #cast timeout
|
||||
BASS_ENCODE_NOTIFY_QUEUE_FULL = 0x10001 #queue is out of space
|
||||
|
||||
#BASS_Encode_ServerInit flags
|
||||
BASS_ENCODE_SERVER_NOHTTP = 1 #no HTTP headers
|
||||
|
||||
#DWORD BASSENCDEF(BASS_Encode_GetVersion)();
|
||||
BASS_Encode_GetVersion = func_type(ctypes.c_ulong)(('BASS_Encode_GetVersion', bassenc_module))
|
||||
|
||||
#HENCODE BASSENCDEF(BASS_Encode_Start)(DWORD handle, const char *cmdline, DWORD flags, ENCODEPROC *proc, void *user);
|
||||
BASS_Encode_Start = func_type(HENCODE, ctypes.c_ulong, ctypes.c_char_p, ctypes.c_ulong, ENCODEPROC, ctypes.c_void_p)(('BASS_Encode_Start', bassenc_module))
|
||||
|
||||
#HENCODE BASSENCDEF(BASS_Encode_StartLimit)(DWORD handle, const char *cmdline, DWORD flags, ENCODEPROC *proc, void *user, DWORD limit);
|
||||
BASS_Encode_StartLimit = func_type(HENCODE, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, ENCODEPROC, ctypes.c_void_p, ctypes.c_ulong)(('BASS_Encode_StartLimit', bassenc_module))
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_AddChunk)(HENCODE handle, const char *id, const void *buffer, DWORD length);
|
||||
BASS_Encode_AddChunk = func_type(ctypes.c_byte, HENCODE, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_ulong)(('BASS_Encode_AddChunk', bassenc_module))
|
||||
|
||||
#DWORD BASSENCDEF(BASS_Encode_IsActive)(DWORD handle);
|
||||
BASS_Encode_IsActive = func_type(ctypes.c_ulong, ctypes.c_ulong)(('BASS_Encode_IsActive', bassenc_module))
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_Stop)(DWORD handle);
|
||||
BASS_Encode_Stop = func_type(ctypes.c_byte, ctypes.c_ulong)(('BASS_Encode_Stop', bassenc_module))
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_StopEx)(DWORD handle, BOOL queue);
|
||||
BASS_Encode_StopEx = func_type(ctypes.c_byte, ctypes.c_ulong, ctypes.c_byte)
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_SetPaused)(DWORD handle, BOOL paused);
|
||||
BASS_Encode_SetPaused = func_type(ctypes.c_byte, ctypes.c_ulong, ctypes.c_byte)(('BASS_Encode_SetPaused', bassenc_module))
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_Write)(DWORD handle, const void *buffer, DWORD length);
|
||||
BASS_Encode_Write = func_type(ctypes.c_byte, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong)(('BASS_Encode_Write', bassenc_module))
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_SetNotify)(DWORD handle, ENCODENOTIFYPROC *proc, void *user);
|
||||
BASS_Encode_SetNotify = func_type(ctypes.c_byte, ctypes.c_ulong, ENCODENOTIFYPROC, ctypes.c_void_p)(('BASS_Encode_SetNotify', bassenc_module))
|
||||
|
||||
#QWORD BASSENCDEF(BASS_Encode_GetCount)(DWORD handle, DWORD count);
|
||||
BASS_Encode_GetCount = func_type(pybass.QWORD, ctypes.c_ulong, ctypes.c_ulong)(('BASS_Encode_GetCount', bassenc_module))
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_SetChannel)(DWORD handle, DWORD channel);
|
||||
BASS_Encode_SetChannel = func_type(ctypes.c_byte, ctypes.c_ulong, ctypes.c_ulong)
|
||||
|
||||
#DWORD BASSENCDEF(BASS_Encode_GetChannel)(HENCODE handle);
|
||||
BASS_Encode_GetChannel = func_type(ctypes.c_ulong, HENCODE)(('BASS_Encode_GetChannel', bassenc_module))
|
||||
|
||||
if platform.system() == 'Windows':
|
||||
#DWORD BASSENCDEF(BASS_Encode_GetACMFormat)(DWORD handle, void *form, DWORD formlen, const char *title, DWORD flags);
|
||||
BASS_Encode_GetACMFormat = func_type(ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_char_p, ctypes.c_ulong)(('BASS_Encode_GetACMFormat', bassenc_module))
|
||||
|
||||
#HENCODE BASSENCDEF(BASS_Encode_StartACM)(DWORD handle, const void *form, DWORD flags, ENCODEPROC *proc, void *user);
|
||||
BASS_Encode_StartACM = func_type(HENCODE, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, ENCODEPROC, ctypes.c_void_p)(('BASS_Encode_StartACM', bassenc_module))
|
||||
|
||||
#HENCODE BASSENCDEF(BASS_Encode_StartACMFile)(DWORD handle, const void *form, DWORD flags, const char *file);
|
||||
BASS_Encode_StartACMFile = func_type(HENCODE, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong, ctypes.c_char_p)(('BASS_Encode_StartACMFile', bassenc_module))
|
||||
|
||||
|
||||
if platform.system() == 'Darwin':
|
||||
#HENCODE BASSENCDEF(BASS_Encode_StartCA)(DWORD handle, DWORD ftype, DWORD atype, DWORD flags, DWORD bitrate, ENCODEPROCEX *proc, void *user);
|
||||
BASS_Encode_StartCA = func_type(HENCODE, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ENCODEPROCEX, ctypes.c_void_p)(('ENCODEPROCEX ', bassenc_module))
|
||||
#HENCODE BASSENCDEF(BASS_Encode_StartCAFile)(DWORD handle, DWORD ftype, DWORD atype, DWORD flags, DWORD bitrate, const char *file);
|
||||
BASS_Encode_StartCAFile = func_type(HENCODE, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_char_p)(('BASS_Encode_StartCAFile', bassenc_module))
|
||||
#Broadcasting
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_CastInit)(HENCODE handle, const char *server, const char *pass, const char *content, const char *name, const char *url, const char *genre, const char *desc, const char *headers, DWORD bitrate, BOOL pub);
|
||||
BASS_Encode_CastInit = func_type(ctypes.c_byte, HENCODE, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_byte)(('BASS_Encode_CastInit', bassenc_module))
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_CastSetTitle)(HENCODE handle, const char *title, const char *url);
|
||||
BASS_Encode_CastSetTitle = func_type(ctypes.c_byte, HENCODE, ctypes.c_char_p, ctypes.c_char_p)(('BASS_Encode_CastSetTitle', bassenc_module))
|
||||
|
||||
#const char *BASSENCDEF(BASS_Encode_CastGetStats)(HENCODE handle, DWORD type, const char *pass);
|
||||
BASS_Encode_CastGetStats = func_type(ctypes.c_char_p, HENCODE, ctypes.c_ulong, ctypes.c_char_p)(('BASS_Encode_CastGetStats', bassenc_module))
|
||||
|
||||
#Local audio server
|
||||
|
||||
#DWORD BASSENCDEF(BASS_Encode_ServerInit)(HENCODE handle, const char *port, DWORD buffer, DWORD burst, DWORD flags, ENCODECLIENTPROC *proc, void *user);
|
||||
BASS_Encode_ServerInit = func_type(ctypes.c_ulong, HENCODE, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ENCODECLIENTPROC, ctypes.c_void_p)(('BASS_Encode_ServerInit', bassenc_module))
|
||||
|
||||
#BOOL BASSENCDEF(BASS_Encode_ServerKick)(HENCODE handle, const char *client);
|
||||
BASS_Encode_ServerKick = func_type(ctypes.c_byte, HENCODE, ctypes.c_char_p)(('BASS_Encode_ServerKick', bassenc_module))
|
||||
|
41
src/sound_lib/external/pybassflac.py
vendored
41
src/sound_lib/external/pybassflac.py
vendored
@@ -1,41 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
# Copyright(c) Max Kolosov 2009 maxkolosov@inbox.ru
|
||||
# http://vosolok2008.narod.ru
|
||||
# BSD license
|
||||
|
||||
__version__ = '0.1'
|
||||
__versionTime__ = '2009-11-15'
|
||||
__author__ = 'Max Kolosov <maxkolosov@inbox.ru>'
|
||||
__doc__ = '''
|
||||
pybassflac.py - is ctypes python module for
|
||||
BASSFLAC - extension to the BASS audio library,
|
||||
enabling the playing of FLAC (Free Lossless Audio Codec) encoded files.
|
||||
'''
|
||||
|
||||
import os, sys, ctypes
|
||||
from . import pybass
|
||||
from .paths import x86_path, x64_path
|
||||
import libloader
|
||||
|
||||
bassflac_module = libloader.load_library('bassflac', x86_path=x86_path, x64_path=x64_path)
|
||||
func_type = libloader.get_functype()
|
||||
#Register the plugin with the Bass plugin system.
|
||||
pybass.BASS_PluginLoad(libloader.find_library_path('bassflac', x86_path=x86_path, x64_path=x64_path), 0)
|
||||
|
||||
QWORD = pybass.QWORD
|
||||
HSTREAM = pybass.HSTREAM
|
||||
DOWNLOADPROC = pybass.DOWNLOADPROC
|
||||
BASS_FILEPROCS = pybass.BASS_FILEPROCS
|
||||
|
||||
# BASS_CHANNELINFO type
|
||||
BASS_CTYPE_STREAM_FLAC = 0x10900
|
||||
BASS_CTYPE_STREAM_FLAC_OGG = 0x10901
|
||||
|
||||
|
||||
#HSTREAM BASSFLACDEF(BASS_FLAC_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags);
|
||||
BASS_FLAC_StreamCreateFile = func_type(HSTREAM, ctypes.c_byte, ctypes.c_void_p, QWORD, QWORD, ctypes.c_ulong)(('BASS_FLAC_StreamCreateFile', bassflac_module))
|
||||
#HSTREAM BASSFLACDEF(BASS_FLAC_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user);
|
||||
BASS_FLAC_StreamCreateURL = func_type(HSTREAM, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_ulong, DOWNLOADPROC, ctypes.c_void_p)(('BASS_FLAC_StreamCreateURL', bassflac_module))
|
||||
#HSTREAM BASSFLACDEF(BASS_FLAC_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *procs, void *user);
|
||||
BASS_FLAC_StreamCreateFileUser = func_type(HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_FILEPROCS), ctypes.c_void_p)(('BASS_FLAC_StreamCreateFileUser', bassflac_module))
|
||||
|
204
src/sound_lib/external/pybassmidi.py
vendored
204
src/sound_lib/external/pybassmidi.py
vendored
@@ -1,204 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
# Copyright(c) Max Kolosov 2009 maxkolosov@inbox.ru
|
||||
# http://vosolok2008.narod.ru
|
||||
# BSD license
|
||||
|
||||
__version__ = '0.1'
|
||||
__versionTime__ = '2009-11-15'
|
||||
__author__ = 'Max Kolosov <maxkolosov@inbox.ru>'
|
||||
__doc__ = '''
|
||||
pybassmidi.py - is ctypes python module for
|
||||
BASSMIDI - extension to the BASS audio library,
|
||||
enabling the playing of MIDI files and real-time events,
|
||||
using SF2 soundfonts to provide the sounds.
|
||||
'''
|
||||
|
||||
import sys, ctypes, platform, os
|
||||
from . import pybass
|
||||
from .paths import x86_path, x64_path
|
||||
import libloader
|
||||
|
||||
bassmidi_module = libloader.load_library('bassmidi', x86_path=x86_path, x64_path=x64_path)
|
||||
func_type = libloader.get_functype()
|
||||
#Register the plugin with the Bass plugin system.
|
||||
pybass.BASS_PluginLoad(libloader.find_library_path('bassmidi', x86_path=x86_path, x64_path=x64_path), 0)
|
||||
|
||||
HSOUNDFONT = ctypes.c_ulong
|
||||
|
||||
QWORD = pybass.QWORD
|
||||
HSTREAM = pybass.HSTREAM
|
||||
DOWNLOADPROC = pybass.DOWNLOADPROC
|
||||
BASS_FILEPROCS = pybass.BASS_FILEPROCS
|
||||
|
||||
|
||||
# Additional BASS_SetConfig options
|
||||
BASS_CONFIG_MIDI_COMPACT = 0x10400
|
||||
BASS_CONFIG_MIDI_VOICES = 0x10401
|
||||
BASS_CONFIG_MIDI_AUTOFONT = 0x10402
|
||||
|
||||
# Additional BASS_SetConfigPtr options
|
||||
BASS_CONFIG_MIDI_DEFFONT = 0x10403
|
||||
|
||||
# Additional sync types
|
||||
BASS_SYNC_MIDI_MARKER = 0x10000
|
||||
BASS_SYNC_MIDI_CUE = 0x10001
|
||||
BASS_SYNC_MIDI_LYRIC = 0x10002
|
||||
BASS_SYNC_MIDI_TEXT = 0x10003
|
||||
BASS_SYNC_MIDI_EVENT = 0x10004
|
||||
BASS_SYNC_MIDI_TICK = 0x10005
|
||||
BASS_SYNC_MIDI_TIMESIG = 0x10006
|
||||
|
||||
# Additional BASS_MIDI_StreamCreateFile/etc flags
|
||||
BASS_MIDI_DECAYEND = 0x1000
|
||||
BASS_MIDI_NOFX = 0x2000
|
||||
BASS_MIDI_DECAYSEEK = 0x4000
|
||||
|
||||
class BASS_MIDI_FONT(ctypes.Structure):
|
||||
_fields_ = [('font', HSOUNDFONT),#HSOUNDFONT font; // soundfont
|
||||
('preset', ctypes.c_int),#int preset; // preset number (-1=all)
|
||||
('bank', ctypes.c_int)#int bank;
|
||||
]
|
||||
|
||||
class BASS_MIDI_FONTINFO(ctypes.Structure):
|
||||
_fields_ = [('name', ctypes.c_char_p),#const char *name;
|
||||
('copyright', ctypes.c_char_p),#const char *copyright;
|
||||
('comment', ctypes.c_char_p),#const char *comment;
|
||||
('presets', ctypes.c_ulong),#DWORD presets; // number of presets/instruments
|
||||
('samsize', ctypes.c_ulong),#DWORD samsize; // total size (in bytes) of the sample data
|
||||
('samload', ctypes.c_ulong),#DWORD samload; // amount of sample data currently loaded
|
||||
('samtype', ctypes.c_ulong)#DWORD samtype; // sample format (CTYPE) if packed
|
||||
]
|
||||
|
||||
class BASS_MIDI_MARK(ctypes.Structure):
|
||||
_fields_ = [('track', ctypes.c_ulong),#DWORD track; // track containing marker
|
||||
('pos', ctypes.c_ulong),#DWORD pos; // marker position (bytes)
|
||||
('text', ctypes.c_char_p)#const char *text; // marker text
|
||||
]
|
||||
|
||||
# Marker types
|
||||
BASS_MIDI_MARK_MARKER = 0 # marker events
|
||||
BASS_MIDI_MARK_CUE = 1 # cue events
|
||||
BASS_MIDI_MARK_LYRIC = 2 # lyric events
|
||||
BASS_MIDI_MARK_TEXT = 3 # text events
|
||||
BASS_MIDI_MARK_TIMESIG = 4 # time signature
|
||||
|
||||
# MIDI events
|
||||
MIDI_EVENT_NOTE = 1
|
||||
MIDI_EVENT_PROGRAM = 2
|
||||
MIDI_EVENT_CHANPRES = 3
|
||||
MIDI_EVENT_PITCH = 4
|
||||
MIDI_EVENT_PITCHRANGE = 5
|
||||
MIDI_EVENT_DRUMS = 6
|
||||
MIDI_EVENT_FINETUNE = 7
|
||||
MIDI_EVENT_COARSETUNE = 8
|
||||
MIDI_EVENT_MASTERVOL = 9
|
||||
MIDI_EVENT_BANK = 10
|
||||
MIDI_EVENT_MODULATION = 11
|
||||
MIDI_EVENT_VOLUME = 12
|
||||
MIDI_EVENT_PAN = 13
|
||||
MIDI_EVENT_EXPRESSION = 14
|
||||
MIDI_EVENT_SUSTAIN = 15
|
||||
MIDI_EVENT_SOUNDOFF = 16
|
||||
MIDI_EVENT_RESET = 17
|
||||
MIDI_EVENT_NOTESOFF = 18
|
||||
MIDI_EVENT_PORTAMENTO = 19
|
||||
MIDI_EVENT_PORTATIME = 20
|
||||
MIDI_EVENT_PORTANOTE = 21
|
||||
MIDI_EVENT_MODE = 22
|
||||
MIDI_EVENT_REVERB = 23
|
||||
MIDI_EVENT_CHORUS = 24
|
||||
MIDI_EVENT_CUTOFF = 25
|
||||
MIDI_EVENT_RESONANCE = 26
|
||||
MIDI_EVENT_RELEASE = 27
|
||||
MIDI_EVENT_ATTACK = 28
|
||||
MIDI_EVENT_REVERB_MACRO = 30
|
||||
MIDI_EVENT_CHORUS_MACRO = 31
|
||||
MIDI_EVENT_REVERB_TIME = 32
|
||||
MIDI_EVENT_REVERB_DELAY = 33
|
||||
MIDI_EVENT_REVERB_LOCUTOFF = 34
|
||||
MIDI_EVENT_REVERB_HICUTOFF = 35
|
||||
MIDI_EVENT_REVERB_LEVEL = 36
|
||||
MIDI_EVENT_CHORUS_DELAY = 37
|
||||
MIDI_EVENT_CHORUS_DEPTH = 38
|
||||
MIDI_EVENT_CHORUS_RATE = 39
|
||||
MIDI_EVENT_CHORUS_FEEDBACK = 40
|
||||
MIDI_EVENT_CHORUS_LEVEL = 41
|
||||
MIDI_EVENT_CHORUS_REVERB = 42
|
||||
MIDI_EVENT_DRUM_FINETUNE = 50
|
||||
MIDI_EVENT_DRUM_COARSETUNE = 51
|
||||
MIDI_EVENT_DRUM_PAN = 52
|
||||
MIDI_EVENT_DRUM_REVERB = 53
|
||||
MIDI_EVENT_DRUM_CHORUS = 54
|
||||
MIDI_EVENT_DRUM_CUTOFF = 55
|
||||
MIDI_EVENT_DRUM_RESONANCE = 56
|
||||
MIDI_EVENT_DRUM_LEVEL = 57
|
||||
MIDI_EVENT_TEMPO = 62
|
||||
MIDI_EVENT_MIXLEVEL = 0x10000
|
||||
MIDI_EVENT_TRANSPOSE = 0x10001
|
||||
|
||||
class BASS_MIDI_EVENT(ctypes.Structure):
|
||||
_fields_ = [('event', ctypes.c_ulong),#DWORD event; // MIDI_EVENT_xxx
|
||||
('param', ctypes.c_ulong),#DWORD param;
|
||||
('chan', ctypes.c_ulong),#DWORD chan;
|
||||
('tick', ctypes.c_ulong),#DWORD tick; // event position (ticks)
|
||||
('pos', ctypes.c_ulong)#DWORD pos; // event position (bytes)
|
||||
]
|
||||
|
||||
# BASS_CHANNELINFO type
|
||||
BASS_CTYPE_STREAM_MIDI = 0x10d00
|
||||
|
||||
# Additional attributes
|
||||
BASS_ATTRIB_MIDI_PPQN = 0x12000
|
||||
BASS_ATTRIB_MIDI_TRACK_VOL = 0x12100 # + track #
|
||||
|
||||
# Additional tag type
|
||||
BASS_TAG_MIDI_TRACK = 0x11000 # + track #, track text : array of null-terminated ANSI strings
|
||||
|
||||
# BASS_ChannelGetLength/GetPosition/SetPosition mode
|
||||
BASS_POS_MIDI_TICK = 2 # tick position
|
||||
|
||||
#HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreate)(DWORD channels, DWORD flags, DWORD freq);
|
||||
BASS_MIDI_StreamCreate = func_type(HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong)(('BASS_MIDI_StreamCreate', bassmidi_module))
|
||||
#HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags, DWORD freq);
|
||||
BASS_MIDI_StreamCreateFile = func_type(HSTREAM, ctypes.c_byte, ctypes.c_void_p, QWORD, QWORD, ctypes.c_ulong, ctypes.c_ulong)(('BASS_MIDI_StreamCreateFile', bassmidi_module))
|
||||
#HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user, DWORD freq);
|
||||
BASS_MIDI_StreamCreateURL = func_type(HSTREAM, ctypes.c_char_p, ctypes.c_ulong, ctypes.c_ulong, DOWNLOADPROC, ctypes.c_void_p, ctypes.c_ulong)(('BASS_MIDI_StreamCreateURL', bassmidi_module))
|
||||
#HSTREAM BASSMIDIDEF(BASS_MIDI_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *procs, void *user, DWORD freq);
|
||||
BASS_MIDI_StreamCreateFileUser = func_type(HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_FILEPROCS), ctypes.c_void_p, ctypes.c_ulong)(('BASS_MIDI_StreamCreateFileUser', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_StreamGetMark)(HSTREAM handle, DWORD type, DWORD index, BASS_MIDI_MARK *mark);
|
||||
BASS_MIDI_StreamGetMark = func_type(ctypes.c_byte, HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_MIDI_MARK))(('BASS_MIDI_StreamGetMark', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_StreamSetFonts)(HSTREAM handle, const BASS_MIDI_FONT *fonts, DWORD count);
|
||||
BASS_MIDI_StreamSetFonts = func_type(ctypes.c_byte, HSTREAM, ctypes.POINTER(BASS_MIDI_FONT), ctypes.c_ulong)(('BASS_MIDI_StreamSetFonts', bassmidi_module))
|
||||
#DWORD BASSMIDIDEF(BASS_MIDI_StreamGetFonts)(HSTREAM handle, BASS_MIDI_FONT *fonts, DWORD count);
|
||||
BASS_MIDI_StreamGetFonts = func_type(ctypes.c_ulong, HSTREAM, ctypes.POINTER(BASS_MIDI_FONT), ctypes.c_ulong)(('BASS_MIDI_StreamGetFonts', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_StreamLoadSamples)(HSTREAM handle);
|
||||
BASS_MIDI_StreamLoadSamples = func_type(ctypes.c_byte, HSTREAM)(('BASS_MIDI_StreamLoadSamples', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_StreamEvent)(HSTREAM handle, DWORD chan, DWORD event, DWORD param);
|
||||
BASS_MIDI_StreamEvent = func_type(ctypes.c_byte, HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong)(('BASS_MIDI_StreamEvent', bassmidi_module))
|
||||
#DWORD BASSMIDIDEF(BASS_MIDI_StreamGetEvent)(HSTREAM handle, DWORD chan, DWORD event);
|
||||
BASS_MIDI_StreamGetEvent = func_type(ctypes.c_ulong, HSTREAM, ctypes.c_ulong, ctypes.c_ulong)(('BASS_MIDI_StreamGetEvent', bassmidi_module))
|
||||
#DWORD BASSMIDIDEF(BASS_MIDI_StreamGetEvents)(HSTREAM handle, DWORD track, DWORD filter, BASS_MIDI_EVENT *events);
|
||||
BASS_MIDI_StreamGetEvents = func_type(ctypes.c_ulong, HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_MIDI_EVENT))(('BASS_MIDI_StreamGetEvents', bassmidi_module))
|
||||
#HSTREAM BASSMIDIDEF(BASS_MIDI_StreamGetChannel)(HSTREAM handle, DWORD chan);
|
||||
BASS_MIDI_StreamGetChannel = func_type(HSTREAM, HSTREAM, ctypes.c_ulong)(('BASS_MIDI_StreamGetChannel', bassmidi_module))
|
||||
|
||||
#HSOUNDFONT BASSMIDIDEF(BASS_MIDI_FontInit)(const void *file, DWORD flags);
|
||||
BASS_MIDI_FontInit = func_type(HSOUNDFONT, ctypes.c_void_p, ctypes.c_ulong)(('BASS_MIDI_FontInit', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_FontFree)(HSOUNDFONT handle);
|
||||
BASS_MIDI_FontFree = func_type(ctypes.c_byte, HSOUNDFONT)(('BASS_MIDI_FontFree', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_FontGetInfo)(HSOUNDFONT handle, BASS_MIDI_FONTINFO *info);
|
||||
BASS_MIDI_FontGetInfo = func_type(ctypes.c_byte, HSOUNDFONT, ctypes.POINTER(BASS_MIDI_FONTINFO))(('BASS_MIDI_FontGetInfo', bassmidi_module))
|
||||
#const char *BASSMIDIDEF(BASS_MIDI_FontGetPreset)(HSOUNDFONT handle, int preset, int bank);
|
||||
BASS_MIDI_FontGetPreset = func_type(ctypes.c_char_p, HSOUNDFONT, ctypes.c_int, ctypes.c_int)(('BASS_MIDI_FontGetPreset', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_FontLoad)(HSOUNDFONT handle, int preset, int bank);
|
||||
BASS_MIDI_FontLoad = func_type(ctypes.c_byte, HSOUNDFONT, ctypes.c_int, ctypes.c_int)(('BASS_MIDI_FontLoad', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_FontCompact)(HSOUNDFONT handle);
|
||||
BASS_MIDI_FontCompact = func_type(ctypes.c_byte, HSOUNDFONT)(('BASS_MIDI_FontCompact', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_FontPack)(HSOUNDFONT handle, const void *outfile, const void *encoder, DWORD flags);
|
||||
BASS_MIDI_FontPack = func_type(ctypes.c_byte, HSOUNDFONT, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_ulong)(('BASS_MIDI_FontPack', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_FontUnpack)(HSOUNDFONT handle, const void *outfile, DWORD flags);
|
||||
BASS_MIDI_FontUnpack = func_type(ctypes.c_byte, HSOUNDFONT, ctypes.c_void_p, ctypes.c_ulong)(('BASS_MIDI_FontUnpack', bassmidi_module))
|
||||
#BOOL BASSMIDIDEF(BASS_MIDI_FontSetVolume)(HSOUNDFONT handle, float volume);
|
||||
BASS_MIDI_FontSetVolume = func_type(ctypes.c_byte, HSOUNDFONT, ctypes.c_float)(('BASS_MIDI_FontSetVolume', bassmidi_module))
|
||||
#float BASSMIDIDEF(BASS_MIDI_FontGetVolume)(HSOUNDFONT handle);
|
||||
BASS_MIDI_FontGetVolume = func_type(ctypes.c_float, HSOUNDFONT)(('BASS_MIDI_FontGetVolume', bassmidi_module))
|
117
src/sound_lib/external/pybassmix.py
vendored
117
src/sound_lib/external/pybassmix.py
vendored
@@ -1,117 +0,0 @@
|
||||
from __future__ import absolute_import
|
||||
# Copyright(c) Max Kolosov 2009 maxkolosov@inbox.ru
|
||||
# http://vosolok2008.narod.ru
|
||||
# BSD license
|
||||
|
||||
__version__ = '0.1'
|
||||
__versionTime__ = '2009-11-15'
|
||||
__author__ = 'Max Kolosov <maxkolosov@inbox.ru>'
|
||||
__doc__ = '''
|
||||
pybassmix.py - is ctypes python module for
|
||||
BASSmix - extension to the BASS audio library, providing the ability
|
||||
to mix together multiple BASS channels, with resampling and matrix mixing
|
||||
features. It also provides the ability to go the other way and split a
|
||||
BASS channel into multiple channels.
|
||||
'''
|
||||
|
||||
import os, sys, ctypes, platform
|
||||
from . import pybass
|
||||
|
||||
QWORD = pybass.QWORD
|
||||
HSYNC = pybass.HSYNC
|
||||
HSTREAM = pybass.HSTREAM
|
||||
DOWNLOADPROC = pybass.DOWNLOADPROC
|
||||
SYNCPROC = pybass.SYNCPROC
|
||||
BASS_FILEPROCS = pybass.BASS_FILEPROCS
|
||||
|
||||
from .paths import x86_path, x64_path
|
||||
import libloader
|
||||
|
||||
bassmix_module = libloader.load_library('bassmix', x86_path=x86_path, x64_path=x64_path)
|
||||
func_type = libloader.get_functype()
|
||||
|
||||
# additional BASS_SetConfig option
|
||||
BASS_CONFIG_MIXER_FILTER = 0x10600
|
||||
BASS_CONFIG_MIXER_BUFFER = 0x10601
|
||||
BASS_CONFIG_SPLIT_BUFFER = 0x10610
|
||||
|
||||
# BASS_Mixer_StreamCreate flags
|
||||
BASS_MIXER_END = 0x10000# end the stream when there are no sources
|
||||
BASS_MIXER_NONSTOP = 0x20000# don't stall when there are no sources
|
||||
BASS_MIXER_RESUME = 0x1000# resume stalled immediately upon new/unpaused source
|
||||
|
||||
# source flags
|
||||
BASS_MIXER_FILTER = 0x1000# resampling filter
|
||||
BASS_MIXER_BUFFER = 0x2000# buffer data for BASS_Mixer_ChannelGetData/Level
|
||||
BASS_MIXER_LIMIT = 0x4000# limit mixer processing to the amount available from this source
|
||||
BASS_MIXER_MATRIX = 0x10000# matrix mixing
|
||||
BASS_MIXER_PAUSE = 0x20000# don't process the source
|
||||
BASS_MIXER_DOWNMIX = 0x400000# downmix to stereo/mono
|
||||
BASS_MIXER_NORAMPIN = 0x800000# don't ramp-in the start
|
||||
|
||||
# envelope node
|
||||
class BASS_MIXER_NODE(ctypes.Structure):
|
||||
_fields_ = [('pos', ctypes.c_ulong),#QWORD pos;
|
||||
('value', ctypes.c_float)#float value;
|
||||
]
|
||||
|
||||
# envelope types
|
||||
BASS_MIXER_ENV_FREQ = 1
|
||||
BASS_MIXER_ENV_VOL = 2
|
||||
BASS_MIXER_ENV_PAN = 3
|
||||
BASS_MIXER_ENV_LOOP = 0x10000# FLAG: loop
|
||||
|
||||
# additional sync type
|
||||
BASS_SYNC_MIXER_ENVELOPE = 0x10200
|
||||
|
||||
# BASS_CHANNELINFO type
|
||||
BASS_CTYPE_STREAM_MIXER = 0x10800
|
||||
BASS_CTYPE_STREAM_SPLIT = 0x10801
|
||||
|
||||
|
||||
#DWORD BASSMIXDEF(BASS_Mixer_GetVersion)();
|
||||
BASS_Mixer_GetVersion = func_type(ctypes.c_ulong)(('BASS_Mixer_GetVersion', bassmix_module))
|
||||
|
||||
#HSTREAM BASSMIXDEF(BASS_Mixer_StreamCreate)(DWORD freq, DWORD chans, DWORD flags);
|
||||
BASS_Mixer_StreamCreate = func_type(HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong)(('BASS_Mixer_StreamCreate', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Mixer_StreamAddChannel)(HSTREAM handle, DWORD channel, DWORD flags);
|
||||
BASS_Mixer_StreamAddChannel = func_type(ctypes.c_byte, HSTREAM, ctypes.c_ulong, ctypes.c_ulong)(('BASS_Mixer_StreamAddChannel', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Mixer_StreamAddChannelEx)(HSTREAM handle, DWORD channel, DWORD flags, QWORD start, QWORD length);
|
||||
BASS_Mixer_StreamAddChannelEx = func_type(ctypes.c_byte, HSTREAM, ctypes.c_ulong, ctypes.c_ulong, QWORD, QWORD)(('BASS_Mixer_StreamAddChannelEx', bassmix_module))
|
||||
|
||||
#HSTREAM BASSMIXDEF(BASS_Mixer_ChannelGetMixer)(DWORD handle);
|
||||
BASS_Mixer_ChannelGetMixer = func_type(HSTREAM, ctypes.c_ulong)(('BASS_Mixer_ChannelGetMixer', bassmix_module))
|
||||
#DWORD BASSMIXDEF(BASS_Mixer_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask);
|
||||
BASS_Mixer_ChannelFlags = func_type(ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong)(('BASS_Mixer_ChannelFlags', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Mixer_ChannelRemove)(DWORD handle);
|
||||
BASS_Mixer_ChannelRemove = func_type(ctypes.c_byte, ctypes.c_ulong)(('BASS_Mixer_ChannelRemove', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Mixer_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode);
|
||||
BASS_Mixer_ChannelSetPosition = func_type(ctypes.c_byte, ctypes.c_ulong, QWORD, ctypes.c_ulong)(('BASS_Mixer_ChannelSetPosition', bassmix_module))
|
||||
#QWORD BASSMIXDEF(BASS_Mixer_ChannelGetPosition)(DWORD handle, DWORD mode);
|
||||
BASS_Mixer_ChannelGetPosition = func_type(QWORD, ctypes.c_ulong, ctypes.c_ulong)(('BASS_Mixer_ChannelGetPosition', bassmix_module))
|
||||
#DWORD BASSMIXDEF(BASS_Mixer_ChannelGetLevel)(DWORD handle);
|
||||
BASS_Mixer_ChannelGetLevel = func_type(ctypes.c_ulong, ctypes.c_ulong)(('BASS_Mixer_ChannelGetLevel', bassmix_module))
|
||||
#DWORD BASSMIXDEF(BASS_Mixer_ChannelGetData)(DWORD handle, void *buffer, DWORD length);
|
||||
BASS_Mixer_ChannelGetData = func_type(ctypes.c_ulong, ctypes.c_ulong, ctypes.c_void_p, ctypes.c_ulong)(('BASS_Mixer_ChannelGetData', bassmix_module))
|
||||
#HSYNC BASSMIXDEF(BASS_Mixer_ChannelSetSync)(DWORD handle, DWORD type, QWORD param, SYNCPROC *proc, void *user);
|
||||
BASS_Mixer_ChannelSetSync = func_type(HSYNC, ctypes.c_ulong, ctypes.c_ulong, QWORD, SYNCPROC, ctypes.c_void_p)(('BASS_Mixer_ChannelSetSync', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Mixer_ChannelRemoveSync)(DWORD channel, HSYNC sync);
|
||||
BASS_Mixer_ChannelRemoveSync = func_type(ctypes.c_byte, ctypes.c_ulong, HSYNC)(('BASS_Mixer_ChannelRemoveSync', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Mixer_ChannelSetMatrix)(DWORD handle, const float *matrix);
|
||||
BASS_Mixer_ChannelSetMatrix = func_type(ctypes.c_byte, ctypes.c_ulong, ctypes.POINTER(ctypes.c_float))(('BASS_Mixer_ChannelSetMatrix', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Mixer_ChannelGetMatrix)(DWORD handle, float *matrix);
|
||||
BASS_Mixer_ChannelGetMatrix = func_type(ctypes.c_byte, ctypes.c_ulong, ctypes.POINTER(ctypes.c_float))(('BASS_Mixer_ChannelGetMatrix', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Mixer_ChannelSetEnvelope)(DWORD handle, DWORD type, const BASS_MIXER_NODE *nodes, DWORD count);
|
||||
BASS_Mixer_ChannelSetEnvelope = func_type(ctypes.c_byte, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(BASS_MIXER_NODE), ctypes.c_ulong)(('BASS_Mixer_ChannelSetEnvelope', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Mixer_ChannelSetEnvelopePos)(DWORD handle, DWORD type, QWORD pos);
|
||||
BASS_Mixer_ChannelSetEnvelopePos = func_type(ctypes.c_byte, ctypes.c_ulong, ctypes.c_ulong, QWORD)(('BASS_Mixer_ChannelSetEnvelopePos', bassmix_module))
|
||||
#QWORD BASSMIXDEF(BASS_Mixer_ChannelGetEnvelopePos)(DWORD handle, DWORD type, float *value);
|
||||
BASS_Mixer_ChannelGetEnvelopePos = func_type(QWORD, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_float)(('BASS_Mixer_ChannelGetEnvelopePos', bassmix_module))
|
||||
|
||||
#HSTREAM BASSMIXDEF(BASS_Split_StreamCreate)(DWORD channel, DWORD flags, int *chanmap);
|
||||
BASS_Split_StreamCreate = func_type(HSTREAM, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_int)(('BASS_Split_StreamCreate', bassmix_module))
|
||||
#DWORD BASSMIXDEF(BASS_Split_StreamGetSource)(HSTREAM handle);
|
||||
BASS_Split_StreamGetSource = func_type(ctypes.c_ulong, HSTREAM)(('BASS_Split_StreamGetSource', bassmix_module))
|
||||
#BOOL BASSMIXDEF(BASS_Split_StreamReset)(DWORD handle);
|
||||
BASS_Split_StreamReset = func_type(ctypes.c_byte, ctypes.c_ulong)(('BASS_Split_StreamReset', bassmix_module))
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user