def _initPlayer(self, videoUrls): self.videoPlayers = [] for playerId, videoUrl in enumerate(videoUrls): videoPlayer = VideoPlayer(playerId, videoUrl) self.maxFps = max(self.maxFps, videoPlayer.fps) self.maxFrameCount = max(self.maxFrameCount, videoPlayer.frameCount) self.videoPlayers.append(videoPlayer) self.videoWidget = VideoWidget(self.videoPlayers) for videoPlayer in self.videoPlayers: videoPlayer.setMaxFps(self.maxFps)
def __init__(self): super().__init__() assert len(self.UTILITY_SCORE) == len(self.VIDEO_BIT_RATE) # get video list vlc = video_list_collector() vlc.save_dir = self.VIDEO_TRACE vlc.load() self.video_list = vlc.get_trace_matrix(self.VIDEO_BIT_RATE) self.video_player = VideoPlayer(self.birate_list,self.video_list) self.buffer_thresh = self.video_player.buffer_thresh self.action_list = len(self.video_list) self.network_speed = np.zeros(self.HISTORY_SIZE) self.reset()
def play_video(self: 'Gui'): if not self.playing_video: self.playing_video = True self.video_player = VideoPlayer(self.playJpgFolder, self.playWavFile, 30) self.play_video_button.setText('Pause') self.video_player.play() self.play_video_button.setText('Play') self.playing_video = False else: self.keyboard_emulator.press('p') self.keyboard_emulator.release('p') self.video_paused = not self.video_paused if self.video_paused: self.play_video_button.setText('Play') else: self.play_video_button.setText('Pause')
def __init__(self, config_path): self._logger = getLogger("raspberry") self._logger.setLevel(INFO) formatter = Formatter( '%(asctime)s [%(name)s] %(levelname)s : %(message)s') stream_handler = StreamHandler() stream_handler.setLevel(INFO) stream_handler.setFormatter(formatter) self._logger.addHandler(stream_handler) signal.signal(signal.SIGINT, self.exit_gracefully) signal.signal(signal.SIGTERM, self.exit_gracefully) self._logger.info("Initializing...") self.preference_checker = Preferences(config_path) self.video_player = VideoPlayer() self.tv_controller = TVController() self._logger.info("Ready")
class TVApp: def __init__(self, config_path): self._logger = getLogger("raspberry") self._logger.setLevel(INFO) formatter = Formatter( '%(asctime)s [%(name)s] %(levelname)s : %(message)s') stream_handler = StreamHandler() stream_handler.setLevel(INFO) stream_handler.setFormatter(formatter) self._logger.addHandler(stream_handler) signal.signal(signal.SIGINT, self.exit_gracefully) signal.signal(signal.SIGTERM, self.exit_gracefully) self._logger.info("Initializing...") self.preference_checker = Preferences(config_path) self.video_player = VideoPlayer() self.tv_controller = TVController() self._logger.info("Ready") def run(self): self._logger.info( "Waiting 1 min if you want to stop me before I go full screen...") time.sleep(60) self._logger.info("Starting all components now...") self.tv_controller.start(self.preference_checker.time_on_off) self.video_player.start(self.preference_checker.video_list) self.preference_checker.start() while True: time.sleep(120) def exit_gracefully(self, signum, frame): self._logger.info("Key pressed, exiting") self.tv_controller.stop() self.video_player.stop() self.preference_checker.stop() self._logger.info("End")
def _reload(self, load): if self.player != None: self.player.close() self.player = VideoPlayer() self.player.set_window_id(self.gui_controller.get_video_window_id()) self.player.activate_video_callback( self.gui_controller.activate_video_area) self.player.open(self.exercise.get_video_path()) self.player.set_callback(self._time_callback) self.paused = False self.gui_controller.activate_video_area(False) self.gui_controller.activate("loaded") self._update_word_list() self.timeUpdateThreadId = thread.start_new_thread( self.time_update_thread, ()) if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() else: self.pause()
class Viewer(object): ''' A high-level class for viewing any supported media type. Delegates viewing to the browser or video player depending on media type. The displaying is performed in a separate thread, so shutdown() must be called before killing the program to avoid errors upon program termination. ''' DISPLAY_TIME_GRANULARITY = 1 # seconds BROWSER = Browser() PLAYER = VideoPlayer() VIEWERS = { Media.IMAGE: BROWSER, Media.WEB_PAGE: BROWSER, Media.VIDEO: PLAYER } def display_content(self, content, is_interrupted_func): self.logger = logging.getLogger(__name__) self.logger.debug('Viewer received content %s', content) viewer = self.VIEWERS[content.content_type] displayed_time = 0 viewer.display_content(content) self.running = True while self.running and displayed_time < content.view_time: if is_interrupted_func(content): break time.sleep(self.DISPLAY_TIME_GRANULARITY) displayed_time += self.DISPLAY_TIME_GRANULARITY self.keep_alive(viewer, content) viewer.hide() self.logger.debug('Viewer finished displaying content %s', content) def keep_alive(self, viewer, content): if not viewer.is_alive(): self.logger.debug('Resurrecting viewer for content %s', content) viewer.display_content(content) def shutdown(self): self.logger.debug('Viewer shutdown requested') self.running = False self.BROWSER.shutdown() self.PLAYER.shutdown() self.logger.debug('Viewer shutdown complete')
def main(): video_play_thread = [1] is_looking_thread = IsLookingThread(video_play_thread) video_player = VideoPlayer("tanioka.mp4") is_looking_thread.start() while (True): video_player.play() video_player.check_state(video_play_thread[0]) if cv2.waitKey(1) & 0xFF == ord('q'): break
def _reload(self, load): if self.player != None: self.player.close() self.player = VideoPlayer() self.player.set_window_id(self.gui_controller.get_video_window_id()) self.player.activate_video_callback(self.gui_controller.activate_video_area) self.player.open(self.exercise.get_video_path()) self.player.set_callback(self._time_callback) self.paused = False self.gui_controller.activate_video_area(False) self.gui_controller.activate("loaded") self._update_word_list() self.timeUpdateThreadId = thread.start_new_thread(self.time_update_thread, ()) if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() else: self.pause()
def _setup_player(self, mode, data_source=None): self.config[CONFIG_KEY_MODE] = mode # Set data source if specified if data_source is not None: self.config[CONFIG_KEY_DATA_SOURCE] = data_source # Quit current player if self.player is not None: self.player.release() self.player = None if self.player is None: # Create new player if mode in [MODE_VIDEO, MODE_STREAM]: from video_player import VideoPlayer self.player = VideoPlayer(self.config) elif mode == MODE_WEBPAGE: from web_player import WebPlayer self.player = WebPlayer(self.config) else: self.player.mode = mode self.player.data_source = self.config[CONFIG_KEY_DATA_SOURCE]
from video_player import VideoPlayer video_input = 'input/project_dataset/frames/concert' audio_samples = 'input/project_dataset/audio/concert.wav' player = VideoPlayer(video_input, audio_samples, 30) player.play()
#if video file input if len(sys.argv) > 1: cameras = [CameraFinder.create_file_camera(sys.argv[1])] # else scan for available cameras else: cameras = CameraFinder.get_available_cameras() print('Found {} cameras.'.format(len(cameras))) if len(cameras) > 0: # index of the currently active camera cam_index = 0 # initialize video player player = VideoPlayer(cameras[cam_index], WINDOW_NAME, fourcc) player.play() while player.playing: if player.camera_defect: print('ERROR: Camera not responding. Removing it from the list.') print('ERROR: CAMERA_BACKEND:', cameras[cam_index % len(cameras)].backend) player.stop() # remove the malfunctioning camera cameras.remove(cameras[cam_index % len(cameras)]) player.change_camera(cameras[cam_index % len(cameras)]) player.play() # handle input key_pressed = cv2.waitKey(1)
def refresh_caches(self): global _player _player=VideoPlayer() if not _standalone: self._get_data_for_first_video()
def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1030, 481) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.video_player_original = VideoPlayer(self.centralwidget) self.video_player_original.setEnabled(True) self.video_player_original.setGeometry(QtCore.QRect(10, 40, 500, 360)) self.video_player_original.setObjectName("video_player_original") self.video_player_result = VideoPlayer(self.centralwidget) self.video_player_result.setGeometry(QtCore.QRect(520, 40, 500, 360)) self.video_player_result.setObjectName("video_player_result") self.input_min_length = QtWidgets.QSpinBox(self.centralwidget) self.input_min_length.setGeometry(QtCore.QRect(210, 410, 171, 24)) self.input_min_length.setMaximum(10000) self.input_min_length.setProperty("value", 100) self.input_min_length.setObjectName("input_min_length") self.input_thresh = QtWidgets.QSpinBox(self.centralwidget) self.input_thresh.setGeometry(QtCore.QRect(20, 410, 171, 24)) self.input_thresh.setMinimum(-99) self.input_thresh.setProperty("value", -40) self.input_thresh.setObjectName("input_thresh") self.button_convert = QtWidgets.QPushButton(self.centralwidget) self.button_convert.setGeometry(QtCore.QRect(830, 400, 181, 32)) self.button_convert.setObjectName("button_convert") self.line = QtWidgets.QFrame(self.centralwidget) self.line.setGeometry(QtCore.QRect(510, -10, 20, 391)) self.line.setFrameShape(QtWidgets.QFrame.VLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) self.line.setObjectName("line") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(180, 10, 200, 20)) font = QtGui.QFont() font.setPointSize(16) self.label.setFont(font) self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(710, 10, 200, 20)) font = QtGui.QFont() font.setPointSize(16) self.label_2.setFont(font) self.label_2.setObjectName("label_2") self.line_2 = QtWidgets.QFrame(self.centralwidget) self.line_2.setGeometry(QtCore.QRect(-3, 370, 1041, 20)) self.line_2.setFrameShape(QtWidgets.QFrame.HLine) self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) self.line_2.setObjectName("line_2") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setGeometry(QtCore.QRect(30, 390, 181, 16)) self.label_3.setObjectName("label_3") self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setGeometry(QtCore.QRect(220, 390, 161, 20)) self.label_4.setObjectName("label_4") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 1030, 22)) self.menubar.setObjectName("menubar") self.menu = QtWidgets.QMenu(self.menubar) self.menu.setObjectName("menu") self.menu_2 = QtWidgets.QMenu(self.menubar) self.menu_2.setObjectName("menu_2") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.action_2 = QtWidgets.QAction(MainWindow) self.action_2.setObjectName("action_2") self.action_3 = QtWidgets.QAction(MainWindow) self.action_3.setObjectName("action_3") self.action_4 = QtWidgets.QAction(MainWindow) self.action_4.setObjectName("action_4") self.actionGithub = QtWidgets.QAction(MainWindow) self.actionGithub.setObjectName("actionGithub") self.menu.addAction(self.action_2) self.menu.addAction(self.action_3) self.menu_2.addAction(self.action_4) self.menu_2.addAction(self.actionGithub) self.menubar.addAction(self.menu.menuAction()) self.menubar.addAction(self.menu_2.menuAction()) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow)
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(1030, 481) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.video_player_original = VideoPlayer(self.centralwidget) self.video_player_original.setEnabled(True) self.video_player_original.setGeometry(QtCore.QRect(10, 40, 500, 360)) self.video_player_original.setObjectName("video_player_original") self.video_player_result = VideoPlayer(self.centralwidget) self.video_player_result.setGeometry(QtCore.QRect(520, 40, 500, 360)) self.video_player_result.setObjectName("video_player_result") self.input_min_length = QtWidgets.QSpinBox(self.centralwidget) self.input_min_length.setGeometry(QtCore.QRect(210, 410, 171, 24)) self.input_min_length.setMaximum(10000) self.input_min_length.setProperty("value", 100) self.input_min_length.setObjectName("input_min_length") self.input_thresh = QtWidgets.QSpinBox(self.centralwidget) self.input_thresh.setGeometry(QtCore.QRect(20, 410, 171, 24)) self.input_thresh.setMinimum(-99) self.input_thresh.setProperty("value", -40) self.input_thresh.setObjectName("input_thresh") self.button_convert = QtWidgets.QPushButton(self.centralwidget) self.button_convert.setGeometry(QtCore.QRect(830, 400, 181, 32)) self.button_convert.setObjectName("button_convert") self.line = QtWidgets.QFrame(self.centralwidget) self.line.setGeometry(QtCore.QRect(510, -10, 20, 391)) self.line.setFrameShape(QtWidgets.QFrame.VLine) self.line.setFrameShadow(QtWidgets.QFrame.Sunken) self.line.setObjectName("line") self.label = QtWidgets.QLabel(self.centralwidget) self.label.setGeometry(QtCore.QRect(180, 10, 200, 20)) font = QtGui.QFont() font.setPointSize(16) self.label.setFont(font) self.label.setObjectName("label") self.label_2 = QtWidgets.QLabel(self.centralwidget) self.label_2.setGeometry(QtCore.QRect(710, 10, 200, 20)) font = QtGui.QFont() font.setPointSize(16) self.label_2.setFont(font) self.label_2.setObjectName("label_2") self.line_2 = QtWidgets.QFrame(self.centralwidget) self.line_2.setGeometry(QtCore.QRect(-3, 370, 1041, 20)) self.line_2.setFrameShape(QtWidgets.QFrame.HLine) self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken) self.line_2.setObjectName("line_2") self.label_3 = QtWidgets.QLabel(self.centralwidget) self.label_3.setGeometry(QtCore.QRect(30, 390, 181, 16)) self.label_3.setObjectName("label_3") self.label_4 = QtWidgets.QLabel(self.centralwidget) self.label_4.setGeometry(QtCore.QRect(220, 390, 161, 20)) self.label_4.setObjectName("label_4") MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 1030, 22)) self.menubar.setObjectName("menubar") self.menu = QtWidgets.QMenu(self.menubar) self.menu.setObjectName("menu") self.menu_2 = QtWidgets.QMenu(self.menubar) self.menu_2.setObjectName("menu_2") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.action_2 = QtWidgets.QAction(MainWindow) self.action_2.setObjectName("action_2") self.action_3 = QtWidgets.QAction(MainWindow) self.action_3.setObjectName("action_3") self.action_4 = QtWidgets.QAction(MainWindow) self.action_4.setObjectName("action_4") self.actionGithub = QtWidgets.QAction(MainWindow) self.actionGithub.setObjectName("actionGithub") self.menu.addAction(self.action_2) self.menu.addAction(self.action_3) self.menu_2.addAction(self.action_4) self.menu_2.addAction(self.actionGithub) self.menubar.addAction(self.menu.menuAction()) self.menubar.addAction(self.menu_2.menuAction()) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle( _translate("MainWindow", "MSE Automatic Pause Cutter")) self.input_min_length.setSuffix(_translate("MainWindow", " мс")) self.input_thresh.setSuffix(_translate("MainWindow", " Дб")) self.button_convert.setText(_translate("MainWindow", "Преобразовать")) self.label.setText(_translate("MainWindow", "Исходный файл")) self.label_2.setText(_translate("MainWindow", "Предпросмотр")) self.label_3.setText(_translate("MainWindow", "Минимальный порог")) self.label_4.setText(_translate("MainWindow", "Минимальная длина")) self.menu.setTitle(_translate("MainWindow", "Файл")) self.menu_2.setTitle(_translate("MainWindow", "Помощь")) self.action_2.setText(_translate("MainWindow", "Открыть")) self.action_3.setText(_translate("MainWindow", "Экспортировать")) self.action_4.setText(_translate("MainWindow", "Об авторах")) self.actionGithub.setText(_translate("MainWindow", "Github"))
class Env(): BITRATE_TRACE = 'bitrate_list' VIDEO_TRACE = 'video_list' HISTORY_SIZE = 7 BUFFER_NORM_FACTOR = 10.0 CHUNK_TIL_VIDEO_END_CAP = 60.0 M_IN_K = 1000.0 REBUF_PENALTY = 10 # 1 sec rebuffering -> 3 Mbps SMOOTH_PENALTY = 1 DEFAULT_QUALITY = 1 # default video quality without agent # video bitrate is used as a ultility reward for each bitrate level so this can be change however fit UTILITY_SCORE = [300,700,1200,1500,3000,4000,5000] VIDEO_BIT_RATE = [300,700,1200,1500,3000,4000,5000] # unit is bit birate_list = pickle.load(open(BITRATE_TRACE,'rb')) def __init__(self): super().__init__() assert len(self.UTILITY_SCORE) == len(self.VIDEO_BIT_RATE) # get video list vlc = video_list_collector() vlc.save_dir = self.VIDEO_TRACE vlc.load() self.video_list = vlc.get_trace_matrix(self.VIDEO_BIT_RATE) self.video_player = VideoPlayer(self.birate_list,self.video_list) self.buffer_thresh = self.video_player.buffer_thresh self.action_list = len(self.video_list) self.network_speed = np.zeros(self.HISTORY_SIZE) self.reset() def action_space(self): return self.action_list def reset(self, mode = 'train'): next_video_chunk_size = self.video_player.reset(mode = mode) self.last_action = self.DEFAULT_QUALITY self.network_speed = np.zeros(self.HISTORY_SIZE) self.state = np.append(self.network_speed, 0) #net speed , buffer self.state = np.append(self.state, 0) #chunk remain self.state = np.append(self.state, next_video_chunk_size / 1e6) #next options self.state = np.append(self.state, 0) #last action terminate = False reward = 0 return self.state def process_trace(self,data): data = copy.deepcopy(data) data.pop("next_seg") data.pop("segment") terminate = data["terminate"] data.pop("terminate", None) reshape = [v for v in data.values()] data = np.array(reshape) return data, terminate def cal_reward(self, action, rebuf): reward = self.UTILITY_SCORE[action] / self.M_IN_K \ - self.REBUF_PENALTY * rebuf \ - self.SMOOTH_PENALTY * np.abs(self.UTILITY_SCORE[action] - self.UTILITY_SCORE[self.last_action]) / self.M_IN_K return reward def get_sep_reward(self, action, rebuf): quality = self.UTILITY_SCORE[action] / self.M_IN_K rebuf_pen = self.REBUF_PENALTY * rebuf switch_pen = self.SMOOTH_PENALTY * np.abs(self.UTILITY_SCORE[action] - self.UTILITY_SCORE[self.last_action]) / self.M_IN_K return quality, rebuf_pen, switch_pen def step(self,action, sep = False): last_state = self.state delay, sleep_time, buffer_size, rebuf, \ video_chunk_size, next_video_chunk_sizes, \ end_of_video, video_chunk_remain = \ self.video_player.download(action) reward = self.cal_reward(action, rebuf) quality, rebuf_pen, switch_pen = self.get_sep_reward(action, rebuf) self.last_action = action net_speed = video_chunk_size / (delay - sleep_time) self.network_speed = np.roll(self.network_speed,axis = -1,shift = 1) self.network_speed[0] = net_speed / 1e6 self.state = np.append(self.network_speed, buffer_size * 0.1) self.state = np.append(self.state, video_chunk_remain * 0.1) self.state = np.append(self.state, next_video_chunk_sizes / 1e7) self.state = np.append(self.state, self.last_action * 0.1) return self.state,reward, end_of_video, [quality,rebuf_pen,switch_pen], delay
class VideoQueryGUI(ttk.Frame): FORCE_CREATE = False def __init__(self, master): super(VideoQueryGUI, self).__init__() self.master = master master.title("CSCI 576 Project") master.wm_protocol("WM_DELETE_WINDOW", self.onClose) self.folders = [x[0] for x in os.walk(config.DB_VID_ROOT)][1:] self.query_scores = None self.create_frames() self.load_db_thread = threading.Thread(target=self.load_database, name='database loader') self.load_db_thread.start() def load_database(self): self.update_status('>>> Loading DB videos', clear=True) print('Started') print('=' * 80) print('Database video list') print('-' * 80) print('\n'.join( ['%d. %s' % (i + 1, f) for (i, f) in enumerate(self.folders)])) print('=' * 80) self.db_vids = [] for selected_folder in self.folders: self.update_status('>>> DB video selected: ' + selected_folder) pkl_path = glob.glob(os.path.join(selected_folder, '*.pkl')) if len(pkl_path) and not self.FORCE_CREATE: tic = time.time() self.update_status('>>> Loading pre-calculated features') with open(pkl_path[0], 'rb') as pkl_fp: v = pickle.load(pkl_fp) self.update_status('>>> Done. Time taken: %0.4fs' % (time.time() - tic)) else: tic = time.time() self.update_status('>>> Loading video') vid_path = selected_folder aud_path = glob.glob(os.path.join(selected_folder, '*.wav'))[0] v = Video(vid_path, aud_path) self.update_status('>>> Done. Time taken: %0.4fs' % (time.time() - tic)) # Computing features tic = time.time() self.update_status('>>> Calculating video features') extract_features(v) self.update_status('>>> Calculated in %0.4fs' % (time.time() - tic)) self.update_status('>>> Saving results to database') with open(os.path.join(selected_folder, '%s.pkl' % v.name), 'wb') as pkl_fp: pickle.dump(v, pkl_fp) self.db_vids.append(v) self.update_status('>>> Saved results to database') def create_frames(self): # Top frame self.top_frame = tk.LabelFrame(self.master, text='', bg="#E9E9E9") self.top_frame.pack(side='top', expand=True, fill='both') self.load_query_button = ttk.Button(self.top_frame, text='Load Query', command=self.load_query_video) self.load_query_button.grid(row=0, column=0, padx=0, pady=0) self.find_matches_button = ttk.Button(self.top_frame, text='Find matches', command=self.run_match) self.find_matches_button.grid(row=1, column=0, padx=0, pady=0) self.match_list = tk.Listbox(self.top_frame, height=4, bd=0) self.yscroll = tk.Scrollbar(self.top_frame, orient=tk.VERTICAL) self.match_list['yscrollcommand'] = self.yscroll.set self.match_list.grid(row=0, column=1, rowspan=2, stick='wens') self.yscroll.grid(row=0, column=1, rowspan=2, sticky='nse') self.match_list.bind('<Double-Button-1>', self.poll_match_list) self.curr_selection = -1 self.top_frame.grid_columnconfigure(0, weight=1) self.top_frame.grid_columnconfigure(1, weight=2) # Middle frame self.middle_frame = tk.LabelFrame(self.master, text='') self.middle_frame.pack(side='top', expand=True, fill='both') self.status_label_text = tk.StringVar() self.status_label_text.set('LOGS') self.status_label = tk.Label(self.middle_frame, textvar=self.status_label_text, justify=tk.LEFT, anchor='w', wraplength=700, bg="black", fg="#C1E0FD") self.status_label.grid(row=0, column=0, stick='nswe', columnspan=2) self.middle_frame.grid_columnconfigure(0, weight=1) self.middle_frame.grid_columnconfigure(1, weight=1) self.query_player = VideoPlayer(self.middle_frame) self.query_player.grid(row=1, column=0, stick='nsw') self.db_player = VideoPlayer(self.middle_frame) self.db_player.grid(row=1, column=1, stick='nse') # Bottom frame self.bottom_frame = tk.LabelFrame(self.master, text='') self.bottom_frame.pack(side='top', expand=True, fill='both') self.match_info_label_text = tk.StringVar() # self.match_info_label_text.set('MATCH INFORMATION') self.match_info_label = tk.Label(self.bottom_frame, textvar=self.match_info_label_text, justify=tk.LEFT, anchor='e') self.match_info_label.grid(row=0, column=0, stick='nswe') image = cv2.imread( "/Users/nikhiljohny/Documents/_CSCI576Project/codebase/master/graph_place_holder.png" ) width = 365 height = 280 dim = (width, height) image = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = Image.fromarray(image) image = ImageTk.PhotoImage(image) self.panelA = tk.Label(self.bottom_frame, image=image, width=365, height=280) self.panelA.image = image self.panelA.grid(row=0, column=1, stick='nse', padx=0, pady=0) self.bottom_frame.grid_columnconfigure(0, weight=1) self.bottom_frame.grid_columnconfigure(1, weight=1) def load_query_video(self): selected_folder = None self.master.update() selected_folder = askdirectory(initialdir=config.QUERY_VID_ROOT, title='Select query folder') # selected_folder = askopenfilename( # initialdir=config.QUERY_VID_ROOT, title='Select query folder') self.update_status('>>> Selected: ' + selected_folder) if selected_folder == '': return self.query_loader = threading.Thread(target=self.load_query, args=(selected_folder, ), name='query_loader') self.query_loader.start() # while self.query_loader.is_alive(): # self.update_idletasks() def load_query(self, selected_folder=None): self.update_status('>>> Loading query video', clear=True) if selected_folder == None: selected_folder = os.path.join(config.QUERY_VID_ROOT, 'subclip_traffic') # selected_folder = askdirectory( # initialdir=config.QUERY_VID_ROOT, title='Select query folder') # print(selected_folder) self.update_status('>>> Query video selected: ' + selected_folder) # print('Selected '+selected_folder) pkl_path = glob.glob(os.path.join(selected_folder, 'query_scores.pkl')) # print(pkl_path) if len(pkl_path) and not self.FORCE_CREATE: vid_pkl_path = [ pth for pth in glob.glob(os.path.join(selected_folder, '*.pkl')) if not os.path.basename(pth).startswith('query_scores') ] tic = time.time() self.update_status('>>> Loading pre-calculated metrics') # print('Loading pre-calculated comparison metrics') with open(pkl_path[0], 'rb') as pkl_fp: self.query_scores = pickle.load(pkl_fp) with open(vid_pkl_path[0], 'rb') as pkl_fp: self.query_vid = pickle.load(pkl_fp) self.update_status('>>> Done. Time taken: %0.4fs' % (time.time() - tic)) else: pkl_path = [ pth for pth in glob.glob(os.path.join(selected_folder, '*.pkl')) if not os.path.basename(pth).startswith('query_scores') ] if len(pkl_path) and not self.FORCE_CREATE: tic = time.time() self.update_status('>>> Loading pre-calculated features') with open(pkl_path[0], 'rb') as pkl_fp: self.query_vid = pickle.load(pkl_fp) self.update_status('>>> Done. Time taken: %0.4fs' % (time.time() - tic)) else: # Loading query video tic = time.time() vid_path = selected_folder aud_path = glob.glob(os.path.join(selected_folder, '*.wav'))[0] self.update_status('>>> Loading query video %s' % os.path.basename(vid_path)) self.query_vid = Video(vid_path, aud_path) # Computing features tic = time.time() self.update_status('>>> Calculating video features') # print('Calculating video features') extract_features(self.query_vid) self.update_status('>>> Calculated in %0.4fs' % (time.time() - tic)) # print('Calculated in %0.4fs' % (time.time()-tic)) self.update_status('>>> Creating pickle file for query video') with open( os.path.join(selected_folder, '%s.pkl' % self.query_vid.name), 'wb') as pkl_fp: pickle.dump(self.query_vid, pkl_fp) self.query_scores = {} for i, db_vid in enumerate(self.db_vids): self.update_status('>>> Comparing features with %s' % db_vid.name) tic = time.time() self.query_scores[db_vid.name] = compare_features( self.query_vid, db_vid) self.update_status( '>>> Feature comparison completed in %0.4fs' % (time.time() - tic)) self.update_status('>>> Saving results to database') with open(os.path.join(selected_folder, 'query_scores.pkl'), 'wb') as pkl_fp: pickle.dump(self.query_scores, pkl_fp) self.update_status('>>> Saved results to database') self.query_player.load_video(self.query_vid) def run_match(self): if self.query_scores is None: self.update_status('>>> No query video selected', clear=True) return self.update_status('>>> Running query in database', clear=True) self.final_ranks = rank_features(self.query_scores) display_plot( self.final_ranks, "graph", "/Users/nikhiljohny/Documents/_CSCI576Project/codebase/master/graph" ) generate_plots( self.final_ranks, "temp", "/Users/nikhiljohny/Documents/_CSCI576Project/codebase/master/temp" ) start_fr = np.argmax(self.final_ranks[0][3]) query_vid_len = len(self.db_vids[0].frames) - len( self.final_ranks[0][3]) + 1 self.update_match_info('') self.update_match_info('Best Match Video: {}'.format( self.final_ranks[0][0])) self.update_match_info('Start Frame: {}'.format(start_fr)) self.update_match_info('End Frame: {}'.format(start_fr + query_vid_len)) start_time = round(start_fr / config.FRAME_RATE) self.update_match_info('Start Time: {}'.format(start_time)) end_time = round(float(start_fr + query_vid_len) / config.FRAME_RATE) self.update_match_info('End Time: {}'.format(end_time)) self.update_status('>>> Final scores computed') image = cv2.imread( "/Users/nikhiljohny/Documents/_CSCI576Project/codebase/master/graph/graph_final.png" ) width = 365 height = 280 dim = (width, height) image = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = Image.fromarray(image) image = ImageTk.PhotoImage(image) self.panelA.configure(image=image) self.panelA.image = image self.update_status('>>> Ranked list of matches generated') self.match_list.delete(0, tk.END) i = 0 matchlist = [x[0] for x in self.final_ranks] for match in matchlist: final_score = str(round(self.final_ranks[i][1], 4)) match = '{} | {}'.format(match, final_score) self.match_list.insert(tk.END, match) i = i + 1 self.poll_match_list() def poll_match_list(self, event=None): current = self.match_list.curselection()[0] # print(current) if current != self.curr_selection: self.update_status('>>> Video selected: ' + self.final_ranks[current][0]) curr_video = self.find_matching_db_vid( self.final_ranks[current][0]) self.db_player.load_video(curr_video) plot = generate_plots(self.final_ranks[current]) self.corr_plot = resize(plot, (100, 356, 3), preserve_range=True).astype('uint8') self.curr_selection = current self.master.after(250, self.poll_match_list) def find_matching_db_vid(self, vidname): for vid in self.db_vids: if vid.name == vidname: return vid else: return None def update_status(self, text, clear=False): if clear: status_text = '\t\t\t\t LOGS\n\n%s' % text else: status_text = '%s\n%s' % (self.status_label_text.get(), text) lines = status_text.split('\n') if len(lines) < 6: status_text = '\n'.join(lines + [''] * (6 - len(lines))) elif len(lines) > 6: status_text = '\n'.join([lines[0]] + lines[-5:]) self.status_label_text.set(status_text) def update_match_info(self, text, clear=False): if clear: match_info_text = 'MATCH INFORMATION:\n%s' % text else: match_info_text = '%s\n%s' % (self.match_info_label_text.get(), text) lines = match_info_text.split('\n') if len(lines) < 6: match_info_text = '\n'.join(lines + [''] * (6 - len(lines))) elif len(lines) > 6: match_info_text = '\n'.join([lines[0]] + lines[-5:]) self.match_info_label_text.set(match_info_text) def onClose(self): self.query_player.onClose() self.db_player.onClose() self.master.quit()
class Square(Scatter): app = ObjectProperty( None ) geometry_id = NumericProperty(None)#location on the field where the Square sits #content id = StringProperty('') title = StringProperty(None) app_type = StringProperty(None) #'info', 'service', 'jeu' color = ObjectProperty( (.82,.82,.82,1) ) color_text = ObjectProperty( (.82,.82,.82,1) ) color_down = ObjectProperty( (1,1,0,1) ) color_up = ObjectProperty( (.1,.1,.1,1) ) authors = StringProperty(None) main_media_type = StringProperty(None) #'image' or 'video' or 'webpage' image_path = StringProperty(None) video_path = StringProperty(None) webpage_path = StringProperty("http://www.google.com") vote_feedback = NumericProperty(0) #value between 0 and 1 #shape rotation_90d = NumericProperty(0) layout_type = StringProperty(None) #'icon'/'small'/'medium' or 'large' icon_size = ObjectProperty( None ) small_size = ObjectProperty( None ) medium_size = ObjectProperty( None ) large_size = ObjectProperty( None ) #internal variables touches = DictProperty( {} ) #current active touches on the widget #buttons = DictProperty( {} ) #store buttons widgets square_parameters = DictProperty( {} ) #initial parameters of the square texture_path = StringProperty("") layout = ObjectProperty( None )#base layout for all the widgets layers = DictProperty( {} )#stores background text layers of each size layer_texture_path = ObjectProperty( None ) process_touch_up_forbidden = BooleanProperty(False) padding = NumericProperty(10) #square layout padding berkelium_is_installed = BooleanProperty(False) def __init__(self,**kwargs) : super(Square,self).__init__(**kwargs) l,h = self.size pad = self.padding self.layout = BoxLayout(orientation = 'vertical', size = (l -2*pad,h -2*pad), pos = (pad,pad) ) self.init_layouts() def on_start(self, a): try : self.parent.mute(self.uid) #mute other parents' video players except: pass self.video.unmute(1) #unmute the player def on_unmute(self,a): try : self.parent.mute(self.uid) except : pass def mute(self): if self.main_media_type == 'video': self.video.mute(1) def on_fullscreen(self, a): self.video.stop(1) vid = self.video x,y = vid.pos self.parent.play_video_fullscreen(self.video_path, self.to_parent(x,y) , self.video.size, self.video.video.position) def on_leave_fullscreen(self, a): pass def process_font_size(self, text, font_size): #in case the text is multiline, reduce the font size multiline = False for i in text : if i == '\n' : multiline = True if not multiline : return font_size else : return font_size - 6 def init_layouts(self): def layers2texture(layers, berkelium): #convert either an image or an html webpage to texture #to be used as a background by the square converted_layers = {} bk = {} for key,path in layers.iteritems(): #fileName, fileExtension = os.path.splitext(path) #if fileName[4] in ['http','file']: #fileExtension in ['.org','.com','.fr','.html','.htm'] : if path[:4] in ['http','file']: if self.berkelium_is_installed == False : return None size = (600,600) bk[key] = berkelium.Webbrowser(url=path, size=size) texture = bk[key]._bk.texture converted_layers[key] = texture #finally delete the berkelium instance del bk[key] else : from kivy.uix.image import Image img = Image(source=path) texture = img.texture converted_layers[key] = texture #print path, texture return converted_layers #load berkelium berkelium = None if self.berkelium_is_installed == True : from kivy.ext import load berkelium = load('berkelium', (1, 1)) #extract textures from layouts self.layers = layers2texture(self.layers, berkelium) #get current layout layout_type = self.layout_type param = self.square_parameters[layout_type] #load parameters specific to that size (small, medium, large) #color a,b,c,d = self.color_up ######################### LAYOUT ########################################################## self.texture_path = texture_path = str(param['texture_path']) #self.style['square_texture_path'] #text layer self.layer_texture_path = self.layers[layout_type] """ from kivy.uix.image import Image self.layer = Image(source = "apps/layers/xyz/large.png", size_hint = (1,1)) self.layout.add_widget(self.layer) """ #top part : Title, app_type, authors self.box_top = BoxLayout(size_hint = param['box_top_size_hint'] )#orientation = 'horizontal', font_size = self.process_font_size( self.title, int( param['title_label_font_size']) ) text_size = (len(self.title)*font_size +100,None ) self.title_label = Label( text=self.title, font_size = font_size, color = self.color_text, halign = 'left', valign = 'top',text_size = text_size, padding = (5,0) ) #font_name = 'DEJAVU SANS CONDENSED', bold = False self.box2 = BoxLayout(orientation = 'horizontal', size_hint = (None,1) , width = self.title_label.text_size[0], pos_hint={'top': 1,'left':1} ) #self.app_type_pic = Image(source = str(self.app_type), pos_hint={'top': 1,'right':1}, size_hint = (1,3) ) #self.box3 = AnchorLayout( anchor_x = 'right', anchor_y = 'bottom') #self.authors_label = Label(text = self.authors, font_size = int( param['authors_label_font_size'] ), pos_hint ={'right':1}, color = self.color_text, halign = 'right') #, pos_hint={'bottom': 1,'right':1} ) self.box2.add_widget(self.title_label) self.box_top.add_widget(self.box2) #self.box3.add_widget(self.authors_label) #self.box_top.add_widget(self.box3) self.layout.add_widget( self.box_top ) #middle part : Image or Video self.box_middle = BoxLayout(orientation = 'horizontal', size_hint = param['box_middle_size_hint'] ) self.box_middle1 = BoxLayout(orientation = 'horizontal', size_hint = param['box_middle1_size_hint'], padding = 0, spacing = 0 ) self.box_middle2 = BoxLayout(orientation = 'horizontal', size_hint = param['box_middle2_size_hint'], padding = 0, spacing = 0 ) self.box_middle.add_widget( self.box_middle1 ) self.box_middle.add_widget( self.box_middle2 ) if self.main_media_type == 'webpage' : #berkelium installed was already checked by field try : self.webpage = berkelium.Webbrowser(url=self.webpage_path, size=(50,50) ) self.box_middle1.add_widget( self.webpage ) except : print 'Cannot load url: '+str(self.webpage_path) self.main_media_type = 'image' if self.main_media_type == 'image' : from kivy.uix.image import Image image = Image(source = self.image_path, allow_stretch = True, keep_ratio = False, size_hint = (1,1), pos_hint={'left': 1, 'top' : 1} ) self.box_middle1.add_widget( image ) elif self.main_media_type == 'video' : #if self.main_media_type == 'video' : self.video = VideoPlayer(source = self.video_path) self.video.bind(on_unmute =self.on_unmute) self.video.bind(on_start=self.on_start) self.video.bind(on_fullscreen = self.on_fullscreen) self.video.bind(on_leave_fullscreen = self.on_leave_fullscreen) self.box_middle1.add_widget( self.video ) self.layout.add_widget( self.box_middle ) #Bottom part : buttons self.box_bottom = BoxLayout(orientation = 'horizontal', size_hint = param['box_bottom_size_hint'] ) self.subbox = BoxLayout(orientation = 'horizontal' ) self.box_bottom.padding = int( param['box_bottom_padding'] ) #box.height*0.15 self.vote_button = SuperButton(background_normal = 'style/square/bouton-vote-T2-off.png', background_down = 'style/square/bouton-vote-T2-on.png', size_hint = (None,None), size=param["vote_button_size"] ) self.vote_button.bind( on_press = self.vote ) self.subbox.add_widget( self.vote_button ) #vote feedback from kivy.uix.image import Image self.fb = Image(source = 'style/square/like'+self.convert_vote_feedback()+'.png', size_hint=(None,None), size=param["vote_feedback_size"]) self.subbox.add_widget( self.fb ) self.box_bottom.add_widget(self.subbox) self.launch_button = SuperButton(background_normal = 'style/square/bouton-lancer-T2-off.png',background_down = 'style/square/bouton-lancer-T2-on.png', size_hint = (None,None), size=param["launch_button_size"] ) self.launch_button.bind( on_press = self.launch ) self.box_bottom.add_widget( self.launch_button ) self.box_bottom.spacing = (self.layout.width - self.vote_button.width - self.launch_button.width)*0.97 self.layout.add_widget( self.box_bottom ) self.add_widget(self.layout) #Clock.schedule_once(self.update_canvas, 4) def convert_vote_feedback(self): vf = self.vote_feedback if vf > 1 : vf =1 elif vf < 0 : vf = 0 vf = int(vf*6) return str(vf) def layout_type2size(self,layout_type) : #print layout_type pad = self.padding if layout_type == 'large': l,h = self.large_size s = (l -2*pad,h -2*pad) elif layout_type == 'medium': l,h = self.medium_size s = (l -2*pad,h -2*pad) elif layout_type == 'small': l,h = self.small_size s = (l -2*pad,h -2*pad) elif layout_type == 'icon': l,h = self.icon_size s = (l -2*pad,h -2*pad) return s def refresh_layout(self, layout_type) : size = self.layout_type2size(layout_type) pad = self.padding self.layout_type = layout_type kwargs = {'duration' : 1.1,'t':'in_quart'} anim = Animation(pos = (pad,pad), size = size, **kwargs) anim.start(self.layout) #refresh background texture Clock.schedule_once(self.refresh_background, 1.1) def refresh_background(self, a): self.texture_path = str( self.square_parameters[self.layout_type]['texture_path'] ) self.layer_texture_path = self.layers[self.layout_type] def launch(self,a): self.app.appview.launch_app(id, self.title) def vote(self,a): print 'vote for app ' + self.title self.vote_feedback += 0.05 self.fb.source = 'style/square/like'+ self.convert_vote_feedback() +'.png' def on_touch_down(self, touch): #analyse and store touches so that we know on_touch_up which #square was concerned by the touch_up if self.collide_point(touch.x,touch.y): self.touches[touch.id] = touch #enlarge a bit self.reshape_when_touch_down(touch, 0) super(Square, self).on_touch_down(touch) def on_touch_up(self, touch): super(Square, self).on_touch_up(touch) if not touch.id in self.touches : return del self.touches[touch.id] if self.collide_point(touch.x,touch.y): #print self.rotation if not self.process_touch_up_forbidden : self.parent.process_touch_up(self) #reduce size a bit self.reshape_when_touch_up(touch) return True def reshape_when_touch_down(self, touch, intensity): self.color = self.color_down self.pos = (self.x + intensity, self.y + intensity) #self.title_label.color = self.color_up self.texture_path = 'style/square/square_'+str(self.layout_type)+'_touch_down.png' #self.app_type_label.color = self.color_up #self.size = (self.width + 3, self.height + 3) #a = Animation(center = self.center, size = self.size) #a.start(self) def reshape_when_touch_up(self, touch): self.color = self.color_up #self.title_label.color = self.color_down #self.app_type_label.color = self.color_up self.texture_path = 'style/square/square_'+str(self.layout_type)+'.png' pass def update_canvas(self,a): self.canvas.ask_update()
def init_layouts(self): def layers2texture(layers, berkelium): #convert either an image or an html webpage to texture #to be used as a background by the square converted_layers = {} bk = {} for key,path in layers.iteritems(): #fileName, fileExtension = os.path.splitext(path) #if fileName[4] in ['http','file']: #fileExtension in ['.org','.com','.fr','.html','.htm'] : if path[:4] in ['http','file']: if self.berkelium_is_installed == False : return None size = (600,600) bk[key] = berkelium.Webbrowser(url=path, size=size) texture = bk[key]._bk.texture converted_layers[key] = texture #finally delete the berkelium instance del bk[key] else : from kivy.uix.image import Image img = Image(source=path) texture = img.texture converted_layers[key] = texture #print path, texture return converted_layers #load berkelium berkelium = None if self.berkelium_is_installed == True : from kivy.ext import load berkelium = load('berkelium', (1, 1)) #extract textures from layouts self.layers = layers2texture(self.layers, berkelium) #get current layout layout_type = self.layout_type param = self.square_parameters[layout_type] #load parameters specific to that size (small, medium, large) #color a,b,c,d = self.color_up ######################### LAYOUT ########################################################## self.texture_path = texture_path = str(param['texture_path']) #self.style['square_texture_path'] #text layer self.layer_texture_path = self.layers[layout_type] """ from kivy.uix.image import Image self.layer = Image(source = "apps/layers/xyz/large.png", size_hint = (1,1)) self.layout.add_widget(self.layer) """ #top part : Title, app_type, authors self.box_top = BoxLayout(size_hint = param['box_top_size_hint'] )#orientation = 'horizontal', font_size = self.process_font_size( self.title, int( param['title_label_font_size']) ) text_size = (len(self.title)*font_size +100,None ) self.title_label = Label( text=self.title, font_size = font_size, color = self.color_text, halign = 'left', valign = 'top',text_size = text_size, padding = (5,0) ) #font_name = 'DEJAVU SANS CONDENSED', bold = False self.box2 = BoxLayout(orientation = 'horizontal', size_hint = (None,1) , width = self.title_label.text_size[0], pos_hint={'top': 1,'left':1} ) #self.app_type_pic = Image(source = str(self.app_type), pos_hint={'top': 1,'right':1}, size_hint = (1,3) ) #self.box3 = AnchorLayout( anchor_x = 'right', anchor_y = 'bottom') #self.authors_label = Label(text = self.authors, font_size = int( param['authors_label_font_size'] ), pos_hint ={'right':1}, color = self.color_text, halign = 'right') #, pos_hint={'bottom': 1,'right':1} ) self.box2.add_widget(self.title_label) self.box_top.add_widget(self.box2) #self.box3.add_widget(self.authors_label) #self.box_top.add_widget(self.box3) self.layout.add_widget( self.box_top ) #middle part : Image or Video self.box_middle = BoxLayout(orientation = 'horizontal', size_hint = param['box_middle_size_hint'] ) self.box_middle1 = BoxLayout(orientation = 'horizontal', size_hint = param['box_middle1_size_hint'], padding = 0, spacing = 0 ) self.box_middle2 = BoxLayout(orientation = 'horizontal', size_hint = param['box_middle2_size_hint'], padding = 0, spacing = 0 ) self.box_middle.add_widget( self.box_middle1 ) self.box_middle.add_widget( self.box_middle2 ) if self.main_media_type == 'webpage' : #berkelium installed was already checked by field try : self.webpage = berkelium.Webbrowser(url=self.webpage_path, size=(50,50) ) self.box_middle1.add_widget( self.webpage ) except : print 'Cannot load url: '+str(self.webpage_path) self.main_media_type = 'image' if self.main_media_type == 'image' : from kivy.uix.image import Image image = Image(source = self.image_path, allow_stretch = True, keep_ratio = False, size_hint = (1,1), pos_hint={'left': 1, 'top' : 1} ) self.box_middle1.add_widget( image ) elif self.main_media_type == 'video' : #if self.main_media_type == 'video' : self.video = VideoPlayer(source = self.video_path) self.video.bind(on_unmute =self.on_unmute) self.video.bind(on_start=self.on_start) self.video.bind(on_fullscreen = self.on_fullscreen) self.video.bind(on_leave_fullscreen = self.on_leave_fullscreen) self.box_middle1.add_widget( self.video ) self.layout.add_widget( self.box_middle ) #Bottom part : buttons self.box_bottom = BoxLayout(orientation = 'horizontal', size_hint = param['box_bottom_size_hint'] ) self.subbox = BoxLayout(orientation = 'horizontal' ) self.box_bottom.padding = int( param['box_bottom_padding'] ) #box.height*0.15 self.vote_button = SuperButton(background_normal = 'style/square/bouton-vote-T2-off.png', background_down = 'style/square/bouton-vote-T2-on.png', size_hint = (None,None), size=param["vote_button_size"] ) self.vote_button.bind( on_press = self.vote ) self.subbox.add_widget( self.vote_button ) #vote feedback from kivy.uix.image import Image self.fb = Image(source = 'style/square/like'+self.convert_vote_feedback()+'.png', size_hint=(None,None), size=param["vote_feedback_size"]) self.subbox.add_widget( self.fb ) self.box_bottom.add_widget(self.subbox) self.launch_button = SuperButton(background_normal = 'style/square/bouton-lancer-T2-off.png',background_down = 'style/square/bouton-lancer-T2-on.png', size_hint = (None,None), size=param["launch_button_size"] ) self.launch_button.bind( on_press = self.launch ) self.box_bottom.add_widget( self.launch_button ) self.box_bottom.spacing = (self.layout.width - self.vote_button.width - self.launch_button.width)*0.97 self.layout.add_widget( self.box_bottom ) self.add_widget(self.layout)
class Gui(QWidget): def __init__(self: 'Gui'): super().__init__() self.title = 'CSCI 576 Final Project' self.left = 0 self.top = 0 self.width = 1000 self.height = 360 self.jpgFolder = None self.rgbFolder = None self.wavFile = None self.playJpgFolder = None self.playWavFile = None self.threadpool = QThreadPool() self.playing_video = False self.video_paused = False self.keyboard_emulator = Controller() self.initUI() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) # Evaluator Progress Bar self.evaluator_progress_bar = self.createProgressBarPercent() # Box Layout self.windowLayout = QVBoxLayout() # Options are to choose folders for video evaluation or play existing video self.online_mode_widget = self.createOnlineModeButtons() self.offline_mode_widget = self.createOfflineModeButtons() # Add buttons self.windowLayout.addWidget(self.online_mode_widget) self.windowLayout.addWidget(self.offline_mode_widget) # Set layout and show self.setLayout(self.windowLayout) self.show() def createProgressBarPercent(self: 'Gui') -> QProgressBar: progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(100) return progress_bar def createOnlineModeButtons(self: 'Gui') -> QGroupBox: onlineModeGroup = QGroupBox( "Choose your JPG, RGB, and WAV Files/Folders for video evaluation") onlineModeGroup.setFixedHeight(250) groupLayout = QVBoxLayout() pathLayout = QHBoxLayout() jpgBox = QVBoxLayout() self.jpgLabel = QLabel() jpgBox.addWidget( self.createButton('Choose JPG Folder', self.setJpgFolder)) jpgBox.addWidget(self.jpgLabel) pathLayout.addLayout(jpgBox) rgbBox = QVBoxLayout() self.rgbLabel = QLabel() rgbBox.addWidget( self.createButton('Choose RGB Folder', self.setRgbFolder)) rgbBox.addWidget(self.rgbLabel) pathLayout.addLayout(rgbBox) wavBox = QVBoxLayout() self.wavLabel = QLabel() wavBox.addWidget(self.createButton('Choose WAV File', self.setWavFile)) wavBox.addWidget(self.wavLabel) pathLayout.addLayout(wavBox) groupLayout.addLayout(pathLayout) evalLayout = QHBoxLayout() evalBox = QVBoxLayout() self.evaluatorProgressLabel = QLabel() evalBox.addWidget( self.createButton('Evaluate Video', self.evaulate_video)) evalBox.addWidget(self.evaluator_progress_bar) evalBox.addWidget(self.evaluatorProgressLabel) evalLayout.addLayout(evalBox) groupLayout.addLayout(evalLayout) playLayout = QHBoxLayout() playBox = QVBoxLayout() self.play_converted_video_button = self.createButton( 'Play', self.play_converted_video) playBox.addWidget(self.play_converted_video_button) playLayout.addLayout(playBox) groupLayout.addLayout(playLayout) onlineModeGroup.setLayout(groupLayout) return onlineModeGroup @pyqtSlot() def setJpgFolder(self: 'Gui'): self.jpgFolder = self.getFolderPathDialog('JPG Folder') + '/' self.jpgLabel.setText('/'.join(self.jpgFolder.split('/')[-5:])) @pyqtSlot() def setRgbFolder(self: 'Gui'): self.rgbFolder = self.getFolderPathDialog('RGB Folder') + '/' self.rgbLabel.setText('/'.join(self.rgbFolder.split('/')[-5:])) @pyqtSlot() def setWavFile(self: 'Gui'): self.wavFile = self.getFilePathDialog('WAV File', 'WAV Audio Files (*.wav)') self.wavLabel.setText('/'.join(self.wavFile.split('/')[-4:])) def createOfflineModeButtons(self: 'Gui') -> QGroupBox: groupBox = QGroupBox( "Or choose your JPG Folder and WAV File for Video Play") groupBox.setFixedHeight(100) layout = QHBoxLayout() jpgBox = QVBoxLayout() self.playJpgLabel = QLabel() jpgBox.addWidget( self.createButton('Choose JPG Folder', self.setPlayJpgFolder)) jpgBox.addWidget(self.playJpgLabel) layout.addLayout(jpgBox) wavBox = QVBoxLayout() self.playWavLabel = QLabel() wavBox.addWidget( self.createButton('Choose WAV File', self.setPlayWavFile)) wavBox.addWidget(self.playWavLabel) layout.addLayout(wavBox) playBox = QVBoxLayout() self.play_video_button = self.createButton('Play', self.play_video) playBox.addWidget(self.play_video_button) playBox.addWidget(QLabel()) layout.addLayout(playBox) groupBox.setLayout(layout) return groupBox @pyqtSlot() def play_video(self: 'Gui'): if not self.playing_video: self.playing_video = True self.video_player = VideoPlayer(self.playJpgFolder, self.playWavFile, 30) self.play_video_button.setText('Pause') self.video_player.play() self.play_video_button.setText('Play') self.playing_video = False else: self.keyboard_emulator.press('p') self.keyboard_emulator.release('p') self.video_paused = not self.video_paused if self.video_paused: self.play_video_button.setText('Play') else: self.play_video_button.setText('Pause') @pyqtSlot() def setPlayJpgFolder(self: 'Gui'): self.playJpgFolder = self.getFolderPathDialog('JPG Folder') + '/' self.playJpgLabel.setText('/'.join(self.playJpgFolder.split('/')[-4:])) @pyqtSlot() def setPlayWavFile(self: 'Gui'): self.playWavFile = self.getFilePathDialog('WAV File', 'WAV Audio Files (*.wav)') self.playWavLabel.setText('/'.join(self.playWavFile.split('/')[-3:])) def createButton(self: 'Gui', label: str, callback) -> QPushButton: button = QPushButton(label, self) button.clicked.connect(callback) return button def getFolderPathDialog(self: 'Gui', caption: str) -> str or None: options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog options |= QFileDialog.ShowDirsOnly dirname = QFileDialog.getExistingDirectory(self, caption, directory=os.getcwd(), options=options) return dirname def getFilePathDialog(self: 'Gui', caption: str, filter: str) -> str or None: options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getOpenFileName(self, caption, directory=os.getcwd(), filter=filter, options=options) return fileName @pyqtSlot() def evaulate_video(self: 'Gui'): worker = EvaluatorWorker(self.rgbFolder, self.wavFile) worker.signals.finished_with_results.connect(self.evaluation_complete) worker.signals.report_progress.connect(self.setProgress) self.threadpool.start(worker) def setProgress(self: 'Gui', information: Tuple[str, float]): label = information[0] percentComplete = information[1] progress = max(min(100, round(100 * percentComplete)), 0) print(label) print(progress) self.evaluatorProgressLabel.setText(label) # Trying this to prevent obscure error time.sleep(1) self.evaluator_progress_bar.setValue(progress) def evaluation_complete(self: 'Gui', information: Tuple[list, Wav]): frame_nums_to_write = information[0] audio = information[1] self.frame_nums_to_write = frame_nums_to_write self.audio = audio def play_converted_video(self: 'Gui'): self.converter.play() @pyqtSlot() def play_converted_video(self: 'Gui'): if not self.playing_video: self.playing_video = True converter = VideoConverter(self.frame_nums_to_write, self.jpgFolder, self.audio.data, 30, \ self.audio.rate, self.audio.sampwidth) self.play_converted_video_button.setText('Pause') converter.play() self.play_converted_video_button.setText('Play') self.playing_video = False else: self.keyboard_emulator.press('p') self.keyboard_emulator.release('p') self.video_paused = not self.video_paused if self.video_paused: self.play_converted_video_button.setText('Play') else: self.play_converted_video_button.setText('Pause')
class Core(object): WAIT_BEGIN = 0 WAIT_END = 1 def __init__(self): self.player = None self.last_save = False self.exercise = None self.config = config self.logger = logging.Logger("Core") self.logger.setLevel(defaultLoggingLevel) self.logger.addHandler(defaultLoggingHandler) #Call by the main, give an handler to the main gui def set_gui(self, gui): self.gui_controller = gui #Create a new exercice based on paths. load the new exercise and #begin to play def new_exercise(self, videoPath, exercisePath, translationPath, langId): self.exercise = Exercise() self.exercise.set_media_change_callback(self.media_change_call_back) self.exercise.new() self.exercise.set_language_id(langId) self._set_paths(videoPath, exercisePath, translationPath) # This initialize the exercise self._reload(True) self._activate_sequence() self.gui_controller.set_title("", True) #Configure the paths for the current exercice. Reload subtitles list. def _set_paths(self, videoPath, exercisePath, translationPath): self.exercise.set_video_path(videoPath) self.exercise.set_exercise_path(exercisePath) self.exercise.set_translation_path(translationPath) self.exercise.initialize() #Reload media player and begin to play (if the params is True) def _reload(self, load): if self.player != None: self.player.close() self.player = VideoPlayer() self.player.set_window_id(self.gui_controller.get_video_window_id()) self.player.activate_video_callback( self.gui_controller.activate_video_area) self.player.open(self.exercise.get_video_path()) self.player.set_callback(self._time_callback) self.paused = False self.gui_controller.activate_video_area(False) self.gui_controller.activate("loaded") self._update_word_list() self.timeUpdateThreadId = thread.start_new_thread( self.time_update_thread, ()) if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() else: self.pause() #play the media def play(self): self.gui_controller.set_playing(True) self.player.play() self.paused = False #pause the media def pause(self): self.gui_controller.set_playing(False) self.player.pause() self.paused = True #Modify media speed def set_speed(self, speed): self.gui_controller.set_speed(speed) self.player.set_speed(speed) #Callback call by video player to notify change of media position. #Stop the media at the end of uncompleted sequences def _time_callback(self): if self.state == Core.WAIT_BEGIN: self.player.set_next_callback_time( self.exercise.get_current_sequence().get_time_end() + self.exercise.get_play_margin_after()) self.state = Core.WAIT_END elif self.state == Core.WAIT_END: self.state = Core.WAIT_BEGIN if self.exercise.get_current_sequence().is_valid(): gtk.gdk.threads_enter() self.next_sequence(False) gtk.gdk.threads_leave() else: self.pause() #Repeat the currence sequence def repeat_sequence(self): if not self.exercise.is_current_sequence_repeat_limit_reach(): #Repeat limit not reach or no limit self.goto_sequence_begin() self.play() self.exercise.increment_current_sequence_repeat_count() #Change the active sequence def select_sequence(self, num, load=True): if self.exercise.get_current_sequence_id() == num: return self.exercise.goto_sequence(num) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() self.set_can_save(True) #Goto next sequence def next_sequence(self, load=True): if self.exercise.goto_next_sequence(): self.set_can_save(True) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() #Goto previous sequence def previous_sequence(self, load=True): if self.exercise.goto_previous_sequence(): self.set_can_save(True) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() #Goto next valid sequence def next_valid_sequence(self, load=True): if self.exercise.goto_next_valid_sequence(): self.set_can_save(True) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() #Goto previous valid sequence def previous_valid_sequence(self, load=True): if self.exercise.goto_previous_valid_sequence(): self.set_can_save(True) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() #Update interface with new sequence. Configure stop media callback def _activate_sequence(self): self.state = Core.WAIT_BEGIN self.set_speed(1) self.player.set_next_callback_time( self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before()) self.gui_controller.set_sequence_number( self.exercise.get_current_sequence_id(), self.exercise.get_sequence_count()) self.gui_controller.set_sequence(self.exercise.get_current_sequence()) self.__activate_translation() self.__activate_previous_sequence_text() self._update_stats() #_update displayed translation on new active sequence def __activate_translation(self): if not self.exercise.get_translation_list(): self.gui_controller.set_translation("") else: translation = "" currentBegin = self.exercise.get_current_sequence().get_time_begin( ) currentEnd = self.exercise.get_current_sequence().get_time_end() for sub in self.exercise.get_translation_list(): begin = sub.get_time_begin() end = sub.get_time_end() if (begin >= currentBegin and begin <= currentEnd) or ( end >= currentBegin and end <= currentEnd) or (begin <= currentBegin and end >= currentEnd): translation += sub.get_text() + " " self.gui_controller.set_translation(translation) #_update displayed previous sentence text def __activate_previous_sequence_text(self): previous_sequence_text = "" previous_sequence = self.exercise.get_previous_sequence() if previous_sequence: for i, symbol in enumerate(previous_sequence.get_symbols()): previous_sequence_text += symbol if i < len(previous_sequence.get_words()): word = previous_sequence.get_words()[i] if word.is_valid(): previous_sequence_text += word.get_valid(lower=False) else: word_text = word.get_text() if len(word_text): previous_sequence_text += word.get_text() else: previous_sequence_text += "_" self.gui_controller.set_previous_sequence_text(previous_sequence_text) #Update displayed stats on new active sequence def _update_stats(self): sequenceCount = self.exercise.get_sequence_count() sequenceFound = 0 wordCount = 0 wordFound = 0 for sequence in self.exercise.get_sequence_list(): wordCount = wordCount + sequence.get_word_count() if sequence.is_valid(): sequenceFound += 1 wordFound += sequence.get_word_count() else: wordFound += sequence.get_word_found() if wordFound == 0: repeatRate = float(0) else: repeatRate = float( self.exercise.get_repeat_count()) / float(wordFound) self.gui_controller.set_statitics(sequenceCount, sequenceFound, wordCount, wordFound, repeatRate) def _update(self): self.gui_controller.set_sequence(self.exercise.get_current_sequence()) self.__validate_sequence() #Verify if the sequence is complete def __validate_sequence(self): if self.exercise.get_current_sequence().is_valid(): if self.exercise.get_repeat_after_completed(): if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() else: self.next_sequence(load=False) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited if self.player.get_seek( ) > (self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before()): self.goto_sequence_begin() self.play() else: self.play() #Goto beginning of the current sequence. Can start to play as soon #as the media player is ready def goto_sequence_begin(self, asSoonAsReady=False): self.state = Core.WAIT_END begin_time = self.exercise.get_current_sequence().get_time_begin( ) - self.exercise.get_play_margin_before() if begin_time < 0: begin_time = 0 if asSoonAsReady: self.player.seek_as_soon_as_ready(begin_time) else: self.player.seek(begin_time) self.player.set_next_callback_time( self.exercise.get_current_sequence().get_time_end() + self.exercise.get_play_margin_after()) #Write a char in current sequence at cursor position def write_char(self, char): if self.exercise.is_character_match(char): self.exercise.get_current_sequence().write_char(char) self.exercise.get_current_sequence().update_cursor_position() self._update() self.set_can_save(True) else: self._update() #Goto next word in current sequence def next_word(self): self.exercise.get_current_sequence().next_word() self._update() #Goto previous word in current sequence def previous_word(self): self.exercise.get_current_sequence().previous_word() self._update() #Choose current word in current sequence def select_sequence_word(self, wordIndex, wordIndexPos): try: self.exercise.get_current_sequence().select_sequence_word( wordIndex, wordIndexPos) except NoCharPossible: self.exercise.get_current_sequence().select_sequence_word( wordIndex, -1) self._update() #Goto first word in current sequence def first_word(self): self.exercise.get_current_sequence().first_word() self._update() #Goto last word in current sequence def last_word(self): self.exercise.get_current_sequence().last_word() self._update() #Delete a char before the cursor in current sequence def delete_previous_char(self): self.exercise.get_current_sequence().delete_previous_char() self._update() self.set_can_save(True) #Delete a char after the cursor in current sequence def delete_next_char(self): self.exercise.get_current_sequence().delete_next_char() self._update() self.set_can_save(True) #Goto previous char in current sequence def previous_char(self): self.exercise.get_current_sequence().previous_char() #The sequence don't change but the cursor position is no more up to date self._update() #Goto next char in current sequence def next_char(self): self.exercise.get_current_sequence().next_char() #The sequence don't change but the cursor position is no more up to date self._update() #Reveal correction for word at cursor in current sequence def complete_word(self): self.exercise.get_current_sequence().show_hint() self._update() self.set_can_save(True) #Reveal correction for word at cursor in current sequence def reveal_word(self): self.exercise.get_current_sequence().complete_word() self.exercise.get_current_sequence().next_word() self._update() self.set_can_save(True) #Reveal correction for word at cursor in current sequence def reveal_sequence(self): self.exercise.get_current_sequence().complete_all() self._update() self.set_can_save(True) #reset whole exercise def reset_exercise_content(self): self.exercise.reset() self.exercise.goto_sequence(0) #FIXME self._update() self.set_can_save(True) self.logger.debug("need to stop the current sequence") #FIXME #pause or play media def toggle_pause(self): if self.player.is_paused() and self.paused: self.play() elif not self.player.is_paused() and not self.paused: self.pause() #Change position in media and play it def seek_sequence(self, time): begin_time = self.exercise.get_current_sequence().get_time_begin( ) - self.exercise.get_play_margin_before() if begin_time < 0: begin_time = 0 pos = begin_time + time self.player.seek(pos) self.player.set_next_callback_time( self.exercise.get_current_sequence().get_time_end() + self.exercise.get_play_margin_after()) self.state = Core.WAIT_END if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() #Thread to update slider position in gui def time_update_thread(self): timeUpdateThreadId = self.timeUpdateThreadId while timeUpdateThreadId == self.timeUpdateThreadId: time.sleep(0.5) pos_int = self.player.get_current_time() if pos_int != None: end_time = self.exercise.get_current_sequence().get_time_end() begin_time = self.exercise.get_current_sequence( ).get_time_begin() - self.exercise.get_play_margin_before() if begin_time < 0: begin_time = 0 duration = end_time - begin_time pos = pos_int - begin_time self.gui_controller.set_sequence_time(pos, duration) #Save current exercice def save(self, saveAs=False): if not self.exercise: self.logger.error("Save called but no exercise load") return if saveAs or self.exercise.get_output_save_path() == None: outputSavePath = self.gui_controller.ask_save_path() if not outputSavePath: return self.exercise.set_output_save_path(outputSavePath + ".perroquet") save_exercise(self.exercise, self.exercise.get_output_save_path()) self.config.set("lastopenfile", self.exercise.get_output_save_path()) #lastopenfileS l = self.config.get("lastopenfiles") path = self.exercise.get_output_save_path() name = self.exercise.get_name() or path self.config.set("lastopenfiles", [[path, name]] + [p for p in l if p[0] != path][:10]) self.set_can_save(False) #load the exercice at path def load_exercise(self, path): self.gui_controller.activate("closed") if self.exercise: self.save() try: self.exercise = load_exercise(path) self.exercise.set_media_change_callback( self.media_change_call_back) except IOError: self.logger.exception("No file at " + path) return if not self.exercise: return validPaths, errorList = self.exercise.is_paths_valid() if not validPaths: for error in errorList: self.gui_controller.signal_exercise_bad_path(error) self.set_can_save(False) self.gui_controller.activate("load_failed") self.gui_controller.ask_properties() return self._reload(False) if self.exercise.get_output_save_path() == None: self.set_can_save(True) else: self.set_can_save(False) self._activate_sequence() self.goto_sequence_begin(True) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() #Change paths of current exercice and reload subtitles and video def _update_paths(self, videoPath, exercisePath, translationPath): self.exercise.set_video_path(videoPath) self.exercise.set_exercise_path(exercisePath) self.exercise.set_translation_path(translationPath) validPaths, errorList = self.exercise.is_paths_valid() if not validPaths: for error in errorList: self.gui_controller.signal_exercise_bad_path(error) self.gui_controller.activate("load_failed") self.set_can_save(False) return self._set_paths(videoPath, exercisePath, translationPath) self._reload(True) self.set_can_save(True) self._activate_sequence() self.goto_sequence_begin(True) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() def update_properties(self): self.exercise.initialize() self._reload(True) self.set_can_save(True) self._activate_sequence() self.goto_sequence_begin(True) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() #get paths of current exercise def get_paths(self): return (self.exercise.get_video_path(), self.exercise.get_exercise_path(), self.exercise.get_translation_path()) #Udpates vocabulary list in interface def _update_word_list(self): self.gui_controller.set_word_list(self.exercise.extract_word_list()) #Notify the user use the repeat command (for stats) def user_repeat(self): self.exercise.increment_repeat_count() self.set_can_save(True) #Signal to the gui that the exercise has unsaved changes def set_can_save(self, save): self.gui_controller.set_can_save(save) if self.exercise == None: title = "" elif self.exercise.get_name() != None: title = self.exercise.get_name() elif self.exercise.get_output_save_path() != None: title = self.exercise.get_output_save_path() else: title = _("Untitled exercise") self.last_save = save self.gui_controller.set_title(title, save) def get_can_save(self): return self.last_save def get_exercise(self): return self.exercise def get_player(self): return self.player def media_change_call_back(self): self.logger.info("new media : " + self.exercise.get_video_path()) """self.Pause() self.player.open(self.exercise.get_video_path()) """ self._reload(True) self._activate_sequence() self.goto_sequence_begin(True) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() def export_as_template(self): self.gui_controller.ask_properties_advanced() path = self.gui_controller.ask_export_as_template_path() if path: self.exercise.set_template(True) save_exercise(self.exercise, path) self.exercise.set_template(False) def export_as_package(self): self.gui_controller.ask_properties_advanced() path = self.gui_controller.ask_export_as_package_path() if path: repoManager = ExerciseRepositoryManager() repoManager.export_as_package(self.exercise, path) self.logger.info("Export done") else: self.logger.warn("No valid path to export??") def import_package(self): import_path = self.gui_controller.ask_import_package() if import_path is not None: repo_manager = ExerciseRepositoryManager() error = repo_manager.import_package(import_path) if error is None: self.gui_controller.display_message( _("Import finish succesfully. Use the exercises manager to use the newly installed exercise." )) else: self.gui_controller.display_message( _("Import failed." + " " + error))
class Core(object): WAIT_BEGIN = 0 WAIT_END = 1 def __init__(self): self.player = None self.last_save = False self.exercise = None self.config = config self.logger = logging.Logger("Core") self.logger.setLevel(defaultLoggingLevel) self.logger.addHandler(defaultLoggingHandler) #Call by the main, give an handler to the main gui def set_gui(self, gui): self.gui_controller = gui #Create a new exercice based on paths. load the new exercise and #begin to play def new_exercise(self, videoPath, exercisePath, translationPath, langId): self.exercise = Exercise() self.exercise.set_media_change_callback(self.media_change_call_back) self.exercise.new() self.exercise.set_language_id(langId) self._set_paths(videoPath, exercisePath, translationPath) # This initialize the exercise self._reload(True); self._activate_sequence() self.gui_controller.set_title("", True) #Configure the paths for the current exercice. Reload subtitles list. def _set_paths(self, videoPath, exercisePath, translationPath): self.exercise.set_video_path(videoPath) self.exercise.set_exercise_path(exercisePath) self.exercise.set_translation_path(translationPath) self.exercise.initialize() #Reload media player and begin to play (if the params is True) def _reload(self, load): if self.player != None: self.player.close() self.player = VideoPlayer() self.player.set_window_id(self.gui_controller.get_video_window_id()) self.player.activate_video_callback(self.gui_controller.activate_video_area) self.player.open(self.exercise.get_video_path()) self.player.set_callback(self._time_callback) self.paused = False self.gui_controller.activate_video_area(False) self.gui_controller.activate("loaded") self._update_word_list() self.timeUpdateThreadId = thread.start_new_thread(self.time_update_thread, ()) if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() else: self.pause() #play the media def play(self): self.gui_controller.set_playing(True) self.player.play() self.paused = False #pause the media def pause(self): self.gui_controller.set_playing(False) self.player.pause() self.paused = True #Modify media speed def set_speed(self, speed): self.gui_controller.set_speed(speed) self.player.set_speed(speed) #Callback call by video player to notify change of media position. #Stop the media at the end of uncompleted sequences def _time_callback(self): if self.state == Core.WAIT_BEGIN: self.player.set_next_callback_time(self.exercise.get_current_sequence().get_time_end() + self.exercise.get_play_margin_after()) self.state = Core.WAIT_END elif self.state == Core.WAIT_END: self.state = Core.WAIT_BEGIN if self.exercise.get_current_sequence().is_valid(): gtk.gdk.threads_enter() self.next_sequence(False) gtk.gdk.threads_leave() else: self.pause() #Repeat the currence sequence def repeat_sequence(self): if not self.exercise.is_current_sequence_repeat_limit_reach(): #Repeat limit not reach or no limit self.goto_sequence_begin() self.play() self.exercise.increment_current_sequence_repeat_count() #Change the active sequence def select_sequence(self, num, load=True): if self.exercise.get_current_sequence_id() == num: return self.exercise.goto_sequence(num) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() self.set_can_save(True) #Goto next sequence def next_sequence(self, load=True): if self.exercise.goto_next_sequence(): self.set_can_save(True) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() #Goto previous sequence def previous_sequence(self, load=True): if self.exercise.goto_previous_sequence(): self.set_can_save(True) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() #Goto next valid sequence def next_valid_sequence(self, load=True): if self.exercise.goto_next_valid_sequence(): self.set_can_save(True) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() #Goto previous valid sequence def previous_valid_sequence(self, load=True): if self.exercise.goto_previous_valid_sequence(): self.set_can_save(True) self._activate_sequence() if load and self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() #Update interface with new sequence. Configure stop media callback def _activate_sequence(self): self.state = Core.WAIT_BEGIN self.set_speed(1) self.player.set_next_callback_time(self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before()) self.gui_controller.set_sequence_number(self.exercise.get_current_sequence_id(), self.exercise.get_sequence_count()) self.gui_controller.set_sequence(self.exercise.get_current_sequence()) self.__activate_translation() self.__activate_previous_sequence_text() self._update_stats() #_update displayed translation on new active sequence def __activate_translation(self): if not self.exercise.get_translation_list(): self.gui_controller.set_translation("") else: translation = "" currentBegin = self.exercise.get_current_sequence().get_time_begin() currentEnd = self.exercise.get_current_sequence().get_time_end() for sub in self.exercise.get_translation_list(): begin = sub.get_time_begin() end = sub.get_time_end() if (begin >= currentBegin and begin <= currentEnd) or (end >= currentBegin and end <= currentEnd) or (begin <= currentBegin and end >= currentEnd): translation += sub.get_text() + " " self.gui_controller.set_translation(translation) #_update displayed previous sentence text def __activate_previous_sequence_text(self): previous_sequence_text = ""; previous_sequence = self.exercise.get_previous_sequence() if previous_sequence: for i, symbol in enumerate(previous_sequence.get_symbols()): previous_sequence_text += symbol if i < len(previous_sequence.get_words()): word = previous_sequence.get_words()[i] if word.is_valid(): previous_sequence_text += word.get_valid(lower=False) else: word_text = word.get_text() if len(word_text): previous_sequence_text += word.get_text() else: previous_sequence_text += "_" self.gui_controller.set_previous_sequence_text(previous_sequence_text) #Update displayed stats on new active sequence def _update_stats(self): sequenceCount = self.exercise.get_sequence_count() sequenceFound = 0 wordCount = 0 wordFound = 0 for sequence in self.exercise.get_sequence_list(): wordCount = wordCount + sequence.get_word_count() if sequence.is_valid(): sequenceFound += 1 wordFound += sequence.get_word_count() else: wordFound += sequence.get_word_found() if wordFound == 0: repeatRate = float(0) else: repeatRate = float(self.exercise.get_repeat_count()) / float(wordFound) self.gui_controller.set_statitics(sequenceCount, sequenceFound, wordCount, wordFound, repeatRate) def _update(self): self.gui_controller.set_sequence(self.exercise.get_current_sequence()) self.__validate_sequence() #Verify if the sequence is complete def __validate_sequence(self): if self.exercise.get_current_sequence().is_valid(): if self.exercise.get_repeat_after_completed(): if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.repeat_sequence() else: self.next_sequence(load=False) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited if self.player.get_seek() > (self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before()): self.goto_sequence_begin() self.play() else: self.play() #Goto beginning of the current sequence. Can start to play as soon #as the media player is ready def goto_sequence_begin(self, asSoonAsReady=False): self.state = Core.WAIT_END begin_time = self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before() if begin_time < 0: begin_time = 0 if asSoonAsReady: self.player.seek_as_soon_as_ready(begin_time) else: self.player.seek(begin_time) self.player.set_next_callback_time(self.exercise.get_current_sequence().get_time_end() + self.exercise.get_play_margin_after()) #Write a char in current sequence at cursor position def write_char(self, char): if self.exercise.is_character_match(char): self.exercise.get_current_sequence().write_char(char) self.exercise.get_current_sequence().update_cursor_position() self._update() self.set_can_save(True) else: self._update() #Goto next word in current sequence def next_word(self): self.exercise.get_current_sequence().next_word() self._update() #Goto previous word in current sequence def previous_word(self): self.exercise.get_current_sequence().previous_word() self._update() #Choose current word in current sequence def select_sequence_word(self, wordIndex, wordIndexPos): try: self.exercise.get_current_sequence().select_sequence_word(wordIndex, wordIndexPos) except NoCharPossible: self.exercise.get_current_sequence().select_sequence_word(wordIndex, -1) self._update() #Goto first word in current sequence def first_word(self): self.exercise.get_current_sequence().first_word() self._update() #Goto last word in current sequence def last_word(self): self.exercise.get_current_sequence().last_word() self._update() #Delete a char before the cursor in current sequence def delete_previous_char(self): self.exercise.get_current_sequence().delete_previous_char() self._update() self.set_can_save(True) #Delete a char after the cursor in current sequence def delete_next_char(self): self.exercise.get_current_sequence().delete_next_char() self._update() self.set_can_save(True) #Goto previous char in current sequence def previous_char(self): self.exercise.get_current_sequence().previous_char() #The sequence don't change but the cursor position is no more up to date self._update() #Goto next char in current sequence def next_char(self): self.exercise.get_current_sequence().next_char() #The sequence don't change but the cursor position is no more up to date self._update() #Reveal correction for word at cursor in current sequence def complete_word(self): self.exercise.get_current_sequence().show_hint() self._update() self.set_can_save(True) #Reveal correction for word at cursor in current sequence def reveal_word(self): self.exercise.get_current_sequence().complete_word() self.exercise.get_current_sequence().next_word() self._update() self.set_can_save(True) #Reveal correction for word at cursor in current sequence def reveal_sequence(self): self.exercise.get_current_sequence().complete_all() self._update() self.set_can_save(True) #reset whole exercise def reset_exercise_content(self): self.exercise.reset() self.exercise.goto_sequence(0) #FIXME self._update() self.set_can_save(True) self.logger.debug("need to stop the current sequence") #FIXME #pause or play media def toggle_pause(self): if self.player.is_paused() and self.paused: self.play() elif not self.player.is_paused() and not self.paused: self.pause() #Change position in media and play it def seek_sequence(self, time): begin_time = self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before() if begin_time < 0: begin_time = 0 pos = begin_time + time self.player.seek(pos) self.player.set_next_callback_time(self.exercise.get_current_sequence().get_time_end() + self.exercise.get_play_margin_after()) self.state = Core.WAIT_END if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() #Thread to update slider position in gui def time_update_thread(self): timeUpdateThreadId = self.timeUpdateThreadId while timeUpdateThreadId == self.timeUpdateThreadId: time.sleep(0.5) pos_int = self.player.get_current_time() if pos_int != None: end_time = self.exercise.get_current_sequence().get_time_end() begin_time = self.exercise.get_current_sequence().get_time_begin() - self.exercise.get_play_margin_before() if begin_time < 0: begin_time = 0 duration = end_time - begin_time pos = pos_int - begin_time self.gui_controller.set_sequence_time(pos, duration) #Save current exercice def save(self, saveAs=False): if not self.exercise: self.logger.error("Save called but no exercise load") return if saveAs or self.exercise.get_output_save_path() == None: outputSavePath = self.gui_controller.ask_save_path() if not outputSavePath: return self.exercise.set_output_save_path(outputSavePath + ".perroquet") save_exercise(self.exercise, self.exercise.get_output_save_path()) self.config.set("lastopenfile", self.exercise.get_output_save_path()) #lastopenfileS l = self.config.get("lastopenfiles") path = self.exercise.get_output_save_path() name = self.exercise.get_name() or path self.config.set("lastopenfiles", [[path, name]] + [p for p in l if p[0] != path][:10]) self.set_can_save(False) #load the exercice at path def load_exercise(self, path): self.gui_controller.activate("closed") if self.exercise: self.save() try: self.exercise = load_exercise(path) self.exercise.set_media_change_callback(self.media_change_call_back) except IOError: self.logger.exception("No file at " + path) return if not self.exercise: return validPaths, errorList = self.exercise.is_paths_valid() if not validPaths: for error in errorList: self.gui_controller.signal_exercise_bad_path(error) self.set_can_save(False) self.gui_controller.activate("load_failed") self.gui_controller.ask_properties() return self._reload(False) if self.exercise.get_output_save_path() == None: self.set_can_save(True) else: self.set_can_save(False) self._activate_sequence() self.goto_sequence_begin(True) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() #Change paths of current exercice and reload subtitles and video def _update_paths(self, videoPath, exercisePath, translationPath): self.exercise.set_video_path(videoPath) self.exercise.set_exercise_path(exercisePath) self.exercise.set_translation_path(translationPath) validPaths, errorList = self.exercise.is_paths_valid() if not validPaths: for error in errorList: self.gui_controller.signal_exercise_bad_path(error) self.gui_controller.activate("load_failed") self.set_can_save(False) return self._set_paths(videoPath, exercisePath, translationPath) self._reload(True) self.set_can_save(True) self._activate_sequence() self.goto_sequence_begin(True) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() def update_properties(self): self.exercise.initialize() self._reload(True) self.set_can_save(True) self._activate_sequence() self.goto_sequence_begin(True) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() #get paths of current exercise def get_paths(self): return (self.exercise.get_video_path(), self.exercise.get_exercise_path(), self.exercise.get_translation_path()) #Udpates vocabulary list in interface def _update_word_list(self): self.gui_controller.set_word_list(self.exercise.extract_word_list()) #Notify the user use the repeat command (for stats) def user_repeat(self): self.exercise.increment_repeat_count() self.set_can_save(True) #Signal to the gui that the exercise has unsaved changes def set_can_save(self, save): self.gui_controller.set_can_save(save) if self.exercise == None: title = "" elif self.exercise.get_name() != None: title = self.exercise.get_name() elif self.exercise.get_output_save_path() != None: title = self.exercise.get_output_save_path() else: title = _("Untitled exercise") self.last_save = save self.gui_controller.set_title(title, save) def get_can_save(self): return self.last_save def get_exercise(self): return self.exercise def get_player(self): return self.player def media_change_call_back(self): self.logger.info("new media : " + self.exercise.get_video_path()) """self.Pause() self.player.open(self.exercise.get_video_path()) """ self._reload(True) self._activate_sequence() self.goto_sequence_begin(True) if self.exercise.get_repeat_count_limit_by_sequence() == 0: #Auto start play only if repeat is not limited self.play() def export_as_template(self): self.gui_controller.ask_properties_advanced() path = self.gui_controller.ask_export_as_template_path() if path: self.exercise.set_template(True) save_exercise(self.exercise, path) self.exercise.set_template(False) def export_as_package(self): self.gui_controller.ask_properties_advanced() path = self.gui_controller.ask_export_as_package_path() if path: repoManager = ExerciseRepositoryManager() repoManager.export_as_package(self.exercise, path) self.logger.info("Export done") else: self.logger.warn("No valid path to export??") def import_package(self): import_path = self.gui_controller.ask_import_package() if import_path is not None: repo_manager = ExerciseRepositoryManager() error = repo_manager.import_package(import_path) if error is None: self.gui_controller.display_message(_("Import finish succesfully. Use the exercises manager to use the newly installed exercise.")) else: self.gui_controller.display_message(_("Import failed." + " " + error))
def create_frames(self): # Top frame self.top_frame = tk.LabelFrame(self.master, text='', bg="#E9E9E9") self.top_frame.pack(side='top', expand=True, fill='both') self.load_query_button = ttk.Button(self.top_frame, text='Load Query', command=self.load_query_video) self.load_query_button.grid(row=0, column=0, padx=0, pady=0) self.find_matches_button = ttk.Button(self.top_frame, text='Find matches', command=self.run_match) self.find_matches_button.grid(row=1, column=0, padx=0, pady=0) self.match_list = tk.Listbox(self.top_frame, height=4, bd=0) self.yscroll = tk.Scrollbar(self.top_frame, orient=tk.VERTICAL) self.match_list['yscrollcommand'] = self.yscroll.set self.match_list.grid(row=0, column=1, rowspan=2, stick='wens') self.yscroll.grid(row=0, column=1, rowspan=2, sticky='nse') self.match_list.bind('<Double-Button-1>', self.poll_match_list) self.curr_selection = -1 self.top_frame.grid_columnconfigure(0, weight=1) self.top_frame.grid_columnconfigure(1, weight=2) # Middle frame self.middle_frame = tk.LabelFrame(self.master, text='') self.middle_frame.pack(side='top', expand=True, fill='both') self.status_label_text = tk.StringVar() self.status_label_text.set('LOGS') self.status_label = tk.Label(self.middle_frame, textvar=self.status_label_text, justify=tk.LEFT, anchor='w', wraplength=700, bg="black", fg="#C1E0FD") self.status_label.grid(row=0, column=0, stick='nswe', columnspan=2) self.middle_frame.grid_columnconfigure(0, weight=1) self.middle_frame.grid_columnconfigure(1, weight=1) self.query_player = VideoPlayer(self.middle_frame) self.query_player.grid(row=1, column=0, stick='nsw') self.db_player = VideoPlayer(self.middle_frame) self.db_player.grid(row=1, column=1, stick='nse') # Bottom frame self.bottom_frame = tk.LabelFrame(self.master, text='') self.bottom_frame.pack(side='top', expand=True, fill='both') self.match_info_label_text = tk.StringVar() # self.match_info_label_text.set('MATCH INFORMATION') self.match_info_label = tk.Label(self.bottom_frame, textvar=self.match_info_label_text, justify=tk.LEFT, anchor='e') self.match_info_label.grid(row=0, column=0, stick='nswe') image = cv2.imread( "/Users/nikhiljohny/Documents/_CSCI576Project/codebase/master/graph_place_holder.png" ) width = 365 height = 280 dim = (width, height) image = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image = Image.fromarray(image) image = ImageTk.PhotoImage(image) self.panelA = tk.Label(self.bottom_frame, image=image, width=365, height=280) self.panelA.image = image self.panelA.grid(row=0, column=1, stick='nse', padx=0, pady=0) self.bottom_frame.grid_columnconfigure(0, weight=1) self.bottom_frame.grid_columnconfigure(1, weight=1)