Compare commits

...

18 Commits

Author SHA1 Message Date
89985cf6bd Updated snapshot info 2019-02-19 22:24:25 -06:00
cc4568b968 Win10: Remapped session mute/umute to Control+win+alt+m 2019-02-19 17:50:05 -06:00
d7132ecaf6 Added 'open in Twitter' for tweets and users 2019-02-19 17:41:34 -06:00
720e0e6c24 Win10: Remapped shortcut for settings dialog to Ctrl+Win+Alt+o 2019-02-19 16:48:54 -06:00
9763d8b26c Fixed an error when trying to retrieve a deleted user while rendering a direct message 2019-02-15 09:04:52 -06:00
f512267b6d Add accessible_output2 to requirements file. Closes #280 2019-01-28 13:28:30 -06:00
241de0264d Use accessible_output2 as external dependency 2019-01-23 17:36:46 -06:00
5c7bce1258 Added sound_lib as an external dependency. #273 2019-01-23 17:28:05 -06:00
e24543be12 Use platform_utils as an external dependency 2019-01-15 17:54:29 -06:00
422c780d0c Merge pull request #279 from codeofdusk/i278
Fix #278
2019-01-15 17:29:28 -06:00
Bill Dengler
96a592a4f9 Fixed #278. 2018-12-31 21:14:09 +00:00
d4bf33ca6d Added support for playback from anyaudio.net 2018-11-25 13:00:01 -06:00
e5b33160e0 Added a custom fix for Libloader with changes made by @jmdaweb #273 2018-11-22 17:48:22 -06:00
c8d83ed9e7 Added new path to libloader in requirements file #273 2018-11-22 17:47:38 -06:00
16b2e16614 Removed libloader from the source repository. #273 2018-11-22 17:47:02 -06:00
221d1d413b Changed codebase's syntax before attempt the python3 migration later. #273 2018-11-22 13:35:51 -06:00
4391e3d3de Install Twython from a git repo instead of shipping it in the source code. #273 2018-11-22 12:19:23 -06:00
c5e9e97c84 Keep custom buffer ordering across restarts and changes in settings 2018-11-18 06:33:33 -06:00
188 changed files with 427 additions and 7193 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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)]

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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("<", "&lt;"))
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

View File

@@ -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

View File

@@ -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

View File

@@ -1 +0,0 @@
from __future__ import absolute_import

View File

@@ -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

View File

@@ -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"]

View File

@@ -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

View File

@@ -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:

View File

@@ -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()

View File

@@ -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:

View File

@@ -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))

View File

@@ -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

View File

@@ -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"])

View File

@@ -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

View File

@@ -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,)

View File

@@ -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):

View File

@@ -1 +1,2 @@
from soundsTutorial import soundsTutorial
from __future__ import absolute_import
from .soundsTutorial import soundsTutorial

View File

@@ -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):

View File

@@ -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.")),

View File

@@ -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 *

View File

@@ -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)

View File

@@ -1,2 +1,4 @@
# -*- coding: utf-8 -*-
import completion, settings
from __future__ import absolute_import
# -*- coding: utf-8 -*-
from . import completion, settings

View File

@@ -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):

View File

@@ -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):

View File

@@ -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

View File

@@ -1,2 +1,4 @@
# -*- coding: utf-8 -*-
import OCRSpace
from __future__ import absolute_import
# -*- coding: utf-8 -*-
from . import OCRSpace

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View 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

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from builtins import object
import application
import platform
import exceptions

View File

@@ -1 +1,2 @@
from keystrokeEditor import KeystrokeEditor
from __future__ import absolute_import
from .keystrokeEditor import KeystrokeEditor

View File

@@ -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):

View File

@@ -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)

View File

@@ -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.
"""

View File

@@ -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

View File

@@ -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']

View File

@@ -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()

View File

@@ -1 +1,2 @@
import widgets
from __future__ import absolute_import
from . import widgets

View File

@@ -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):

View File

@@ -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

View File

@@ -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']

View File

@@ -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'

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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"]:

View File

@@ -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):

View File

@@ -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:

View File

@@ -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"

View File

@@ -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

View File

@@ -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"]

View File

@@ -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]:

View File

@@ -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:

View File

@@ -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)]

View File

@@ -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

View File

@@ -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)

View File

@@ -1 +0,0 @@
from .tempo import Tempo

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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')

File diff suppressed because it is too large Load Diff

View File

@@ -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))

View File

@@ -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)

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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))

View File

@@ -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