def ConnectWiimote(self, config_file, daemon): """Request a wiimote connection using the config_file as mapping. In order to allow connections a bluetooth adaptor must be available, the uinput module must be loaded and no other connection could be in use (3 - WC_AVAILABLE status, check the StatusChanged signal for more info). The bluetooth adaptor connection changes are auto-discovered. By now, the uinput module load/unload it's only discovered at service start and at bluetooth adaptor connection changes too. So the best it's to ensure that module it's loaded before launching the service. The daemon mode sets the connection for waiting indefinitely for pressing 1+2 (not daemon mode only wait for 3 seconds) and trying to reconnect if wiimote it's disconnected. Parameters: config_file - a string with the absolute path to mapping config file daemon - a boolean to set the daemon mode Potential Errors: Not uinput module present Not bluetooth adapter present A wiimote connection still in use (disconnect first) Mapping validation error """ self.__check_uinput_present() if not self.status & WC_UINPUT_PRESENT: raise dbus.exceptions.DBusException('Not uinput module present') elif not self.status & WC_BLUEZ_PRESENT: raise dbus.exceptions.DBusException('Not bluetooth adapter present') elif self.status & WC_WIIMOTE_DISCOVERING: raise dbus.exceptions.DBusException('Disconnect wiimote first') else: if config_file: validator = MappingValidator() validator.validate_file(config_file, False) if validator.validation_errors: raise dbus.exceptions.DBusException('Mapping validation error') return self.__wminput = WMInputLauncher(config_file, daemon) self.__wminput.start()
def __init__(self, mapping, system_mapping=False): self.mapping = mapping self.builder = gtk.Builder() if not self.builder.add_objects_from_file(MAPPING_UI, ["mapping_editor_dlg"]): # , 'mapping_buffer']): raise "Cant load %s" % MAPPING_UI self.builder.connect_signals(self) self.mapping_editor_dlg = self.builder.get_object("mapping_editor_dlg") self.name_entry = self.builder.get_object("name_entry") self.comment_entry = self.builder.get_object("comment_entry") self.version_entry = self.builder.get_object("version_entry") self.authors_entry = self.builder.get_object("authors_entry") self.scrolledwindow2 = self.builder.get_object("scrolledwindow2") self.icon_image = self.builder.get_object("icon_image") self.execute_btn = self.builder.get_object("execute_btn") lm = gtksourceview2.LanguageManager() self.mapping_buffer = gtksourceview2.Buffer() self.mapping_buffer.set_data("languages-manager", lm) view = gtksourceview2.View(self.mapping_buffer) view.set_show_line_numbers(True) view.set_auto_indent(True) self.scrolledwindow2.add(view) self.scrolledwindow2.show_all() if system_mapping: self.warning_box = self.builder.get_object("warning_box") self.warning_frame = self.builder.get_object("warning_frame") self.warning_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#F6FA9C")) self.warning_frame.show_all() # FIXME: iconfilechooser with default dialog from glade 3.6.7 crashes self.icon_dlg = IconChooserDialog(self.mapping_editor_dlg) self.iconfilechooser_btn = gtk.FileChooserButton(self.icon_dlg) self.iconfilechooser_btn.show() self.iconfilechooser_btn.connect("file-set", self.iconfilechooser_btn_file_set_cb) self.builder.get_object("hbox2").add(self.iconfilechooser_btn) # Populate dialog with mapping values pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.mapping.get_icon(), 48, 48) self.icon_image.set_from_pixbuf(pixbuf) self.name_entry.set_text(self.mapping.get_name() or "") self.comment_entry.set_text(self.mapping.get_comment() or "") self.version_entry.set_text(self.mapping.get_version() or "") self.authors_entry.set_text(self.mapping.get_authors() or "") self.mapping_buffer.set_text(self.mapping.get_mapping() or "") self.mapping_buffer.place_cursor(self.mapping_buffer.get_start_iter()) self.mapping_editor_dlg.set_title(_("Editing ") + self.mapping.get_name()) # Initial error underlining and colorize comments self.mapping_buffer.create_tag("underline_error", underline=pango.UNDERLINE_ERROR) self.mapping_buffer.create_tag("comment", foreground="darkblue") self.validator = MappingValidator() self.changed_cb(None) self.mapping_buffer.connect("changed", self.changed_cb) # Connect and manage wiican service status bus = dbus.SessionBus() self.wiican_iface = dbus.Interface(bus.get_object(WIICAN_URI, WIICAN_PATH), WIICAN_URI) # FIXME: I think that handler_block/unblock its a bad design for this self.sig_id = self.execute_btn.connect("clicked", self.execute_btn_clicked_cb) def wiican_status_changed(new_status): if new_status & WC_WIIMOTE_DISCOVERING: if not self.execute_btn.get_active(): self.execute_btn.handler_block(self.sig_id) self.execute_btn.set_active(True) self.execute_btn.handler_unblock(self.sig_id) self.execute_btn.set_tooltip_text(_("A mapping is running")) self.execute_btn.set_image(gtk.image_new_from_pixbuf(wiican_disc3_icon)) elif new_status == (WC_UINPUT_PRESENT | WC_BLUEZ_PRESENT): self.execute_btn.set_sensitive(True) self.execute_btn.set_tooltip_text(_("Execute this mapping")) self.execute_btn.set_image(gtk.image_new_from_pixbuf(wiican_on_icon)) if self.execute_btn.get_active(): self.execute_btn.handler_block(self.sig_id) self.execute_btn.set_active(False) self.execute_btn.handler_unblock(self.sig_id) else: self.execute_btn.set_sensitive(False) self.execute_btn.set_image(gtk.image_new_from_pixbuf(wiican_off_icon)) self.execute_btn.set_tooltip_text( _("Ensure a bluetooth " + "adapter its available and uinput module its loaded") ) self.wiican_iface.connect_to_signal("StatusChanged", wiican_status_changed, dbus_interface="org.gnome.Wiican") status = self.wiican_iface.GetStatus() wiican_status_changed(status) self.notificator = Notificator("wiican")
class MappingEditorDialog(object): def __init__(self, mapping, system_mapping=False): self.mapping = mapping self.builder = gtk.Builder() if not self.builder.add_objects_from_file(MAPPING_UI, ["mapping_editor_dlg"]): # , 'mapping_buffer']): raise "Cant load %s" % MAPPING_UI self.builder.connect_signals(self) self.mapping_editor_dlg = self.builder.get_object("mapping_editor_dlg") self.name_entry = self.builder.get_object("name_entry") self.comment_entry = self.builder.get_object("comment_entry") self.version_entry = self.builder.get_object("version_entry") self.authors_entry = self.builder.get_object("authors_entry") self.scrolledwindow2 = self.builder.get_object("scrolledwindow2") self.icon_image = self.builder.get_object("icon_image") self.execute_btn = self.builder.get_object("execute_btn") lm = gtksourceview2.LanguageManager() self.mapping_buffer = gtksourceview2.Buffer() self.mapping_buffer.set_data("languages-manager", lm) view = gtksourceview2.View(self.mapping_buffer) view.set_show_line_numbers(True) view.set_auto_indent(True) self.scrolledwindow2.add(view) self.scrolledwindow2.show_all() if system_mapping: self.warning_box = self.builder.get_object("warning_box") self.warning_frame = self.builder.get_object("warning_frame") self.warning_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#F6FA9C")) self.warning_frame.show_all() # FIXME: iconfilechooser with default dialog from glade 3.6.7 crashes self.icon_dlg = IconChooserDialog(self.mapping_editor_dlg) self.iconfilechooser_btn = gtk.FileChooserButton(self.icon_dlg) self.iconfilechooser_btn.show() self.iconfilechooser_btn.connect("file-set", self.iconfilechooser_btn_file_set_cb) self.builder.get_object("hbox2").add(self.iconfilechooser_btn) # Populate dialog with mapping values pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.mapping.get_icon(), 48, 48) self.icon_image.set_from_pixbuf(pixbuf) self.name_entry.set_text(self.mapping.get_name() or "") self.comment_entry.set_text(self.mapping.get_comment() or "") self.version_entry.set_text(self.mapping.get_version() or "") self.authors_entry.set_text(self.mapping.get_authors() or "") self.mapping_buffer.set_text(self.mapping.get_mapping() or "") self.mapping_buffer.place_cursor(self.mapping_buffer.get_start_iter()) self.mapping_editor_dlg.set_title(_("Editing ") + self.mapping.get_name()) # Initial error underlining and colorize comments self.mapping_buffer.create_tag("underline_error", underline=pango.UNDERLINE_ERROR) self.mapping_buffer.create_tag("comment", foreground="darkblue") self.validator = MappingValidator() self.changed_cb(None) self.mapping_buffer.connect("changed", self.changed_cb) # Connect and manage wiican service status bus = dbus.SessionBus() self.wiican_iface = dbus.Interface(bus.get_object(WIICAN_URI, WIICAN_PATH), WIICAN_URI) # FIXME: I think that handler_block/unblock its a bad design for this self.sig_id = self.execute_btn.connect("clicked", self.execute_btn_clicked_cb) def wiican_status_changed(new_status): if new_status & WC_WIIMOTE_DISCOVERING: if not self.execute_btn.get_active(): self.execute_btn.handler_block(self.sig_id) self.execute_btn.set_active(True) self.execute_btn.handler_unblock(self.sig_id) self.execute_btn.set_tooltip_text(_("A mapping is running")) self.execute_btn.set_image(gtk.image_new_from_pixbuf(wiican_disc3_icon)) elif new_status == (WC_UINPUT_PRESENT | WC_BLUEZ_PRESENT): self.execute_btn.set_sensitive(True) self.execute_btn.set_tooltip_text(_("Execute this mapping")) self.execute_btn.set_image(gtk.image_new_from_pixbuf(wiican_on_icon)) if self.execute_btn.get_active(): self.execute_btn.handler_block(self.sig_id) self.execute_btn.set_active(False) self.execute_btn.handler_unblock(self.sig_id) else: self.execute_btn.set_sensitive(False) self.execute_btn.set_image(gtk.image_new_from_pixbuf(wiican_off_icon)) self.execute_btn.set_tooltip_text( _("Ensure a bluetooth " + "adapter its available and uinput module its loaded") ) self.wiican_iface.connect_to_signal("StatusChanged", wiican_status_changed, dbus_interface="org.gnome.Wiican") status = self.wiican_iface.GetStatus() wiican_status_changed(status) self.notificator = Notificator("wiican") def changed_cb(self, widget, data=None): start, end = self.mapping_buffer.get_bounds() self.mapping_buffer.remove_all_tags(start, end) start, end = self.mapping_buffer.get_bounds() self.validator.validate(self.mapping_buffer.get_text(start, end), halt_on_errors=False) for error in self.validator.validation_errors: if not error: continue start = self.mapping_buffer.get_iter_at_offset(error.lexpos) # FIXME: Finding '\n' for underlining error it's not the best way end = self.mapping_buffer.get_iter_at_offset(error.lexpos + error.value.find("\n")) self.mapping_buffer.apply_tag_by_name("underline_error", start, end) for comment in self.validator.comments: start = self.mapping_buffer.get_iter_at_offset(comment.lexpos) end = self.mapping_buffer.get_iter_at_offset(comment.lexpos + len(comment.value)) self.mapping_buffer.apply_tag_by_name("comment", start, end) def set_title(self, title=""): self.mapping_editor_dlg.set_title(title) def run(self): return self.mapping_editor_dlg.run() def destroy(self): self.mapping_editor_dlg.destroy() def get_mapping(self): start, end = self.mapping_buffer.get_bounds() mapping_code = self.mapping_buffer.get_text(start, end) # FIXME: If mapping doesn't ends with \n wminput prompts segfault if not mapping_code.endswith("\n"): mapping_code += "\n" self.mapping.set_mapping(mapping_code) self.mapping.set_name(self.name_entry.get_text()) self.mapping.set_comment(self.comment_entry.get_text()) self.mapping.set_version(self.version_entry.get_text()) self.mapping.set_authors(self.authors_entry.get_text()) return self.mapping def help_btn_clicked_cb(self, widget): webbrowser.open(widget.get_uri()) def execute_btn_clicked_cb(self, widget): if self.execute_btn.get_active(): start, end = self.mapping_buffer.get_bounds() mapping_code = self.mapping_buffer.get_text(start, end) # FIXME: If mapping doesn't ends with \n wminput prompts segfault if not mapping_code.endswith("\n"): mapping_code += "\n" # TODO: This file must be unlinked after being used filename = tempfile.mktemp() fp = open(filename, "w") fp.write(mapping_code) fp.close() try: self.wiican_iface.ConnectWiimote(filename, True) except dbus.exceptions.DBusException, error: if error.message == ("Mapping validation error"): valerr_dlg = ValidationErrorDialog(self.mapping.get_icon(), parent=self.mapping_editor_dlg) valerr_dlg.run() valerr_dlg.destroy() return self.notificator.display_notification( title=_("Press 1+2"), text=_("To put you Wiimote in discoverable mode now"), icon="wiican" ) else: