diff --git a/LXST/Codecs/libs/pyogg/libs/macos/README b/LXST/Codecs/libs/pyogg/libs/macos/README new file mode 100644 index 0000000..ad21431 --- /dev/null +++ b/LXST/Codecs/libs/pyogg/libs/macos/README @@ -0,0 +1,50 @@ +The shared libraries for macOS were obtained by first +installing/compiling the standard libraries using Homebrew: + + brew install libogg opus opusfile libopusenc libvorbis flac + +These libraries were then copied into this directory. However a +number of the libraries were looking for eachother internally. + +The paths the libraries are currently expecting can be seen by +executing the command: + + otool -L *.dylib + +This shows, for example: + + libopusfile.0.dylib: + /usr/local/opt/opusfile/lib/libopusfile.0.dylib (compatibility version 5.0.0, current version 5.5.0) + /usr/local/opt/libogg/lib/libogg.0.dylib (compatibility version 9.0.0, current version 9.4.0) + /usr/local/opt/opus/lib/libopus.0.dylib (compatibility version 9.0.0, current version 9.0.0) + /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4) + +Note the hard-coded location to libogg and libopus. These files are +included with the PyOgg distribution, but not at those locations. + +To fix the expected paths, we ran the following commands: + + install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib @loader_path/libogg.0.dylib libFLAC.8.dylib + install_name_tool -change /usr/local/opt/opus/lib/libopus.0.dylib @loader_path/libopus.0.dylib libopusenc.0.dylib + install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib @loader_path/libogg.0.dylib libopusfile.0.dylib + install_name_tool -change /usr/local/opt/opus/lib/libopus.0.dylib @loader_path/libopus.0.dylib libopusfile.0.dylib + install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib @loader_path/libogg.0.dylib libvorbis.0.dylib + install_name_tool -change /usr/local/Cellar/libvorbis/1.3.7/lib/libvorbis.0.dylib @loader_path/libvorbis.0.dylib libvorbisenc.2.dylib + install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib @loader_path/libogg.0.dylib libvorbisenc.2.dylib + install_name_tool -change /usr/local/Cellar/libvorbis/1.3.7/lib/libvorbis.0.dylib @loader_path/libvorbis.0.dylib libvorbisfile.3.dylib + install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib @loader_path/libogg.0.dylib libvorbisfile.3.dylib + +After changing the locations of the paths, we can rerun: + + otool -L *.dylib + +Which shows, in the case of libopusfile: + + libopusfile.0.dylib: + /usr/local/opt/opusfile/lib/libopusfile.0.dylib (compatibility version 5.0.0, current version 5.5.0) + @loader_path/libogg.0.dylib (compatibility version 9.0.0, current version 9.4.0) + @loader_path/libopus.0.dylib (compatibility version 9.0.0, current version 9.0.0) + /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4) + +These relative paths mean the libraries will be found within the PyOgg +package. \ No newline at end of file diff --git a/LXST/Codecs/libs/pyogg/libs/macos/libFLAC.8.dylib b/LXST/Codecs/libs/pyogg/libs/macos/libFLAC.8.dylib new file mode 100644 index 0000000..5b20ba2 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/macos/libFLAC.8.dylib differ diff --git a/LXST/Codecs/libs/pyogg/libs/macos/libogg.0.dylib b/LXST/Codecs/libs/pyogg/libs/macos/libogg.0.dylib new file mode 100644 index 0000000..efa95a5 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/macos/libogg.0.dylib differ diff --git a/LXST/Codecs/libs/pyogg/libs/macos/libopus.0.dylib b/LXST/Codecs/libs/pyogg/libs/macos/libopus.0.dylib new file mode 100644 index 0000000..bed4d75 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/macos/libopus.0.dylib differ diff --git a/LXST/Codecs/libs/pyogg/libs/macos/libopusenc.0.dylib b/LXST/Codecs/libs/pyogg/libs/macos/libopusenc.0.dylib new file mode 100644 index 0000000..bdb4fa2 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/macos/libopusenc.0.dylib differ diff --git a/LXST/Codecs/libs/pyogg/libs/macos/libopusfile.0.dylib b/LXST/Codecs/libs/pyogg/libs/macos/libopusfile.0.dylib new file mode 100644 index 0000000..8177598 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/macos/libopusfile.0.dylib differ diff --git a/LXST/Codecs/libs/pyogg/libs/macos/libvorbis.0.dylib b/LXST/Codecs/libs/pyogg/libs/macos/libvorbis.0.dylib new file mode 100644 index 0000000..5149694 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/macos/libvorbis.0.dylib differ diff --git a/LXST/Codecs/libs/pyogg/libs/macos/libvorbisenc.2.dylib b/LXST/Codecs/libs/pyogg/libs/macos/libvorbisenc.2.dylib new file mode 100644 index 0000000..0da95bd Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/macos/libvorbisenc.2.dylib differ diff --git a/LXST/Codecs/libs/pyogg/libs/macos/libvorbisfile.3.dylib b/LXST/Codecs/libs/pyogg/libs/macos/libvorbisfile.3.dylib new file mode 100644 index 0000000..58ffe07 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/macos/libvorbisfile.3.dylib differ diff --git a/LXST/Codecs/libs/pyogg/libs/win32/libFLAC.dll b/LXST/Codecs/libs/pyogg/libs/win32/libFLAC.dll new file mode 100644 index 0000000..9c05b1b Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win32/libFLAC.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win32/libcrypto-1_1.dll b/LXST/Codecs/libs/pyogg/libs/win32/libcrypto-1_1.dll new file mode 100644 index 0000000..7bc59c4 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win32/libcrypto-1_1.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win32/libssl-1_1.dll b/LXST/Codecs/libs/pyogg/libs/win32/libssl-1_1.dll new file mode 100644 index 0000000..ee2d970 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win32/libssl-1_1.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win32/libvorbis.dll b/LXST/Codecs/libs/pyogg/libs/win32/libvorbis.dll new file mode 100644 index 0000000..0129c5b Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win32/libvorbis.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win32/libvorbisfile.dll b/LXST/Codecs/libs/pyogg/libs/win32/libvorbisfile.dll new file mode 100644 index 0000000..c3457a2 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win32/libvorbisfile.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win32/ogg.dll b/LXST/Codecs/libs/pyogg/libs/win32/ogg.dll new file mode 100644 index 0000000..cf71c39 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win32/ogg.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win32/opus.dll b/LXST/Codecs/libs/pyogg/libs/win32/opus.dll new file mode 100644 index 0000000..06986fa Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win32/opus.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win32/opusenc.dll b/LXST/Codecs/libs/pyogg/libs/win32/opusenc.dll new file mode 100644 index 0000000..177a109 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win32/opusenc.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win32/opusfile.dll b/LXST/Codecs/libs/pyogg/libs/win32/opusfile.dll new file mode 100644 index 0000000..7a58b06 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win32/opusfile.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win_amd64/libFLAC.dll b/LXST/Codecs/libs/pyogg/libs/win_amd64/libFLAC.dll new file mode 100644 index 0000000..fd72988 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win_amd64/libFLAC.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win_amd64/libcrypto-1_1-x64.dll b/LXST/Codecs/libs/pyogg/libs/win_amd64/libcrypto-1_1-x64.dll new file mode 100644 index 0000000..83e7897 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win_amd64/libcrypto-1_1-x64.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win_amd64/libssl-1_1-x64.dll b/LXST/Codecs/libs/pyogg/libs/win_amd64/libssl-1_1-x64.dll new file mode 100644 index 0000000..8f625cb Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win_amd64/libssl-1_1-x64.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win_amd64/libvorbis.dll b/LXST/Codecs/libs/pyogg/libs/win_amd64/libvorbis.dll new file mode 100644 index 0000000..a8a15e7 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win_amd64/libvorbis.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win_amd64/libvorbisfile.dll b/LXST/Codecs/libs/pyogg/libs/win_amd64/libvorbisfile.dll new file mode 100644 index 0000000..a6876ed Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win_amd64/libvorbisfile.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win_amd64/ogg.dll b/LXST/Codecs/libs/pyogg/libs/win_amd64/ogg.dll new file mode 100644 index 0000000..6ff55d5 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win_amd64/ogg.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win_amd64/opus.dll b/LXST/Codecs/libs/pyogg/libs/win_amd64/opus.dll new file mode 100644 index 0000000..22753b0 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win_amd64/opus.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win_amd64/opusenc.dll b/LXST/Codecs/libs/pyogg/libs/win_amd64/opusenc.dll new file mode 100644 index 0000000..868380e Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win_amd64/opusenc.dll differ diff --git a/LXST/Codecs/libs/pyogg/libs/win_amd64/opusfile.dll b/LXST/Codecs/libs/pyogg/libs/win_amd64/opusfile.dll new file mode 100644 index 0000000..ed2d3c4 Binary files /dev/null and b/LXST/Codecs/libs/pyogg/libs/win_amd64/opusfile.dll differ diff --git a/LXST/Sinks.py b/LXST/Sinks.py index 997d650..2942542 100644 --- a/LXST/Sinks.py +++ b/LXST/Sinks.py @@ -23,9 +23,61 @@ class LinuxBackend(): def get_player(self, samples_per_frame=None): return self.device.player(samplerate=self.samplerate, blocksize=samples_per_frame) + def release_player(self): pass + +class DarwinBackend(): + SAMPLERATE = 48000 + + def __init__(self, preferred_device=None, samplerate=SAMPLERATE): + import soundcard + self.samplerate = samplerate + self.soundcard = soundcard + if preferred_device: + try: self.device = self.soundcard.get_speaker(preferred_device) + except: self.device = soundcard.default_speaker() + else: self.device = soundcard.default_speaker() + RNS.log(f"Using output device {self.device}", RNS.LOG_DEBUG) + + def flush(self): + self.recorder.flush() + + def get_player(self, samples_per_frame=None): + return self.device.player(samplerate=self.samplerate, blocksize=samples_per_frame) + + def release_player(self): pass + +class WindowsBackend(): + SAMPLERATE = 48000 + + def __init__(self, preferred_device=None, samplerate=SAMPLERATE): + import soundcard + from pythoncom import CoInitializeEx, CoUninitialize + self.com_init = CoInitializeEx + self.com_release = CoUninitialize + self.samplerate = samplerate + self.soundcard = soundcard + if preferred_device: + try: self.device = self.soundcard.get_speaker(preferred_device) + except: self.device = soundcard.default_speaker() + else: self.device = soundcard.default_speaker() + RNS.log(f"Using output device {self.device}", RNS.LOG_DEBUG) + + def flush(self): + self.recorder.flush() + + def get_player(self, samples_per_frame=None): + self.com_init(0) + return self.device.player(samplerate=self.samplerate, blocksize=samples_per_frame) + + def release_player(self): self.com_release() + def get_backend(): if RNS.vendor.platformutils.is_linux(): return LinuxBackend + elif RNS.vendor.platformutils.is_windows(): + return WindowsBackend + elif RNS.vendor.platformutils.is_darwin(): + return DarwinBackend else: return None @@ -132,5 +184,7 @@ class LineSink(LocalSink): else: time.sleep(self.frame_time*0.1) + self.backend.release_player() + class PacketSink(RemoteSink): pass \ No newline at end of file diff --git a/LXST/Sounds/ringer.opus b/LXST/Sounds/ringer.opus new file mode 100644 index 0000000..36d0094 Binary files /dev/null and b/LXST/Sounds/ringer.opus differ diff --git a/LXST/Sounds/soft.opus b/LXST/Sounds/soft.opus new file mode 100644 index 0000000..6e3d792 Binary files /dev/null and b/LXST/Sounds/soft.opus differ diff --git a/LXST/Sources.py b/LXST/Sources.py index 23e208c..2fe6d2c 100644 --- a/LXST/Sources.py +++ b/LXST/Sources.py @@ -32,9 +32,65 @@ class LinuxBackend(): def get_recorder(self, samples_per_frame): return self.device.recorder(samplerate=self.SAMPLERATE, blocksize=samples_per_frame) + def release_recorder(self): pass + +class DarwinBackend(): + SAMPLERATE = 48000 + + def __init__(self, preferred_device=None, samplerate=SAMPLERATE): + import soundcard + self.samplerate = samplerate + self.soundcard = soundcard + if preferred_device: + try: self.device = self.soundcard.get_microphone(preferred_device) + except: self.device = self.soundcard.default_microphone() + else: self.device = self.soundcard.default_microphone() + self.channels = self.device.channels + self.bitdepth = 32 + RNS.log(f"Using input device {self.device}", RNS.LOG_DEBUG) + + def flush(self): + self.recorder.flush() + + def get_recorder(self, samples_per_frame): + return self.device.recorder(samplerate=self.SAMPLERATE, blocksize=samples_per_frame) + + def release_recorder(self): pass + +class WindowsBackend(): + SAMPLERATE = 48000 + + def __init__(self, preferred_device=None, samplerate=SAMPLERATE): + import soundcard + from pythoncom import CoInitializeEx, CoUninitialize + self.com_init = CoInitializeEx + self.com_release = CoUninitialize + self.samplerate = samplerate + self.soundcard = soundcard + if preferred_device: + try: self.device = self.soundcard.get_microphone(preferred_device) + except: self.device = self.soundcard.default_microphone() + else: self.device = self.soundcard.default_microphone() + self.channels = self.device.channels + self.bitdepth = 32 + RNS.log(f"Using input device {self.device}", RNS.LOG_DEBUG) + + def flush(self): + self.recorder.flush() + + def get_recorder(self, samples_per_frame): + self.com_init(0) + return self.device.recorder(samplerate=self.SAMPLERATE, blocksize=samples_per_frame) + + def release_recorder(self): self.com_release() + def get_backend(): if RNS.vendor.platformutils.is_linux(): return LinuxBackend + elif RNS.vendor.platformutils.is_windows(): + return WindowsBackend + elif RNS.vendor.platformutils.is_darwin(): + return DarwinBackend else: return None diff --git a/LXST/Utilities/rnphone.py b/LXST/Utilities/rnphone.py index e1d8814..94ade8b 100644 --- a/LXST/Utilities/rnphone.py +++ b/LXST/Utilities/rnphone.py @@ -98,6 +98,16 @@ class ReticulumTelephone(): if not os.path.isdir(self.storagedir): os.makedirs(self.storagedir) + ringer_tones = ["ringer.opus", "soft.opus"] + sounds_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "Sounds")) + if os.path.isdir(sounds_path): + import shutil + for filename in ringer_tones: + src_path = os.path.join(sounds_path, filename) + dst_path = os.path.join(self.configdir, filename) + if os.path.isfile(src_path): + RNS.log(f"Copying {src_path} to {dst_path}") + shutil.copy(src_path, dst_path) if not os.path.isfile(self.configpath): self.create_default_config() @@ -691,7 +701,7 @@ __default_rnphone_config__ = """# This is an example rnphone config file. # phone is ringing. Must be in OPUS format, and # located in the rnphone config directory. - ringtone = ringtone.opus + ringtone = ringer.opus # You can define the preferred audio devices # to use as the speaker output, ringer output diff --git a/LXST/_version.py b/LXST/_version.py index 7a17bdd..845be45 100644 --- a/LXST/_version.py +++ b/LXST/_version.py @@ -1 +1 @@ -__version__ = "0.2.4" \ No newline at end of file +__version__ = "0.2.5" \ No newline at end of file diff --git a/README.md b/README.md index 84ac2b4..7db451c 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ LXST uses encryption provided by [Reticulum](https://reticulum.network), and thu ## Project Status & License -This software is in a very early alpha state, and will change rapidly with ongoing development. Consider no APIs stable. Consider everything explosive. +This software is in a very early alpha state, and will change rapidly with ongoing development. Consider no APIs stable. Consider everything explosive. Not all features are implemented. Nothing is documented. For a fully functional LXST program, take a look at the included `rnphone` program, which provides telephony service over Reticulum. Everything else will currently be a voyage of your own making. While under early development, the project is kept under a `CC BY-NC-ND 4.0` license. diff --git a/setup.py b/setup.py index fa9c5e2..5e377a3 100644 --- a/setup.py +++ b/setup.py @@ -10,8 +10,14 @@ packages.append("LXST.Utilities") packages.append("LXST.Primitives.hardware") packages.append("LXST.Codecs.libs.pydub") packages.append("LXST.Codecs.libs.pyogg") -print("Packages:") -print(packages) + +package_data = { +"": [ + "Codecs/libs/pyogg/libs/win_amd64/*", + "Codecs/libs/pyogg/libs/macos/*", + "Sounds/*", + ] +} setuptools.setup( name="lxst", @@ -23,6 +29,7 @@ setuptools.setup( long_description_content_type="text/markdown", url="https://git.unsigned.io/markqvist/lxst", packages=packages, + package_data=package_data, classifiers=[ "Programming Language :: Python :: 3", "License :: Other/Proprietary License",