Skip to content

Commit

Permalink
Basig audio working. Many kinks.
Browse files Browse the repository at this point in the history
  • Loading branch information
poconbhui committed Jun 11, 2016
1 parent 9c561e8 commit d216ec6
Show file tree
Hide file tree
Showing 9 changed files with 734 additions and 16 deletions.
35 changes: 29 additions & 6 deletions ds4drv/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
from .daemon import Daemon
from .eventloop import EventLoop
from .exceptions import BackendError
from .audio import GstPulseToSBCPipeline


class DS4Controller(object):
def __init__(self, index, options, dynamic=False):
def __init__(self, index, options, audio_pipeline, dynamic=False):
self.index = index
self.dynamic = dynamic
self.logger = Daemon.logger.new_module("controller {0}".format(index))
Expand All @@ -33,6 +34,8 @@ def __init__(self, index, options, dynamic=False):
if self.profiles:
self.profiles.append("default")

self.audio_pipeline = audio_pipeline

self.load_options(self.options)

def fire_event(self, event, *args):
Expand Down Expand Up @@ -120,8 +123,10 @@ def exit(self, *args, error = True):
self.logger.info(*args)


def create_controller_thread(index, controller_options, dynamic=False):
controller = DS4Controller(index, controller_options, dynamic=dynamic)
def create_controller_thread(index, controller_options, audio_pipeline,
dynamic=False):
controller = DS4Controller(index, controller_options, audio_pipeline,
dynamic=dynamic)

thread = Thread(target=controller.run)
thread.controller = controller
Expand All @@ -131,26 +136,33 @@ def create_controller_thread(index, controller_options, dynamic=False):


class SigintHandler(object):
def __init__(self, threads):
def __init__(self, threads, audio_pipeline):
self.threads = threads
self.audio_pipeline = audio_pipeline

def cleanup_controller_threads(self):
for thread in self.threads:
thread.controller.exit("Cleaning up...", error=False)
thread.controller.loop.stop()
thread.join()

def cleanup_audio_pipeline(self):
self.audio_pipeline.stop()

def __call__(self, signum, frame):
signal.signal(signum, signal.SIG_DFL)

self.cleanup_audio_pipeline()
self.cleanup_controller_threads()

sys.exit(0)


def main():
threads = []
audio_pipeline = GstPulseToSBCPipeline()

sigint_handler = SigintHandler(threads)
sigint_handler = SigintHandler(threads, audio_pipeline)
signal.signal(signal.SIGINT, sigint_handler)

try:
Expand All @@ -172,10 +184,20 @@ def main():
Daemon.fork(options.daemon_log, options.daemon_pid)

for index, controller_options in enumerate(options.controllers):
thread = create_controller_thread(index + 1, controller_options)
thread = create_controller_thread(
index + 1, controller_options, audio_pipeline
)
threads.append(thread)

audio_pipeline.start()

for device in backend.devices:
print("-----")
from multiprocessing import Pool
p = Pool(processes=1)
def f(d):
print("f:", d)
p.apply_async(f, (device,))
connected_devices = []
for thread in threads:
# Controller has received a fatal error, exit
Expand All @@ -199,6 +221,7 @@ def main():
else:
thread = create_controller_thread(len(threads) + 1,
options.default_controller,
audio_pipeline,
dynamic=True)
threads.append(thread)

Expand Down
1 change: 1 addition & 0 deletions ds4drv/actions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
from . import input
from . import led
from . import status
from . import audio
128 changes: 128 additions & 0 deletions ds4drv/actions/audio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
from ..action import Action
from ..audio import SBCHeaders


class AudioCallbacks():
callbacks = []

def __call__(self, buffer, data):
import os
#print("cbpid: ", os.getpid())
for callback in self.callbacks:
callback(data)

import os
from io import FileIO
hidraw_device = "/dev/hidraw3"
report_fd = os.open(hidraw_device, os.O_RDWR | os.O_NONBLOCK)
fd = FileIO(report_fd, "rb+", closefd=False)
class AudioAction(Action):
"""Plays audio through the device"""

frame_number = 0
audio_buffer = b''

def setup(self, device):
self.audio_pipeline = self.controller.audio_pipeline

if not isinstance(self.audio_pipeline.get_callback(), AudioCallbacks):
self.audio_pipeline.set_callback(AudioCallbacks())

self.audio_pipeline.get_callback().callbacks.append(self.play_audio)

self.audio_pipeline.restart()

def play_audio(self, data):
pos = 0
sbc_headers = SBCHeaders()

#print()
#print("ld: ", len(data))
import os
#print("lpid:", os.getpid())
while pos != len(data):
sbc_headers.parse_header(data)
frame_length = sbc_headers.calculate_frame_length()
#print("fl: ", frame_length)

self.controller.device.play_audio(sbc_headers,
data[pos:pos + frame_length])
#self.lplay_audio(None, data[pos:(pos+frame_length)])

pos += frame_length
#print("done")

def lplay_audio(self, sbc_headers, data):
print()
print(len(self.audio_buffer))
print(len(data))
print()
if len(self.audio_buffer) + len(data) <= 448:
self.audio_buffer += data
return
print("running: ", len(self.audio_buffer))

rumble_weak = 0
rumble_strong = 0
r = 0
g = 0
b = 10
crc = b'\x00\x00\x00\x00'
volume_speaker = 80
volume_l = 60
volume_r = 60
unk2 = 100
unk3 = 100
flash_bright = 0
flash_dark = 0
#audio_header = b'\x24'
audio_header = b'\x24'


def frame_number(inc):
import struct
res = struct.pack("<H", self.frame_number)
self.frame_number += inc
if self.frame_number > 0xffff:
self.frame_number = 0
return res

def joy_data():
data = [0xff,0x4,0x00]
#global volume_r,volume_unk2, unk3
data.extend([rumble_weak,rumble_strong,r,g,b,flash_bright,flash_dark])
data.extend([0]*8)
data.extend([volume_l,volume_r,unk2,volume_speaker,unk3])
return data


def _11_report():
data = joy_data()
data.extend([0]*(48))
return b'\x11\xC0\x20' + bytearray(data) + crc

try:
if self.reported_11 == True: pass
except AttributeError:
fd.write(_11_report())

def _17_report(audo_data):
return (
b'\x17\x40\xA0'
+ frame_number(4)
+ audio_header
+ audo_data
+ bytearray(452 - len(audo_data)) + crc
)
report = _17_report(self.audio_buffer)

print(data[0])
self.audio_buffer = data

#if self._volume_r == 0:
# self.set_volume(60, 60, 0)
# self._control()
#self.write_report(report[0], report[1:])
print(report)
print(len(report))
fd.write(report)
2 changes: 2 additions & 0 deletions ds4drv/audio/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .sbc_headers import SBCHeaders
from .gst_pulse_to_sbc_pipeline import GstPulseToSBCPipeline
Loading

0 comments on commit d216ec6

Please sign in to comment.