From c001cb10f69d4530c1652fdf1531a127765de573 Mon Sep 17 00:00:00 2001 From: langolierz Date: Fri, 11 May 2018 00:18:10 +0000 Subject: [PATCH] plugged a large memory leak, there still seems to be a small one - added a program reset as workaround for now --- actions.py | 10 +- display_centre/display.py | 8 +- display_centre/display.py.save | 264 ----------------------------- json_objects/settings_default.json | 5 + r_e_c_u_r.py | 3 + user_input/midi_input.py | 2 +- 6 files changed, 23 insertions(+), 269 deletions(-) delete mode 100644 display_centre/display.py.save mode change 100644 => 100755 r_e_c_u_r.py diff --git a/actions.py b/actions.py index 700c500..4df8790 100644 --- a/actions.py +++ b/actions.py @@ -1,5 +1,8 @@ import subprocess +import tracemalloc import data_centre.length_setter as length_setter +import sys +import os class Actions(object): def __init__(self, tk, message_handler, data, video_driver, capture, display): @@ -232,7 +235,7 @@ class Actions(object): def check_and_set_output_mode_on_boot(self): #### checking if pi display mode is composite response = str(subprocess.check_output(['tvservice', '-s'])) - if '0x80002' in response or '0x40002' in response: + if 'PAL' in response or 'NTSC' in response: self.data.update_setting_value('video', 'OUTPUT', 'composite') else: self.data.update_setting_value('video', 'OUTPUT', 'hdmi') @@ -333,6 +336,11 @@ class Actions(object): self.toggle_x_autorepeat() self.tk.destroy() + def restart_the_program(self): + self.quit_the_program() + os.execv('/usr/bin/python3', [sys.argv[0],'/home/pi/r_e_c_u_r/r_e_c_u_r.py']) + + def set_fixed_length(self, value): self.data.control_mode = 'LENGTH_SET' self.message_handler.set_message('INFO', 'tap: ■ ; < > : back') diff --git a/display_centre/display.py b/display_centre/display.py index 4f1e467..a79039e 100644 --- a/display_centre/display.py +++ b/display_centre/display.py @@ -7,6 +7,7 @@ class Display(object): MENU_HEIGHT = 10 SELECTOR_WIDTH = 0.47 ROW_OFFSET = 6.0 + TITLE = '================== r_e_c_u_r ==================' def __init__(self, tk, video_driver, capture, message_handler, data): self.tk = tk @@ -26,7 +27,7 @@ class Display(object): @staticmethod def _create_display_text(tk): - return Text(tk, bg="black", fg="white", font=('Liberation Mono', 13)) + return Text(tk, bg="black", fg="white", font=('Liberation Mono', 13), undo=False) def _add_tags(self): self.display_text.tag_configure("SELECT", background="white", foreground="black") @@ -39,16 +40,17 @@ class Display(object): self.display_text.tag_configure("COLUMN_NAME", background="black", foreground="VioletRed1") self.display_text.tag_configure("FUNCTION", background="yellow", foreground="black") self.display_text.tag_configure("BROKEN_PATH", background="black", foreground="gray") - + def _load_display(self): self._load_title() self._load_player() self._load_display_body() self._load_message() + #print('the number of tags are {}'.format(len(self.display_text.tag_names()))) self.display_text.pack() def _load_title(self): - self.display_text.insert(END, '================== r_e_c_u_r ================== \n') + self.display_text.insert(END, self.TITLE + ' \n') self.display_text.tag_add("TITLE", 1.19, 1.28) def _load_player(self): diff --git a/display_centre/display.py.save b/display_centre/display.py.save deleted file mode 100644 index 5bcb724..0000000 --- a/display_centre/display.py.save +++ /dev/null @@ -1,264 +0,0 @@ -from tkinter import Text, END -import math -import time -import display_centre.menu as menu - -class Display(object): - MENU_HEIGHT = 10 - SELECTOR_WIDTH = 0.47 - ROW_OFFSET = 6.0 - VIDEO_DISPLAY_BANNER_TEXT = ' {} {} {}' - - def __init__(self, tk, video_driver, capture, message_handler, data): - self.tk = tk - self.video_driver = video_driver - self.capture = capture - self.message_handler = message_handler - self.data = data - self.browser_menu = menu.BrowserMenu(self.data, self.MENU_HEIGHT) - self.settings_menu = menu.SettingsMenu(self.data, self.MENU_HEIGHT) - - #self.top_menu_index = 0 - #self.selected_list_index = self.top_menu_index - - self.display_text = self._create_display_text(self.tk) - self._add_tags() - self._update_screen_every_second() - - @staticmethod - def _create_display_text(tk): - return Text(tk, bg="black", fg="white", font=('Liberation Mono', 13)) - - def _add_tags(self): - self.display_text.tag_configure("SELECT", background="white", foreground="black") - self.display_text.tag_configure("TITLE", background="black", foreground="red") - self.display_text.tag_configure("DISPLAY_MODE", background="black", foreground="magenta") - self.display_text.tag_configure("ERROR_MESSAGE", background="red", foreground="white") - self.display_text.tag_configure("INFO_MESSAGE", background="blue", foreground="white") - self.display_text.tag_configure("PLAYER_INFO", background="black", foreground="yellow") - self.display_text.tag_configure("COLUMN_NAME", background="black", foreground="cyan") - self.display_text.tag_configure("FUNCTION", background="cyan", foreground="black") - self.display_text.tag_configure("BROKEN_PATH", background="black", foreground="gray") - - def _load_display(self): - self._load_title() - self._load_player() - self._load_display_body() - self._load_message() - self.display_text.pack() - - def _load_title(self): - self.display_text.insert(END, '================== r_e_c_u_r ================== \n') - self.display_text.tag_add("TITLE", 1.19, 1.28) - - def _load_player(self): - text, banner = self._get_info_for_player() - end_of_text = float("3." + str(len(text))) - end_of_banner = float("3." + str(len(banner))) - self.display_text.insert(END, text + '\n') - self.display_text.tag_add("PLAYER_INFO", 2.0, end_of_text) - self.display_text.insert(END, banner + '\n') - self.display_text.tag_add("PLAYER_INFO", 3.0, end_of_banner) - - def _load_display_body(self): - if self.data.display_mode == 'BROWSER': - self._load_browser() - elif self.data.display_mode == 'SETTINGS': - self._load_settings() - else: - self._load_sampler() - self.display_text.tag_add("COLUMN_NAME", 5.0, 6.0) - - - def _load_sampler(self): - bank_data = self.data.bank_data[self.data.bank_number] - self.display_text.insert(END, '------------------ ------------------ \n') - self.display_text.tag_add("DISPLAY_MODE", 4.19, 4.29) - - self.display_text.insert(END, '{:^6} {:<16} {:<4} {:<4} {:<4} \n'.format( - '{}-slot'.format(self.data.bank_number), 'name', 'length', 'start', 'end')) - for index, slot in enumerate(bank_data): - name_without_extension = slot['name'].rsplit('.',1)[0] - self.display_text.insert(END, '{:^4} {:<18} {:<4} {:<4} {:<4} \n'.format( - index, name_without_extension[0:22], self.format_time_value(slot['length']), - self.format_time_value(slot['start']), self.format_time_value(slot['end']))) - if self.data.is_this_path_broken(slot['location']): - self.display_text.tag_add("BROKEN_PATH", self.ROW_OFFSET + index, - self.ROW_OFFSET + self.SELECTOR_WIDTH + index) - current_bank , current_slot = self.data.split_bankslot_number(self.video_driver.current_player.bankslot_number) - if current_bank is self.data.bank_number: - self.selected_list_index = current_slot - else: - self.selected_list_index = 0 - - def _load_browser(self): - browser_list = self.browser_menu.menu_list - number_of_lines_displayed = 0 - self.display_text.insert(END, '------------------ ------------------ \n') - self.display_text.tag_add("DISPLAY_MODE", 4.19, 4.29) - self.display_text.insert(END, '{:40} {:5} \n'.format('path', 'slot')) - - number_of_browser_items = len(browser_list) - for index in range(number_of_browser_items): - if number_of_lines_displayed >= self.MENU_HEIGHT: - break - if index >= self.browser_menu.top_menu_index: - path = browser_list[index] - self.display_text.insert(END, '{:40} {:5} \n'.format(path['name'][0:35], path['slot'])) - number_of_lines_displayed = number_of_lines_displayed + 1 - - for index in range(self.MENU_HEIGHT - number_of_browser_items): - self.display_text.insert(END, '\n') - - self._highlight_this_row(self.browser_menu.selected_list_index - self.browser_menu.top_menu_index) - - def _load_settings(self): - line_count = 0 - settings_list = self.settings_menu.menu_list - self.display_text.insert(END, '------------------ ----------------- \n') - self.display_text.tag_add("DISPLAY_MODE", 4.19, 4.29) - self.display_text.insert(END, '{:^23} {:^22} \n'.format('SETTING', 'VALUE')) - number_of_settings_items = len(settings_list) - for index in range(number_of_settings_items): - if line_count >= self.MENU_HEIGHT: - break - if index >= self.settings_menu.top_menu_index: - setting = settings_list[index] - self.display_text.insert(END, '{:<23} {:<22} \n'.format(setting['name'], setting['value'])) - line_count = line_count + 1 - - for index in range(self.MENU_HEIGHT - number_of_settings_items): - self.display_text.insert(END, '\n') - - self._highlight_this_row(self.settings_menu.selected_list_index - self.settings_menu.top_menu_index) - - def _load_message(self): - if self.message_handler.current_message[1]: - self.display_text.insert(END, '{:5} {:38}'.format( - self.message_handler.current_message[0], self.message_handler.current_message[1][0:38])) - self.display_text.tag_add('{}_MESSAGE'.format( - self.message_handler.current_message[0]), 16.0,16.0 + self.SELECTOR_WIDTH) - if self.message_handler.current_message[2]: - self.message_handler.current_message[2] = False - message_length = 4000 - self.tk.after(message_length, self.message_handler.clear_message) - elif self.data.function_on: - self.display_text.insert(END, '{:^45}'.format('< FUNCTION KEY ON >')) - self.display_text.tag_add('FUNCTION', 16.0,16.0 + self.SELECTOR_WIDTH) - else: - self.display_text.insert(END, '{:8} {:<10}'.format('CONTROL:', self.data.control_mode)) - self.display_text.tag_add('TITLE', 16.0,16.0 + self.SELECTOR_WIDTH) - - def _highlight_this_row(self, row): - self.display_text.tag_add("SELECT", self.ROW_OFFSET + row, - self.ROW_OFFSET + self.SELECTOR_WIDTH + row) - - def _unhighlight_this_row(self, row): - self.display_text.tag_remove("SELECT", self.ROW_OFFSET + row, - self.ROW_OFFSET + self.SELECTOR_WIDTH + row) - - def _get_info_for_player(self): - now_slot, now_status, next_slot, next_status, position, crop_length, start, end = self.video_driver.get_info_for_player_display() - banner = self.create_video_display_banner(start, end, crop_length, position) - time_been = self.format_time_value(position - start) - time_left = self.format_time_value(end - position) - capture_status = self._generate_capture_status() - - now_info = 'NOW [{}] {}'.format(now_slot, now_status) - next_info = 'NEXT [{}] {}'.format(next_slot, next_status) - capture_info = '{}'.format(capture_status) - - return self.VIDEO_DISPLAY_BANNER_TEXT.format(time_been, banner, time_left), \ - '{:17} {:10} {:17}'.format(now_info[:17], capture_info[:10], next_info[:18]) - - def _generate_capture_status(self): - is_previewing = self.capture.is_previewing - is_recording = self.capture.is_recording - rec_time = -1 - if is_recording == True: - rec_time = self.capture.get_recording_time() - capture_status = '' - if is_previewing and is_recording == True: - capture_status = '<{}>'.format('REC'+ self.format_time_value(rec_time)) - elif is_previewing and is_recording == 'saving': - capture_status = '<{}>'.format('_saving_') - elif is_previewing: - capture_status = '<{}>'.format('_preview') - elif is_recording == True: - capture_status = '[{}]'.format('REC'+ self.format_time_value(rec_time)) - elif is_recording == 'saving': - capture_status = '[{}]'.format('_saving_') - else: - capture_status = '' - - return capture_status - - @staticmethod - def create_video_display_banner(start, end, crop_length, position): - - banner_list = ['[', '-', '-', '-', '-', '-', '-', '-', '-', - '-', '-', '-', '-', '-', '-', '-', '-', '-', - '-', '-', '-', '-', '-', '-', '-', '-', '-', - '-', '-', '-', '-', '-', - ']'] - max = len(banner_list) - 1 - if position < start: - banner_list[0] = '<' - elif position > end: - banner_list[max] = '>' - elif crop_length != 0: - marker = int(math.floor(float(position - start) / - float(crop_length) * (max - 1)) + 1) - banner_list[marker] = '*' - - return ''.join(banner_list) - - def _update_screen_every_second(self): - self.refresh_display() - self.tk.after(500, self._update_screen_every_second) - - def refresh_display(self): - self.display_text.configure(state='normal') - self.display_text.delete(1.0, END) - self._load_display() - self.display_text.configure(state='disable') - self.display_text.focus_set() - - def navigate_menu(self, move_direction, number_items_in_list): - last_list_index = number_items_in_list - 1 - bottom_menu_index = self.top_menu_index + self.MENU_HEIGHT - 1 - - ##self._unhighlight_this_row(self.selected_list_index - self.top_menu_index) - - if move_direction == 'down': - if self.selected_list_index != last_list_index: - if self.selected_list_index == bottom_menu_index: - self.top_menu_index += 1 - self.selected_list_index += 1 - else: - self.top_menu_index = 0 - self.selected_list_index = self.top_menu_index - - elif move_direction == 'up': - if self.selected_list_index != 0: - if self.selected_list_index == self.top_menu_index: - self.top_menu_index -= 1 - self.selected_list_index -= 1 - else: - self.selected_list_index = last_list_index - self.top_menu_index = last_list_index - (self.MENU_HEIGHT - 1) - if self.top_menu_index < 0: - self.top_menu_index = 0 - - ##self._highlight_this_row(self.selected_list_index - self.top_menu_index) - - return - - @staticmethod - def format_time_value(time_in_seconds): - if time_in_seconds < 0: - return '' - elif time_in_seconds >= 6000: - return '99:99' - else: - return time.strftime("%M:%S", time.gmtime(time_in_seconds)) diff --git a/json_objects/settings_default.json b/json_objects/settings_default.json index 123a32a..411f0cf 100644 --- a/json_objects/settings_default.json +++ b/json_objects/settings_default.json @@ -95,6 +95,11 @@ ], "value": "off" }, + "RESTART_PROGRAM": { + "action": "restart_the_program", + "options": [], + "value": null + }, "QUIT": { "action": "quit_the_program", "options": [], diff --git a/r_e_c_u_r.py b/r_e_c_u_r.py old mode 100644 new mode 100755 index f6b2136..e414a28 --- a/r_e_c_u_r.py +++ b/r_e_c_u_r.py @@ -1,6 +1,9 @@ +#!/usr/bin/python + import traceback from tkinter import Tk, Frame import sys +import tracemalloc from actions import Actions from data_centre.data import Data diff --git a/user_input/midi_input.py b/user_input/midi_input.py index dbe68df..86911c8 100644 --- a/user_input/midi_input.py +++ b/user_input/midi_input.py @@ -16,7 +16,7 @@ class MidiInput(object): def try_open_port(self): midi_setting = self.data.settings['midi']['INPUT']['value'] - print('try open port : midi setting is {}'.format(midi_setting)) + #print('try open port : midi setting is {}'.format(midi_setting)) if midi_setting == 'enabled': midi_ports = mido.get_input_names() midi_device_on_port_20 = [s for s in midi_ports if '20:0' in s]