mirror of
https://github.com/cyberboy666/r_e_c_u_r.git
synced 2025-12-05 16:00:06 +01:00
created seperate class for of_capture so they do not compete for access to camera etc
This commit is contained in:
20
actions.py
20
actions.py
@@ -9,18 +9,27 @@ from pythonosc import osc_server
|
||||
from pythonosc import dispatcher
|
||||
import threading
|
||||
import argparse
|
||||
from video_centre.capture import Capture
|
||||
from video_centre.of_capture import OfCapture
|
||||
|
||||
class Actions(object):
|
||||
def __init__(self, tk, message_handler, data, video_driver, capture, shaders, display):
|
||||
def __init__(self, tk, message_handler, data, video_driver, shaders, display, osc_client):
|
||||
self.tk = tk
|
||||
self.message_handler = message_handler
|
||||
self.data = data
|
||||
self.video_driver = video_driver
|
||||
self.capture = capture
|
||||
self.shaders = shaders
|
||||
self.display = display
|
||||
self.osc_client = osc_client
|
||||
self.create_capture_object('value')
|
||||
self.server = self.setup_osc_server()
|
||||
|
||||
def create_capture_object(self, value):
|
||||
if self.data.settings['other']['USE_OF_CAPTURE']['value'] == 'yes':
|
||||
self.capture = OfCapture(self.tk, self.osc_client, self.message_handler, self.data)
|
||||
else:
|
||||
self.capture = Capture(self.tk, self.message_handler, self.data)
|
||||
self.display.capture = self.capture
|
||||
|
||||
def move_browser_selection_down(self):
|
||||
self.display.browser_menu.navigate_menu_down()
|
||||
@@ -192,6 +201,13 @@ class Actions(object):
|
||||
if is_successful and self.video_driver.current_player.status != 'PAUSED':
|
||||
self.video_driver.current_player.toggle_pause()
|
||||
|
||||
## these are temp for testing !
|
||||
def start_of_capture_preview(self):
|
||||
self.osc_client.send_message("/capture/start", True)
|
||||
|
||||
def stop_of_capture_preview(self):
|
||||
self.osc_client.send_message("/capture/stop", True)
|
||||
|
||||
def toggle_capture_recording(self):
|
||||
is_recording = self.capture.is_recording
|
||||
if is_recording:
|
||||
|
||||
@@ -9,10 +9,10 @@ class Display(object):
|
||||
ROW_OFFSET = 6.0
|
||||
TITLE = '================== r_e_c_u_r =================='
|
||||
|
||||
def __init__(self, tk, video_driver, capture, shaders, message_handler, data):
|
||||
def __init__(self, tk, video_driver, shaders, message_handler, data):
|
||||
self.tk = tk
|
||||
self.video_driver = video_driver
|
||||
self.capture = capture
|
||||
self.capture = None
|
||||
self.shaders = shaders
|
||||
self.message_handler = message_handler
|
||||
self.data = data
|
||||
@@ -198,9 +198,17 @@ class Display(object):
|
||||
def _get_status_for_player(self):
|
||||
now_slot, now_status, now_alpha, next_slot, next_status, next_alpha = self.video_driver.get_player_info_for_status()
|
||||
|
||||
capture_status = self._generate_capture_status()
|
||||
if self.capture is not None:
|
||||
capture_status = self._generate_capture_status()
|
||||
preview_alpha = self.capture.get_preview_alpha()
|
||||
else:
|
||||
capture_status = ''
|
||||
preview_alpha = 0
|
||||
|
||||
preview_alpha = self.capture.get_preview_alpha()
|
||||
|
||||
if preview_alpha == None:
|
||||
preview_alpha = 0
|
||||
#print('capture alpha is {}'.format(preview_alpha))
|
||||
|
||||
self._set_colour_from_alpha(now_alpha, preview_alpha, next_alpha)
|
||||
|
||||
@@ -260,7 +268,10 @@ class Display(object):
|
||||
|
||||
def _set_colour_from_alpha(self, now_alpha, preview_alpha, next_alpha):
|
||||
upper_bound = 150
|
||||
is_recording = self.capture.is_recording == True
|
||||
if self.capture is not None:
|
||||
is_recording = self.capture.is_recording == True
|
||||
else:
|
||||
is_recording = False
|
||||
### scale values
|
||||
scaled_now = int(( now_alpha / 255 ) * (255 - upper_bound) + upper_bound)
|
||||
scaled_preview = int(( preview_alpha / 255 ) * (255 - upper_bound) + upper_bound)
|
||||
|
||||
@@ -59,10 +59,10 @@
|
||||
"DEFAULT": ["load_slot_6_into_next_player","toggle_shaders"]
|
||||
},
|
||||
"q": {
|
||||
"DEFAULT": ["load_slot_7_into_next_player", "increase_speed"]
|
||||
"DEFAULT": ["load_slot_7_into_next_player", "start_of_capture_preview"]
|
||||
},
|
||||
"r": {
|
||||
"DEFAULT": ["load_slot_8_into_next_player", "decrease_speed"]
|
||||
"DEFAULT": ["load_slot_8_into_next_player", "stop_of_capture_preview"]
|
||||
},
|
||||
"s": {
|
||||
"DEFAULT": ["load_slot_9_into_next_player","quit_the_program"]
|
||||
|
||||
@@ -131,6 +131,14 @@
|
||||
],
|
||||
"value": "dev"
|
||||
},
|
||||
"USE_OF_CAPTURE": {
|
||||
"action": "create_capture_object",
|
||||
"options": [
|
||||
"yes",
|
||||
"no"
|
||||
],
|
||||
"value": "no"
|
||||
},
|
||||
"VIDEO_BACKEND": {
|
||||
"action": "switch_video_backend",
|
||||
"options": [
|
||||
|
||||
@@ -15,7 +15,7 @@ from user_input.numpad_input import NumpadInput
|
||||
from user_input.midi_input import MidiInput
|
||||
from user_input.analog_input import AnalogInput
|
||||
from video_centre.video_driver import VideoDriver
|
||||
from video_centre.capture import Capture
|
||||
#from video_centre.capture import Capture
|
||||
from video_centre.shaders import Shaders
|
||||
import data_centre
|
||||
|
||||
@@ -43,14 +43,14 @@ def setup_osc_client():
|
||||
osc_client = setup_osc_client()
|
||||
# setup the video driver
|
||||
video_driver = VideoDriver(tk, osc_client, message_handler, data)
|
||||
capture = Capture(tk, osc_client, message_handler, data)
|
||||
#capture = Capture(tk, osc_client, message_handler, data)
|
||||
shaders = Shaders(tk, osc_client, message_handler, data)
|
||||
|
||||
# setup the display
|
||||
display = Display(tk, video_driver, capture, shaders, message_handler, data)
|
||||
display = Display(tk, video_driver, shaders, message_handler, data)
|
||||
|
||||
# setup the actions
|
||||
actions = Actions(tk, message_handler, data, video_driver, capture, shaders, display)
|
||||
actions = Actions(tk, message_handler, data, video_driver, shaders, display, osc_client)
|
||||
|
||||
numpad_input = NumpadInput(tk, message_handler, display, actions, data)
|
||||
midi_input = MidiInput(tk, message_handler, display, actions, data)
|
||||
|
||||
@@ -7,9 +7,8 @@ import fractions
|
||||
class Capture(object):
|
||||
PREVIEW_LAYER = 255
|
||||
|
||||
def __init__(self, root, osc_client, message_handler, data):
|
||||
def __init__(self, root, message_handler, data):
|
||||
self.root = root
|
||||
self.osc_client = osc_client
|
||||
self.message_handler = message_handler
|
||||
self.data = data
|
||||
|
||||
@@ -57,14 +56,19 @@ class Capture(object):
|
||||
if self.use_capture == False:
|
||||
self.message_handler.set_message('INFO', 'capture not enabled')
|
||||
return False
|
||||
if not self.device or self.device.closed:
|
||||
self.create_capture_device()
|
||||
self.is_previewing = True
|
||||
self.device.start_preview()
|
||||
self.set_preview_screen_size()
|
||||
self.set_capture_settings()
|
||||
self.device.preview.layer = self.PREVIEW_LAYER
|
||||
return True
|
||||
if self.data.settings['other']['USE_OF_CAPTURE']['value'] == 'yes':
|
||||
self.osc_client.send_message("/capture/start", True)
|
||||
self.is_previewing = True
|
||||
return True
|
||||
else:
|
||||
if not self.device or self.device.closed:
|
||||
self.create_capture_device()
|
||||
self.is_previewing = True
|
||||
self.device.start_preview()
|
||||
self.set_preview_screen_size()
|
||||
self.set_capture_settings()
|
||||
self.device.preview.layer = self.PREVIEW_LAYER
|
||||
return True
|
||||
|
||||
def set_capture_settings(self):
|
||||
if self.capture_type == "piCaptureSd1":
|
||||
@@ -84,10 +88,14 @@ class Capture(object):
|
||||
self.device.preview.fullscreen = True
|
||||
|
||||
def stop_preview(self):
|
||||
self.device.stop_preview()
|
||||
self.is_previewing = False
|
||||
if not self.device.recording:
|
||||
self.device.close()
|
||||
if self.data.settings['other']['USE_OF_CAPTURE']['value'] == 'yes':
|
||||
self.osc_client.send_message("/capture/stop", True)
|
||||
self.is_previewing = False
|
||||
else:
|
||||
self.device.stop_preview()
|
||||
self.is_previewing = False
|
||||
if not self.device.recording:
|
||||
self.device.close()
|
||||
|
||||
def start_recording(self):
|
||||
if self.use_capture == False:
|
||||
@@ -95,7 +103,7 @@ class Capture(object):
|
||||
return
|
||||
if not self.check_available_disk_space():
|
||||
return
|
||||
if self.device.closed:
|
||||
if self.device is None or self.device.closed:
|
||||
self.create_capture_device()
|
||||
|
||||
if not os.path.exists(self.video_dir):
|
||||
@@ -185,22 +193,10 @@ class Capture(object):
|
||||
error_info = e.message
|
||||
else:
|
||||
error_info = e
|
||||
self.message_handler.set_message('ERROR',error_info)
|
||||
else:
|
||||
self.message_handler.set_message('ERROR',error_info)
|
||||
return 0
|
||||
return 0
|
||||
|
||||
#def is_previewing(self):
|
||||
# if self.device.closed or not self.device.preview:
|
||||
# return False
|
||||
#else:
|
||||
# return True
|
||||
|
||||
#def is_recording(self):
|
||||
# if self.device.recording:
|
||||
# return True
|
||||
#else:
|
||||
# return False
|
||||
|
||||
def set_colour(self, u_value, v_value):
|
||||
(u, v) = (128, 128)
|
||||
if self.device.color_effects is not None:
|
||||
@@ -235,6 +231,3 @@ class Capture(object):
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
189
video_centre/of_capture.py
Normal file
189
video_centre/of_capture.py
Normal file
@@ -0,0 +1,189 @@
|
||||
import os
|
||||
import subprocess
|
||||
import datetime
|
||||
import fractions
|
||||
|
||||
class OfCapture(object):
|
||||
def __init__(self, root, osc_client, message_handler, data):
|
||||
self.root = root
|
||||
self.osc_client = osc_client
|
||||
self.message_handler = message_handler
|
||||
self.data = data
|
||||
|
||||
self.device = None
|
||||
self.is_recording = False
|
||||
self.is_previewing = False
|
||||
self.video_dir = '/home/pi/Videos/'
|
||||
self.update_capture_settings()
|
||||
#self.create_capture_device()
|
||||
|
||||
#def create_capture_device(self):
|
||||
# if self.use_capture:
|
||||
# self.update_capture_settings()
|
||||
# try:
|
||||
# self.device = picamera.PiCamera(resolution=self.resolution, framerate=self.framerate, sensor_mode = self.sensor_mode)
|
||||
# except picamera.exc.PiCameraError as e:
|
||||
# self.use_capture = False
|
||||
# print('camera exception is {}'.format(e))
|
||||
# self.message_handler.set_message('INFO', 'no capture device attached')
|
||||
|
||||
def update_capture_settings(self):
|
||||
##setting class variables
|
||||
self.use_capture = self.data.settings['capture']['DEVICE']['value'] == 'enabled'
|
||||
self.resolution = self.convert_resolution_value(self.data.settings['capture']['RESOLUTION']['value'])
|
||||
self.framerate = self.convert_framerate_value(self.data.settings['capture']['FRAMERATE']['value'])
|
||||
self.capture_type = self.data.settings['capture']['TYPE']['value']
|
||||
if self.capture_type == "piCaptureSd1":
|
||||
self.sensor_mode = 6
|
||||
else:
|
||||
self.sensor_mode = 0
|
||||
##update current instance (device) if in use
|
||||
if self.device and not self.device.closed:
|
||||
self.device.image_effect = self.data.settings['capture']['IMAGE_EFFECT']['value']
|
||||
self.device.shutter_speed = self.convert_shutter_value(self.data.settings['capture']['SHUTTER']['value'])
|
||||
## can only update resolution and framerate if not recording
|
||||
if not self.is_recording:
|
||||
self.device.framerate = self.framerate
|
||||
self.device.resolution = self.resolution
|
||||
|
||||
|
||||
def start_preview(self):
|
||||
if self.use_capture == False:
|
||||
self.message_handler.set_message('INFO', 'capture not enabled')
|
||||
return False
|
||||
|
||||
self.is_previewing = True
|
||||
self.set_capture_settings()
|
||||
self.osc_client.send_message("/capture/preview/start", True)
|
||||
return True
|
||||
|
||||
def set_capture_settings(self):
|
||||
if self.capture_type == "piCaptureSd1":
|
||||
pass
|
||||
#self.device.sensor_mode = 6
|
||||
#self.device.awb_mode = "off"
|
||||
#self.device.awb_gains = 1.0
|
||||
#self.device.exposure_mode = "off"
|
||||
else:
|
||||
pass
|
||||
#self.sensor_mode = 0
|
||||
|
||||
def stop_preview(self):
|
||||
self.osc_client.send_message("/capture/preview/stop", True)
|
||||
self.is_previewing = False
|
||||
|
||||
def start_recording(self):
|
||||
if self.use_capture == False:
|
||||
self.message_handler.set_message('INFO', 'capture not enabled')
|
||||
return
|
||||
if not self.check_available_disk_space():
|
||||
return
|
||||
|
||||
if not os.path.exists(self.video_dir):
|
||||
os.makedirs(self.video_dir)
|
||||
self.is_recording = True
|
||||
#self.device.start_recording(self.video_dir + '/raw.h264')
|
||||
self.osc_client.send_message("/capture/record/start", True)
|
||||
self.monitor_disk_space()
|
||||
|
||||
def monitor_disk_space(self):
|
||||
if self.is_recording:
|
||||
if self.check_available_disk_space():
|
||||
self.root.after(10000, self.monitor_disk_space)
|
||||
else:
|
||||
self.stop_recording()
|
||||
|
||||
def check_available_disk_space(self):
|
||||
mb_free = self.data._get_mb_free_diskspace(self.video_dir)
|
||||
if mb_free < 10:
|
||||
self.message_handler.set_message('INFO', 'insufficient space on disk')
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def stop_recording(self):
|
||||
#self.device.stop_recording()
|
||||
self.osc_client.send_message("/capture/record/stop", True)
|
||||
#set status to saving
|
||||
mp4box_process, recording_name = self.convert_raw_recording()
|
||||
self.is_recording = 'saving'
|
||||
self.root.after(0, self.wait_for_recording_to_save, mp4box_process, recording_name)
|
||||
|
||||
self.update_capture_settings()
|
||||
# return path to the video
|
||||
if not self.device.preview:
|
||||
self.device.close()
|
||||
|
||||
def convert_raw_recording(self):
|
||||
recording_path , recording_name = self.generate_recording_path()
|
||||
try:
|
||||
if self.sensor_mode == 6:
|
||||
mp4box_process = subprocess.Popen(['MP4Box', '-fps', '60', '-add', self.video_dir + '/raw.h264', recording_path])
|
||||
return mp4box_process , recording_name
|
||||
else:
|
||||
mp4box_process = subprocess.Popen(['MP4Box', '-add', self.video_dir + '/raw.h264', recording_path])
|
||||
return mp4box_process , recording_name
|
||||
except Exception as e:
|
||||
print(e)
|
||||
if hasattr(e, 'message'):
|
||||
error_info = e.message
|
||||
else:
|
||||
error_info = e
|
||||
self.message_handler.set_message('ERROR',error_info)
|
||||
|
||||
|
||||
def wait_for_recording_to_save(self, process, name):
|
||||
print('the poll is {}'.format(process.poll()))
|
||||
if process.poll() is not None:
|
||||
self.is_recording = False
|
||||
os.remove(self.video_dir + '/raw.h264')
|
||||
self.data.create_new_slot_mapping_in_first_open(name)
|
||||
else:
|
||||
self.root.after(300, self.wait_for_recording_to_save, process, name)
|
||||
|
||||
def generate_recording_path(self):
|
||||
rec_dir = self.video_dir + '/recordings'
|
||||
if not os.path.exists(rec_dir):
|
||||
os.makedirs(rec_dir)
|
||||
date = datetime.datetime.now().strftime("%Y-%m-%d")
|
||||
i = 0
|
||||
while os.path.exists('{}/rec-{}-{}.mp4'.format(rec_dir,date, i)):
|
||||
i += 1
|
||||
name = 'rec-{}-{}.mp4'.format(date, i)
|
||||
return '{}/{}'.format(rec_dir,name), name
|
||||
|
||||
def get_recording_time(self):
|
||||
pass
|
||||
#if not self.device or not self.device.recording or self.device.frame.timestamp == None:
|
||||
# return -1
|
||||
#else:
|
||||
# return self.device.frame.timestamp / 1000000
|
||||
|
||||
def get_preview_alpha(self):
|
||||
return 0
|
||||
|
||||
def set_colour(self, u_value, v_value):
|
||||
pass
|
||||
|
||||
def set_alpha(self, amount):
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def convert_resolution_value(setting_value):
|
||||
split_values = setting_value.split('x')
|
||||
return (int(split_values[0]), int(split_values[1]))
|
||||
|
||||
@staticmethod
|
||||
def convert_framerate_value(setting_value):
|
||||
return fractions.Fraction(setting_value).limit_denominator()
|
||||
|
||||
def convert_shutter_value(self, setting_value):
|
||||
if setting_value == 'auto':
|
||||
return 0
|
||||
elif setting_value == 'max':
|
||||
return int(1000000 / self.framerate)
|
||||
else:
|
||||
return int(fractions.Fraction(setting_value) * 1000000)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user