diff --git a/usr/openmv-ide.glade b/usr/openmv-ide.glade deleted file mode 100644 index dd6c04c94..000000000 --- a/usr/openmv-ide.glade +++ /dev/null @@ -1,1567 +0,0 @@ - - - - - - False - 5 - True - center-on-parent - True - dialog - OpenMV IDE - v1.1 - Copyright (c) 2014 Ibrahim Abdalkader <i.abdalkader@gmail.com> - Machine vision with Python! - https://openmv.io/ - https://openmv.io/ - The MIT License (MIT) - -Copyright (c) 2014 Ibrahim Abdalkader <i.abdalkader@gmail.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE - Ibrahim Abdalkader -Kwabena W. Agyeman - logo.png - True - - - True - False - 2 - - - True - False - end - - - True - True - 0 - - - - - - - - - - - - - - - - 921600 - - - 12000000 - - - - - -2 - 2 - 1 - 1 - - - - -2 - 2 - 1 - 1 - - - - True - False - - - True - False - Save Template - True - - - - - - True - False - Save Descriptor - True - - - - - - True - False - Show Color Statistics - True - - - - - - False - 5 - Update Firmware - True - center-on-parent - 430 - 162 - True - dialog - - - True - False - 1 - - - True - False - end - - - gtk-ok - True - True - True - True - - - False - False - 0 - - - - - gtk-cancel - True - True - True - True - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - True - ' - - - True - False - 1 - - - - - True - False - - - True - True - - True - False - False - True - True - - - True - True - 0 - - - - - ... - True - True - True - - - False - False - 1 - - - - - False - True - 2 - - - - - True - False - - - Erase Filesystem - True - True - False - True - True - - - True - True - 0 - - - - - True - True - 3 - - - - - - fw_ok_button - fw_cancel_button - - - - 6 - 1 - - - - True - False - gtk-sort-ascending - - - True - False - 0.49000000953674316 - gtk-dialog-question - - - False - 5 - center-on-parent - True - dialog - - - True - False - 2 - - - True - False - end - - - gtk-ok - True - True - True - True - - - False - False - 0 - - - - - - - - True - True - 0 - - - - - True - False - pinout.png - - - True - True - 1 - - - - - - button5 - - - - - - - - - - OpenMV1 - - - OpenMV2 - - - - - - - - - - - -2 - 2 - 1 - 1 - - - - False - GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_STRUCTURE_MASK - OpenMV IDE - 1024 - 600 - - - - True - False - - - True - False - - - True - False - _File - True - - - True - False - - - gtk-new - True - False - True - True - - - - - - gtk-open - True - False - True - True - - - - - - gtk-save - True - False - True - True - - - - - - gtk-save-as - True - False - True - True - - - - - - True - False - - - - - True - False - Examples - True - - - - - True - False - Recent Files - True - - - - - True - False - - - - - gtk-quit - True - False - True - True - - - - - - - - - - True - False - _Tools - True - - - True - False - - - True - False - Bootloader - True - - - - - - - - - - True - False - _Help - True - - - True - False - - - Pinout - True - False - image2 - False - - - - - - True - False - - - - - gtk-about - True - False - True - True - - - - - - - - - - False - True - 0 - - - - - True - False - - - True - False - Connect - True - gtk-connect - - - - False - True - - - - - True - False - Reset - True - gtk-quit - - - - False - True - - - - - True - False - - - False - True - - - - - True - False - Execute Script - True - gtk-execute - - - - False - True - - - - - True - False - Stop Script - True - gtk-stop - - - - False - True - - - - - True - False - - - False - True - - - - - True - False - False - Save Script - True - gtk-save - - - - False - True - - - - - True - False - - - False - True - - - - - True - False - Zoom Out - True - gtk-zoom-out - - - - False - True - - - - - True - False - Best Fit - True - gtk-zoom-fit - - - - False - True - - - - - True - False - Zoom In - True - gtk-zoom-in - - - - False - True - - - - - True - False - - - False - True - - - - - True - False - True - gtk-preferences - - - - False - True - - - - - False - True - 1 - - - - - True - True - 400 - - - True - True - - - True - True - - - - - - True - False - - - - - True - False - - - True - False - 2 - 0 - 0 - etched-out - - - True - False - 5 - - - 200 - 200 - True - False - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK - - - - - - - - - - Preview - True - True - False - True - True - - - - - - True - True - 0 - - - - - True - False - 2 - 0 - 0 - etched-out - - - True - False - - - True - False - 4 - 2 - 12 - - - True - False - 0 - Contrast - - - GTK_FILL - GTK_FILL - - - - - True - False - 0 - Brightness - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True - False - 0 - Saturation - - - 2 - 3 - GTK_FILL - GTK_FILL - - - - - True - True - contrast_adjust - True - 0 - 0 - right - - - 1 - 2 - - - - - True - True - brightness_adjust - 0 - 0 - right - - - 1 - 2 - 1 - 2 - - - - - True - True - saturation_adjust - off - off - 0 - 0 - right - - - 1 - 2 - 2 - 3 - - - - - True - False - 0 - Gain Ceiling - - - 3 - 4 - GTK_FILL - GTK_FILL - - - - - True - False - - - True - True - gainceiling_adjust - off - off - 0 - 0 - right - - - True - True - 0 - - - - - True - False - True - - - True - False - 0 - 2x - - - - - - True - True - 0 - - - - - True - False - 0 - 4x - - - - - - True - True - 1 - - - - - True - False - 0 - 8x - - - - - - True - True - 2 - - - - - True - False - 0 - 16x - - - - - - True - True - 3 - - - - - True - False - 0 - 32x - - - - - - True - True - 4 - - - - - True - False - 0 - 64x - - - - - - True - True - 5 - - - - - True - False - 0 - 128x - - - - - - True - True - 6 - - - - - False - True - 1 - - - - - 1 - 2 - 3 - 4 - - - - - - - - - - True - False - 0 - <b>Controls</b> - True - - - - - False - True - 1 - - - - - False - True - - - - - True - True - - - - - True - True - - - - True - True - False - word - - - - - False - True - - - - - True - True - 2 - - - - - True - False - 2 - - - False - True - 3 - - - - - - - 300 - False - 5 - Preferences - center-on-parent - True - dialog - top_window - - - True - False - 20 - - - True - False - end - - - gtk-ok - True - True - True - True - - - False - False - 0 - - - - - gtk-cancel - True - True - True - True - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - 4 - 2 - 4 - - - True - False - Board - - - - 5 - - - - - True - False - Serial Port - - - 1 - 2 - - 5 - - - - - True - False - pref_board_liststore - 0 - - - - 0 - - - - - 1 - 2 - - - - - True - False - pref_port_liststore - 0 - - - - 0 - - - - - 1 - 2 - 1 - 2 - - - - - True - False - Baudrate - - - 2 - 3 - - 5 - - - - - True - False - baud_liststore - 0 - - - - 0 - - - - - 1 - 2 - 2 - 3 - - - - - True - True - 2 - - - - - - button11 - button12 - - - - False - 5 - An Update is Available! - center-on-parent - True - dialog - top_window - - - True - False - 2 - - - True - False - label - - - True - True - 1 - - - - - True - False - end - - - Download - True - True - True - True - image1 - http://www.google.com - - - False - False - 1 - - - - - gtk-cancel - True - True - True - True - - - False - False - 2 - - - - - True - True - 2 - - - - - - download_button - button22 - - - - False - 5 - Save Descriptor - center-on-parent - True - dialog - - - True - False - 1 - - - True - False - end - - - gtk-ok - True - True - True - True - - - False - False - 0 - - - - - gtk-cancel - True - True - True - True - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - gtk-missing-image - - - True - True - 1 - - - - - True - True - - /desc.freak - True - False - False - True - True - - - True - True - 2 - - - - - - button3 - button4 - - - - False - 5 - Save Template - center-on-parent - True - dialog - - - True - False - 1 - - - True - False - end - - - gtk-ok - True - True - True - True - - - False - False - 0 - - - - - gtk-cancel - True - True - True - True - - - False - False - 1 - - - - - False - True - end - 0 - - - - - True - False - gtk-missing-image - - - True - True - 1 - - - - - True - True - - /template.pgm - False - False - True - True - - - True - True - 2 - - - - - - button1 - button2 - - - diff --git a/usr/openmv-ide.py b/usr/openmv-ide.py deleted file mode 100755 index bd690a7f4..000000000 --- a/usr/openmv-ide.py +++ /dev/null @@ -1,1060 +0,0 @@ -#!/usr/bin/env python2 -import openmv -import gtk -import gobject -import pango -import serial -import platform -import sys, os, os.path -from time import sleep -from os.path import expanduser -import gtksourceview2 as gtksourceview -import glob -import urllib2, json -import numpy as np -import serial.tools.list_ports as list_ports -try: - # 3.x name - import configparser -except ImportError: - # 2.x name - configparser = __import__("ConfigParser") - -if hasattr(sys,"frozen"): - IDE_DIR=os.path.dirname(sys.executable) - BUNDLE_DIR = sys._MEIPASS -else: - IDE_DIR=os.path.dirname(os.path.realpath(__file__)) - BUNDLE_DIR = IDE_DIR - -FIRMWARE_VERSION_MAJOR = 2 -FIRMWARE_VERSION_MINOR = 1 -FIRMWARE_VERSION_PATCH = 0 - -RELEASE_TAG_NAME = 'v2.0' -RELEASE_URL = 'https://api.github.com/repos/openmv/openmv/releases/latest' - -SCALE =1 -RECENT_FILES_LIMIT=5 -FLASH_SECTOR_START=1 -FLASH_SECTOR_END=11 - -DATA_DIR = os.path.join(os.path.expanduser("~"), "openmv") #use home dir -SCRIPTS_DIR = os.path.join(DATA_DIR, "scripts") -EXAMPLES_DIR = os.path.join(IDE_DIR, "examples") -GLADE_PATH = os.path.join(BUNDLE_DIR, "openmv-ide.glade") -CONFIG_PATH = os.path.join(DATA_DIR, "openmv.config") -UDEV_PATH = "/etc/udev/rules.d/50-openmv.rules" - -DEFAULT_CONFIG='''\ -[main] -board = OpenMV2 -serial_port = /dev/openmvcam -recent = -last_fw_path = -baudrate = 921600 -enable_jpeg = True -''' -CONFIG_KEYS = ['board', 'serial_port', 'recent', 'last_fw_path', 'baudrate', 'enable_jpeg'] -OPENMV_BOARDS = ['OpenMV1', 'OpenMV2'] - -class Bootloader: - def __init__(self, builder, config): - self.config = config - self.parent = builder.get_object("top_window") - self.dialog = builder.get_object("fw_dialog") - self.dialog.set_transient_for(self.parent) - - self.fw_progress = builder.get_object("fw_progressbar") - self.fw_path_entry = builder.get_object("fw_path_entry") - self.fw_path_button = builder.get_object("fw_path_button") - - self.ok_button = builder.get_object("fw_ok_button") - self.cancel_button = builder.get_object("fw_cancel_button") - self.erase_fs_check = builder.get_object("erase_fs_check") - - # Connect signals - self.dialog.connect("close", self.on_dialog_close) - self.dialog.connect("delete_event", self.on_dialog_close) - self.dialog.connect("response", self.on_dialog_response) - self.fw_path_button.connect("clicked", self.on_fw_path) - - def show_message_dialog(self, msg_type, msg): - message = gtk.MessageDialog(parent=self.parent, flags=gtk.DIALOG_DESTROY_WITH_PARENT, - type=msg_type, buttons=gtk.BUTTONS_OK, message_format=msg) - message.run() - message.destroy() - - def on_fw_path(self, widget): - dialog = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_OPEN, - buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) - dialog.set_default_response(gtk.RESPONSE_OK) - dialog.set_current_folder(SCRIPTS_DIR) - ff = gtk.FileFilter() - ff.set_name("binary") - ff.add_pattern("*.bin") - dialog.add_filter(ff) - - if dialog.run() == gtk.RESPONSE_OK: - self.fw_path_entry.set_text(dialog.get_filename()) - - dialog.destroy() - - def run(self): - # Read config options - self.port = self.config.get("main", "serial_port") - self.baud = int(self.config.get("main", "baudrate")) - self.last_fw_path = self.config.get("main", "last_fw_path") - - # Firmware progress - self.fw_progress.set_text("") - self.fw_progress.set_fraction(0.0) - - # Buttons initial state - self.ok_button.set_sensitive(True) - self.cancel_button.set_sensitive(True) - self.fw_path_button.set_sensitive(True) - - # Set firmware path entry - if os.path.isfile(self.last_fw_path) == False: - self.last_fw_path = "" - self.fw_path_entry.set_text(self.last_fw_path) - - # Run bootloader dialog - self.dialog.run() - - # Fake multitasking :P - def task(self, state): - if (self.running == False or state["next"](state) == False): - self.dialog.hide() - return False - return True - - def task_init(self, state): - openmv.disconnect() - try: - # Attempt to connect to bootloader - openmv.init(self.port, baudrate=self.baud, timeout=0.050) - if openmv.bootloader_start(): - openmv.set_timeout(1) - state["next"] = self.task_erase - state["bar"].set_text("Erasing...") - self.cancel_button.set_sensitive(False) - except Exception as e: - openmv.disconnect() - if self.flash_msg: - state["bar"].set_text("Connecting to bootloader...\ - \n ") - else: - state["bar"].set_text("Connecting to bootloader...\ - \nDisconnect and re-connect cam!") - self.flash_msg = self.flash_msg ^ 1 - sleep(0.100) - - return True - - def task_erase(self, state): - sector = state["sector"] - sector_offset = state["sector_offset"] - state["bar"].set_fraction((sector-sector_offset+1)/float(FLASH_SECTOR_END-sector_offset+1)) - state["bar"].set_text("Erasing sector %d/%d"%((sector-sector_offset+1), FLASH_SECTOR_END-sector_offset+1)) - openmv.flash_erase(sector) - sector += 1 - if (sector == FLASH_SECTOR_END+1): - state["next"] = self.task_upload - state["sector"] = sector - return True - - def task_upload(self, state): - buf = state["buf"] - xfer_bytes = state["xfer_bytes"] - xfer_total = state["xfer_total"] - - # Send chunk - chunk = min (60, xfer_total-xfer_bytes) - openmv.flash_write(buf[xfer_bytes : xfer_bytes+chunk]) - - xfer_bytes += chunk - state["xfer_bytes"] = xfer_bytes - state["bar"].set_fraction(xfer_bytes/float(xfer_total)) - state["bar"].set_text("Uploading %d/%d"%(xfer_bytes, xfer_total)) - - if (xfer_bytes == xfer_total): - openmv.bootloader_reset() - openmv.disconnect() - return False - return True - - def on_dialog_close(self, widget, event=None): - self.dialog.hide() - self.running = False - return True - - def on_dialog_response(self, dialog, response, *args): - if response == gtk.RESPONSE_OK: - self.ok_button.set_sensitive(False) - self.fw_path_button.set_sensitive(False) - - fw_path = self.fw_path_entry.get_text() - try: - with open(fw_path, 'rb') as f: - buf = f.read() - except Exception as e: - self.show_message_dialog(gtk.MESSAGE_ERROR, "Failed to open file %s"%str(e)) - self.dialog.hide() - return - - self.last_fw_path = fw_path - self.config.set("main", "last_fw_path", self.last_fw_path) - - if self.erase_fs_check.get_active(): - sector_offset = FLASH_SECTOR_START - else: - sector_offset = FLASH_SECTOR_START + 3 - - self.state={ "next":self.task_init, "buf":buf, "sector":sector_offset, "sector_offset": sector_offset, - "bar":self.fw_progress, "dialog":self.dialog, "xfer_bytes":0, "xfer_total":len(buf)} - - self.flash_msg = 1 - self.running = True - - # Reset the camera if it's connected, this way the bootloader - # runs without disconnecting and reconnecting the camera. - try: - openmv.reset() - except: - pass - - gobject.gobject.idle_add(self.task, self.state) - else: - self.dialog.hide() - self.running = False - -class ColorStats: - def __init__(self): - pass - - def rgb2lab(self, rgb): - - def lin(c): - return 100 * ((c/12.92) if (c<=0.04045) else pow((c+0.055)/1.055, 2.4)) - - def f(t): - return pow(t, (1/3.0)) if (t>0.008856) else ((7.787037*t)+0.137931) - - r_lin = lin(rgb[0] / 255.0) - g_lin = lin(rgb[1] / 255.0) - b_lin = lin(rgb[2] / 255.0) - - x = (r_lin * 0.4124) + (g_lin * 0.3576) + (b_lin * 0.1805); - y = (r_lin * 0.2126) + (g_lin * 0.7152) + (b_lin * 0.0722); - z = (r_lin * 0.0193) + (g_lin * 0.1192) + (b_lin * 0.9505); - - x = f(x / 095.047) - y = f(y / 100.000) - z = f(z / 108.883) - - l = int(round(116 * y)) - 16; - a = int(round(500 * (x-y))); - b = int(round(200 * (y-z))); - - return (l, a, b) - - def rgb2gry(self, rgb): - - def lin(c): - return 100 * ((c/12.92) if (c<=0.04045) else pow((c+0.055)/1.055, 2.4)) - - def f(t): - return (1.055*pow(t, (1/2.4)))-0.055 if (t>0.0031308) else 12.92*t - - r_lin = lin(rgb[0] / 255.0) - g_lin = lin(rgb[1] / 255.0) - b_lin = lin(rgb[2] / 255.0) - - y = f(((r_lin * 0.2126) + (g_lin * 0.7152) + (b_lin * 0.0722)) / 100.0); - return max(min(y * 255, 255), 0) - - def stats(self, buf, f): - new_buf = np.zeros((buf.shape[0], buf.shape[1]), int) - hist = np.zeros(384, int) - for i in range(buf.shape[0]): - for j in range(buf.shape[1]): - color = f(buf[i][j]) - new_buf[i][j] = color - hist[int(color + 128)] += 1 - return (np.mean(new_buf), - np.median(new_buf), - np.argmax(hist) - 128, - np.std(new_buf), - np.amin(new_buf), - np.amax(new_buf), - np.percentile(new_buf, 25), - np.percentile(new_buf, 75)) - - def get_color_stats(self, pixbuf): - buf = pixbuf.get_pixels_array() - - r_stats = self.stats(buf, lambda x: x[0]) - g_stats = self.stats(buf, lambda x: x[1]) - b1stats = self.stats(buf, lambda x: x[2]) - l_stats = self.stats(buf, lambda x: self.rgb2lab(x)[0]) - a_stats = self.stats(buf, lambda x: self.rgb2lab(x)[1]) - b2stats = self.stats(buf, lambda x: self.rgb2lab(x)[2]) - y_stats = self.stats(buf, lambda x: self.rgb2gry(x)) - out = [r_stats, g_stats, b1stats, l_stats, a_stats, b2stats, y_stats] - - rgb_thresholds = [max(r_stats[6] - r_stats[3]*3, 0), - min(r_stats[7] + r_stats[3]*3, 255), - max(g_stats[6] - g_stats[3]*3, 0), - min(g_stats[7] + g_stats[3]*3, 255), - max(b1stats[6] - b1stats[3]*3, 0), - min(b1stats[7] + b1stats[3]*3, 255)] - lab_thresholds = [max(l_stats[6] - l_stats[3]*3, 0), - min(l_stats[7] + l_stats[3]*3, 100), - max(a_stats[6] - a_stats[3]*3, -128), - min(a_stats[7] + a_stats[3]*3, 127), - max(b2stats[6] - b2stats[3]*3, -128), - min(b2stats[7] + b2stats[3]*3, 127)] - gry_thresholds = [max(y_stats[6] - y_stats[3]*3, 0), - min(y_stats[7] + y_stats[3]*3, 255)] - out.extend([rgb_thresholds, lab_thresholds, gry_thresholds]) - - return \ - "# RGB Color Space Stats:\n"\ - "# R: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\ - "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\ - "# G: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\ - "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\ - "# B: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\ - "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\ - "#\n"\ - "# LAB Color Space Stats:\n"\ - "# L: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\ - "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\ - "# A: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\ - "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\ - "# B: Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\ - "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\ - "#\n"\ - "# GRY Color Space Stats:\n"\ - "# Mean %4d, Median %4d, Mode %4d, Stdev %4d\n"\ - "# Min %4d, Max %4d, LQ %4d, UQ %4d\n"\ - "#\n"\ - "# Suggested Thresholds (LQ-Stdev*3, UQ+Stdev*3):\n"\ - "# RGB = (%4d, %4d, %4d, %4d, %4d, %4d)\n"\ - "# LAB = (%4d, %4d, %4d, %4d, %4d, %4d)\n"\ - "# GRY = (%4d, %4d)\n"\ - "#\n"\ - "# *Use LAB for RGB565 and GRY for GRAYSCALE images."\ - % tuple([i for sub in out for i in sub]) - -class OMVGtk: - def __init__(self): - #Set the Glade file - self.builder = gtk.Builder() - self.builder.add_from_file(GLADE_PATH) - - # get top window - self.window = self.builder.get_object("top_window") - - # status bar stuff - self.statusbar = self.builder.get_object("statusbar") - self.statusbar_ctx = self.statusbar.get_context_id("default") - - # set buttons - self.save_button = self.builder.get_object('save_file_toolbutton') - self.connect_button = self.builder.get_object('connect_button') - self.exec_button = self.builder.get_object('exec_button') - self.stop_button = self.builder.get_object('stop_button') - - self.save_button.set_sensitive(False) - self.exec_button.set_sensitive(False) - self.stop_button.set_sensitive(False) - self.connect_button.set_sensitive(True) - - # set control buttons - self.controls = [ - self.builder.get_object('reset_button'), - self.builder.get_object('exec_button'), - self.builder.get_object('zoomin_button'), - self.builder.get_object('zoomout_button'), - self.builder.get_object('bestfit_button')] - - self.connected = False - map(lambda x:x.set_sensitive(False), self.controls) - - # gtksourceview widget - sourceview = gtksourceview.View() - lang_manager = gtksourceview.language_manager_get_default() - style_manager = gtksourceview.style_scheme_manager_get_default() - - # append cwd to style search paths - style_manager.set_search_path(style_manager.get_search_path() + - [os.path.join(IDE_DIR, "share/gtksourceview-2.0/styles")]) - - # append cwd to language search paths - lang_manager.set_search_path(lang_manager.get_search_path() + - [os.path.join(IDE_DIR, "share/gtksourceview-2.0/language-specs")]) - - # configure gtksourceview widget - sourceview.set_show_line_numbers(True) - sourceview.set_tab_width(4) - sourceview.set_indent_on_tab(True) - sourceview.set_insert_spaces_instead_of_tabs(True) - sourceview.set_auto_indent(True) - sourceview.set_highlight_current_line(True) - - fonts = [] - for font in sourceview.get_pango_context().list_families(): - fonts.append(font.get_name().lower()) - - if sys.platform.startswith("win"): - if "consolas" in fonts: - sourceview.modify_font(pango.FontDescription("consolas 10")) - else: - sourceview.modify_font(pango.FontDescription("courier new 10")) - elif sys.platform.startswith("darwin"): - if "monaco" in fonts: - sourceview.modify_font(pango.FontDescription("monaco 10")) - else: - sourceview.modify_font(pango.FontDescription("courier new 10")) - elif sys.platform.startswith("linux"): - if "dejavu sans mono" in fonts: - sourceview.modify_font(pango.FontDescription("dejavu sans mono 10")) - else: - sourceview.modify_font(pango.FontDescription("courier new 10")) - - # configure gtksourceview buffer - self.buffer = gtksourceview.Buffer() - self.buffer.set_highlight_syntax(True) - self.buffer.set_language(lang_manager.get_language("python")) - self.buffer.connect("changed", self.text_changed) - - sourceview.set_buffer(self.buffer) - self.builder.get_object("src_scrolledwindow").add(sourceview) - - # Configure terminal window - self.terminal_scroll = self.builder.get_object('vte_scrolledwindow') - self.terminal = self.builder.get_object('vte_textview') - self.terminal.modify_base(gtk.STATE_NORMAL, gtk.gdk.color_parse('black')) - self.terminal.modify_text(gtk.STATE_NORMAL, gtk.gdk.color_parse('green')) - - # get drawingarea - self.fb = None - self.pixbuf = None - self.drawingarea = self.builder.get_object("drawingarea") - self.da_menu = self.builder.get_object("da_menu") - - self.fb_enabled = False - - # selection coords - self.sel_ended=False - self.selection_started=False - self.x1 = self.y1 = self.x2 = self.y2 =0 - - # set control scales attributes - self.builder.get_object("contrast_adjust").attr= openmv.ATTR_CONTRAST - self.builder.get_object("brightness_adjust").attr= openmv.ATTR_BRIGHTNESS - self.builder.get_object("saturation_adjust").attr= openmv.ATTR_SATURATION - self.builder.get_object("gainceiling_adjust").attr= openmv.ATTR_GAINCEILING - - # create data directory - if not os.path.isdir(DATA_DIR): - os.makedirs(DATA_DIR) - - # create user scripts directory - if not os.path.isdir(SCRIPTS_DIR): - os.makedirs(SCRIPTS_DIR) - - # set config parser - self.config = configparser.ConfigParser() - - config_valid = True - - # check if config file exists - if os.path.isfile(CONFIG_PATH): - try: - # load config - self.config.read(CONFIG_PATH) - except Exception as e: - print ("Failed to open config file %s"%(e)) - sys.exit(1) - - # Check config keys, if one is missing set invalid - for key in CONFIG_KEYS: - if not self.config.has_option('main', key): - config_valid = False - break - else: - config_valid = False - - # create fresh config if needed - if config_valid == False: - try: - with open(CONFIG_PATH, "w") as f: - f.write(DEFAULT_CONFIG) - except Exception as e: - print ("Failed to create config file %s"%(e)) - sys.exit(1) - - # load or reload the config file - try: - self.config.read(CONFIG_PATH) - except Exception as e: - print ("Failed to open config file %s"%(e)) - sys.exit(1) - - # Current file path - self.file_path= None - - # Built-in examples menu - submenu = gtk.Menu() - for root, dirs, files in os.walk(EXAMPLES_DIR, topdown=True): - for dirname in sorted(dirs): - smenu = gtk.Menu() - path = os.path.join(root, dirname) - for f in os.listdir(path): - if f.endswith(".py"): - label = os.path.basename(f) - mitem = gtk.MenuItem(label, use_underline=False) - mitem.connect("activate", self.open_example, path) - smenu.append(mitem) - - menu = gtk.MenuItem(dirname) - menu.set_submenu(smenu) - submenu.append(menu) - - menu = self.builder.get_object('example_menu') - menu.set_submenu(submenu) - - # recent files menu - self.files = [] - files =self.config.get("main", "recent") - if files: - self.files = files.split(',') - self.update_recent_files() - - self.baudrate = int(self.config.get("main", "baudrate")) - - # Set firmware version - self.fw_version = (0, 0, 0) - - # load helloworld.py - self._load_file(os.path.join(EXAMPLES_DIR, "01-Basics", "helloworld.py")) - self.save_button.set_sensitive(False) - - #connect signals - signals = { - "on_top_window_destroy" : self.quit, - "on_connect_clicked" : self.connect_clicked, - "on_reset_clicked" : self.reset_clicked, - "on_execute_clicked" : self.execute_clicked, - "on_stop_clicked" : self.stop_clicked, - "on_bootloader_clicked" : self.bootloader_clicked, - "on_enable_fb_toggled" : self.enable_fb_toggled, - "on_motion_notify" : self.motion_notify, - "on_button_press" : self.button_pressed, - "on_button_release" : self.button_released, - "on_open_file" : self.open_file, - "on_new_file" : self.new_file, - "on_save_file" : self.save_file, - "on_save_file_as" : self.save_file_as, - "on_about_dialog" : self.about_dialog, - "on_pinout_dialog" : self.pinout_dialog, - "on_color_stats_activate" : self.color_stats, - "on_save_template_activate" : self.save_template, - "on_save_descriptor_activate" : self.save_descriptor, - "on_ctrl_scale_value_changed" : self.on_ctrl_scale_value_changed, - "on_zoomin_clicked" : self.zoomin_clicked, - "on_zoomout_clicked" : self.zoomout_clicked, - "on_bestfit_clicked" : self.bestfit_clicked, - "on_preferences_clicked" : self.preferences_clicked, - "on_vte_size_allocate" : self.scroll_terminal, - } - self.builder.connect_signals(signals) - - # Create bootloader object - self.bootloader = Bootloader(self.builder, self.config) - - def show_message_dialog(self, msg_type, msg): - message = gtk.MessageDialog(parent=self.window, flags=gtk.DIALOG_DESTROY_WITH_PARENT, - type=msg_type, buttons=gtk.BUTTONS_OK, message_format=msg) - message.run() - message.destroy() - - def connect(self): - connected = False - openmv.disconnect() - for i in range(10): - try: - # opens CDC port. - # Set small timeout when connecting - openmv.init(self.config.get("main", "serial_port"), baudrate=self.baudrate, timeout=0.050) - connected = True - break - except Exception as e: - connected = False - sleep(0.100) - - if not connected: - if platform.system() == "Linux" and not os.path.isfile(UDEV_PATH): - error_msg = ("Failed to open serial port.\n" - "Please install OpenMV's udev rules first:\n\n" - "sudo cp openmv/udev/50-openmv.rules /etc/udev/rules.d/\n" - "sudo udevadm control --reload-rules\n\n") - else: - error_msg = ("Failed to open serial port.\n" - "Please check the preferences Dialog.\n") - - self.show_message_dialog(gtk.MESSAGE_ERROR,"%s%s"%(error_msg, e)) - return - - # Set higher timeout after connecting for lengthy transfers. - openmv.set_timeout(1*2) # SD Cards can cause big hicups. - - # check firmware version - fw_ver = openmv.fw_version() - self.fw_version = fw_ver - ide_ver = (FIRMWARE_VERSION_MAJOR, FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCH) - - if (fw_ver[0] != FIRMWARE_VERSION_MAJOR or fw_ver[1] != FIRMWARE_VERSION_MINOR): - self.connected = False - self.show_message_dialog(gtk.MESSAGE_ERROR, - "Firmware version mismatch!\n" - "Please update the firmware image and/or the IDE!") - else: - self.connected = True - self._update_title() - map(lambda x:x.set_sensitive(True), self.controls) - - # Interrupt running code - openmv.stop_script() - - # Enable Framebuffer - enable_fb_check = self.builder.get_object("enable_fb_check") - self.fb_enabled = enable_fb_check.get_active() - openmv.enable_fb(self.fb_enabled) - - # Disable connect button - self.connect_button.set_sensitive(False) - - def disconnect(self): - try: - # stop running code - openmv.stop_script(); - except: - pass - - openmv.disconnect() - self.connected = False - self._update_title() - self.stop_button.set_sensitive(False) - self.connect_button.set_sensitive(True) - map(lambda x:x.set_sensitive(False), self.controls) - - def connect_clicked(self, widget): - self.connect() - - def reset_clicked(self, widget): - if (self.connected): - openmv.reset() - openmv.disconnect() - - def execute_clicked(self, widget): - buf = self.buffer.get_text(self.buffer.get_start_iter(), self.buffer.get_end_iter()) - # exec script - openmv.exec_script(buf) - self.exec_button.set_sensitive(False) - self.stop_button.set_sensitive(True) - - def stop_clicked(self, widget): - openmv.stop_script(); - self.exec_button.set_sensitive(True) - self.stop_button.set_sensitive(False) - - def zoomin_clicked(self, widget): - global SCALE - SCALE+=1 - - def zoomout_clicked(self, widget): - global SCALE - if SCALE>1: - SCALE-=1 - - def bestfit_clicked(self, widget): - global SCALE - SCALE=1 - - def preferences_clicked(self, widget): - board_combo = self.builder.get_object("board_combo") - sport_combo = self.builder.get_object("sport_combo") - baud_combo = self.builder.get_object("baud_combo") - dialog = self.builder.get_object("preferences_dialog") - - # Set selected board - board_combo.get_model().clear() - config_board = self.config.get("main", "board") - for i in range(0, len(OPENMV_BOARDS)): - board = OPENMV_BOARDS[i] - board_combo.append_text(board) - if (board == config_board): - board_combo.set_active(i) - - # Fill serial ports combo - sport_combo.get_model().clear() - serial_ports = self.list_serial_ports() - config_port = self.config.get("main", "serial_port") - for i in range(0, len(serial_ports)): - port = serial_ports[i] - sport_combo.append_text(port) - if (port == config_port): - sport_combo.set_active(i) - - # Save config - if dialog.run() == gtk.RESPONSE_OK: - self.config.set("main", "board", board_combo.get_active_text()) - self.config.set("main", "serial_port", sport_combo.get_active_text()) - self.config.set("main", "baudrate", baud_combo.get_active_text()) - self.config.set("main", "enable_jpeg", True) - self.save_config() - - dialog.hide() - - def bootloader_clicked(self, widget): - self.bootloader.run() - - def enable_fb_toggled(self, widget): - enable_fb_check = self.builder.get_object("enable_fb_check") - self.fb_enabled = enable_fb_check.get_active() - openmv.enable_fb(self.fb_enabled) - - def button_pressed(self, widget, event): - self.x1 = int(event.x) - self.y1 = int(event.y) - self.x2 = int(event.x) - self.y2 = int(event.y) - self.selection_started = True - - def button_released(self, widget, event): - self.x2 = int(event.x) - self.y2 = int(event.y) - self.selection_started = False - if (self.connected): - self.da_menu.popup(None, None, None, event.button, event.time, None) - self.da_menu.show_all() - - def motion_notify(self, widget, event): - x = int(event.x) - y = int(event.y) - self.x2 = int(event.x) - self.y2 = int(event.y) - if self.pixbuf and x < self.pixbuf.get_width() and y < self.pixbuf.get_height(): - pixel = self.pixbuf.get_pixels_array()[y][x] - rgb = "(%d, %d, %d)" %(pixel[0], pixel[1], pixel[2]) - self.statusbar.pop(self.statusbar_ctx) - self.statusbar.push(self.statusbar_ctx, rgb) - - def scroll_terminal(self, widget, event): - adj = self.terminal_scroll.get_vadjustment() - adj.set_value(adj.upper - adj.page_size) - - def update_terminal(self): - if (self.connected): - try: - buf_len = openmv.tx_buf_len() - if (buf_len): - buf = openmv.tx_buf(buf_len) - buffer = self.terminal.get_buffer() - buffer.insert(buffer.get_end_iter(), buf) - except: - pass - - return True - - def update_drawing(self): - fb = None - if (self.fb_enabled and self.connected): - try: - # read drawingarea - fb = openmv.fb_dump() - except Exception as e: - self.disconnect() - self._update_title() - return True - if fb: - self.fb = fb - else: - fb = self.fb - - if fb: - # create pixbuf from np array - self.pixbuf = gtk.gdk.pixbuf_new_from_array(fb[2], gtk.gdk.COLORSPACE_RGB, 8) - self.pixbuf = self.pixbuf.scale_simple(fb[0]*SCALE, fb[1]*SCALE, gtk.gdk.INTERP_BILINEAR) - - self.drawingarea.realize(); - cm = self.drawingarea.window.get_colormap() - gc = self.drawingarea.window.new_gc(foreground=cm.alloc_color('#FFFFFF',True,False)) - - self.drawingarea.set_size_request(fb[0]*SCALE, fb[1]*SCALE) - self.drawingarea.window.draw_pixbuf(gc, self.pixbuf, 0, 0, 0, 0) - if self.selection_started or self.da_menu.flags() & gtk.MAPPED: - self.drawingarea.window.draw_rectangle(gc, False, self.x1, self.y1, self.x2-self.x1, self.y2-self.y1) - - return True - - def update_exec_button(self): - if (self.connected): - try: - # read drawingarea - running = (openmv.script_running()==1) - self.stop_button.set_sensitive(running) - self.exec_button.set_sensitive(not running) - except Exception as e: - self.disconnect() - self._update_title() - - return True - - def on_ctrl_scale_value_changed(self, adjust): - openmv.set_attr(adjust.attr, int(adjust.value)) - - def save_config(self): - # config.set("section", "key", value) - self.config.set("main", "recent", ','.join(self.files)) - with open(CONFIG_PATH, "w") as file: - self.config.write(file) - - def _update_title(self): - if (self.file_path==None): - title = "Untitled" - else: - title = os.path.basename(self.file_path) - - if not self.connected: - title += " [Disconnected]" - else: - title += " [Connected. Firmware: v%d.%d.%d]"%self.fw_version - - self.window.set_title(title) - - def update_recent_files(self): - if (self.file_path and self.file_path not in self.files ): - self.files.insert(0, self.file_path) - - if len(self.files)>RECENT_FILES_LIMIT: - self.files.pop() - - submenu = gtk.Menu() - menu = self.builder.get_object('recent_menu') - for f in self.files: - if f.endswith(".py"): - mitem =gtk.MenuItem(f, use_underline=False) - mitem.connect("activate", self.open_example, "") - submenu.append(mitem) - - menu.set_submenu(submenu) - menu.show_all() - - def _load_file(self, path): - buf = '' - self.file_path = path - if path == None: # New file - self.save_button.set_sensitive(True) - else: - self.save_button.set_sensitive(False) - with open(path, "r") as file: - buf = file.read() - self.update_recent_files() - - self._update_title() - self.buffer.begin_not_undoable_action() - self.buffer.set_text(buf) - self.buffer.end_not_undoable_action() - - def _save_file(self, new_file): - if new_file: - dialog = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_SAVE, - buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) - dialog.set_default_response(gtk.RESPONSE_OK) - dialog.set_current_folder(SCRIPTS_DIR) - ff = gtk.FileFilter() - ff.set_name("python") - ff.add_pattern("*.py") - dialog.add_filter(ff) - - if dialog.run() == gtk.RESPONSE_OK: - self.file_path = dialog.get_filename() - self.save_button.set_sensitive(False) - self._update_title() - self.update_recent_files() - - # append .py - filename = dialog.get_filename() - if not filename.endswith(".py"): - filename += ".py" - - # save file - with open(filename, "w") as file: - file.write(self.buffer.get_text(self.buffer.get_start_iter(), self.buffer.get_end_iter())) - - dialog.destroy() - else: - self.save_button.set_sensitive(False) - with open(self.file_path, "w") as file: - file.write(self.buffer.get_text(self.buffer.get_start_iter(), self.buffer.get_end_iter())) - - def color_stats(self, widget): - self.da_menu.hide() - - if (self.pixbuf): - x = max(0, self.x1) - y = max(0, self.y1) - w = max(1, self.x2-self.x1) - h = max(1, self.y2-self.y1) - - cs = ColorStats() - stats = cs.get_color_stats(self.pixbuf.subpixbuf(x, y, w, h)) - self.show_message_dialog(gtk.MESSAGE_INFO, stats) - - def save_template(self, widget): - self.da_menu.hide() - - if (self.pixbuf): - x = max(0, self.x1) - y = max(0, self.y1) - w = max(1, self.x2-self.x1) - h = max(1, self.y2-self.y1) - - entry = self.builder.get_object("template_entry") - image = self.builder.get_object("template_image") - image.set_from_pixbuf(self.pixbuf.subpixbuf(x, y, w, h)) - - dialog = self.builder.get_object("save_template_dialog") - dialog.set_transient_for(self.window); - #dialog.set_default_response(gtk.RESPONSE_OK) - - if dialog.run() == gtk.RESPONSE_OK: - openmv.save_template(x/SCALE, y/SCALE, w/SCALE, h/SCALE, entry.get_text()) #Use Scale - dialog.hide() - - def save_descriptor(self, widget): - self.da_menu.hide() - - if (self.pixbuf): - x = max(0, self.x1) - y = max(0, self.y1) - w = max(1, self.x2-self.x1) - h = max(1, self.y2-self.y1) - - entry = self.builder.get_object("desc_entry") - image = self.builder.get_object("desc_image") - image.set_from_pixbuf(self.pixbuf.subpixbuf(x, y, w, h)) - - dialog = self.builder.get_object("save_descriptor_dialog") - dialog.set_transient_for(self.window); - #dialog.set_default_response(gtk.RESPONSE_OK) - - if dialog.run() == gtk.RESPONSE_OK: - #if not entry.get_text(): - openmv.save_descriptor(x/SCALE, y/SCALE, w/SCALE, h/SCALE, entry.get_text()) #Use Scale - dialog.hide() - - def new_file(self, widget): - self._load_file(None) - - def save_file(self, widget): - self._save_file(self.file_path==None) - - def save_file_as(self, widget): - self._save_file(True) - - def open_file(self, widget): - dialog = gtk.FileChooserDialog(title=None,action=gtk.FILE_CHOOSER_ACTION_OPEN, - buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) - dialog.set_default_response(gtk.RESPONSE_OK) - dialog.set_current_folder(SCRIPTS_DIR) - ff = gtk.FileFilter() - ff.set_name("python") - ff.add_pattern("*.py") - dialog.add_filter(ff) - - if dialog.run() == gtk.RESPONSE_OK: - self._load_file(dialog.get_filename()) - - dialog.destroy() - - def open_example(self, widget, basedir): - self.file_path = os.path.join(basedir, widget.get_label()) - self._load_file(self.file_path) - - def about_dialog(self, widget): - dialog = self.builder.get_object("about_dialog") - ide_version = "v%d.%d.%d"%(FIRMWARE_VERSION_MAJOR, FIRMWARE_VERSION_MINOR, FIRMWARE_VERSION_PATCH) - dialog.set_version(ide_version) - dialog.run() - dialog.hide() - - def pinout_dialog(self, widget): - dialog = self.builder.get_object("pinout_dialog") - dialog.run() - dialog.hide() - - def text_changed(self, widget): - self.save_button.set_sensitive(True) - - def list_serial_ports(self): - serial_ports = [] - system_name = platform.system() - - if system_name == "Linux": - serial_ports.append("/dev/openmvcam") - elif system_name == "Darwin": - serial_ports.extend(glob.glob('/dev/tty.*')) - elif system_name == "Windows": - for port in list_ports.comports(): - serial_ports.append(port[0]) - - return serial_ports - - def check_for_updates(self): - try: - url = urllib2.urlopen(RELEASE_URL) - release = json.loads(url.read()) - url.close() - if (release['tag_name'] != RELEASE_TAG_NAME): - dialog = self.builder.get_object("update_dialog") - dn_button = self.builder.get_object("download_button") - - # Set release notes - self.builder.get_object("rn_label").\ - set_text('Release notes (%s):\n\n%s'%(release['tag_name'], release['body'])) - # Set URL - dn_button.set_uri(release['html_url']) - dialog.run() - dialog.hide() - except: - pass #pass quietly - - def quit(self, widget): - try: - # disconnect - self.disconnect() - except: - pass - - self.save_config() - # exit - gtk.main_quit() - -if __name__ == "__main__": - omvgtk = OMVGtk() - omvgtk.window.show_all() - omvgtk.check_for_updates() - # Terminal update callback - gobject.gobject.timeout_add(30, omvgtk.update_terminal) - # Framebuffer update callback - gobject.gobject.timeout_add(10, omvgtk.update_drawing) - # Execute button update callback - gobject.gobject.timeout_add(500, omvgtk.update_exec_button) - gtk.main() diff --git a/usr/pinout.png b/usr/pinout.png deleted file mode 100644 index b6b6cc7ad..000000000 Binary files a/usr/pinout.png and /dev/null differ