#!/usr/bin/python2.3 """ Copyright (c) 2005 Erik Rigtorp 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. """ VERSION='0.1' import pygtk pygtk.require("2.0") import gtk, gobject, pango import egg.trayicon import md5, string, math def wep_key_from_passphrase(passphrase): """Returns a static WEP-key created from passphrase""" data = "" for i in range(64): data += passphrase[i % len(passphrase)] m = md5.new() m.update(data) return m.hexdigest()[:26] def is_hex_string(string): for char in string: if not char in string.hexdigits: return False return True class Unplugged: def __init__(self, interface): self.supplicant = WpaSupplicantControler(interface) self.trayicon = egg.trayicon.TrayIcon("Unplugged") self.eventbox = gtk.EventBox() self.image = gtk.Image() self.image.set_from_pixbuf(radio0p) self.eventbox.add(self.image) self.trayicon.add(self.eventbox) self.trayicon.show_all() self.eventbox.connect("button-release-event", self.button_release_event) self.eventbox.connect("enter-notify-event", self.enter_notify_event) self.eventbox.set_events(gtk.gdk.ENTER_NOTIFY_MASK) self.oldq = 0 gobject.timeout_add(500, self.update_icon_event) def update_icon_event(self): q = self.supplicant.interface_link_quality() if not self.oldq == q: self.oldq = q if q == 0: self.image.set_from_pixbuf(radio0p) elif q < 25: self.image.set_from_pixbuf(radio1p) elif q < 50: self.image.set_from_pixbuf(radio2p) elif q < 75: self.image.set_from_pixbuf(radio3p) else: self.image.set_from_pixbuf(radio4p) return True def enter_notify_event(self, widget, event): status = self.supplicant.get_status() tooltips = gtk.Tooltips() if status['wpa_state'] == 'COMPLETED': msg = 'Connected to network "' + status['ssid'] + '"' else: msg = 'Not connected' tooltips.set_tip(self.eventbox, msg) tooltips.enable() def button_release_event(self, widget, event): if event.button == 1: self.supplicant.request('SCAN') wlans = self.supplicant.get_available_networks() menu = self._menu(wlans) menu.popup(None,None,None,1,0) elif event.button == 3: about = gtk.AboutDialog() about.set_name('Unplugged') about.set_version(VERSION) about.set_copyright(u'© 2005 Erik Rigtorp') about.set_comments('Simple notification area icon to manage wireless networks.') about.set_authors(['Erik Rigtorp ']) about.set_website('http://rigtorp.se/unplugged.xhtml') about.set_logo(radio4p) about.show() def network_selected(self, widget, event, wlan): if wlan['configured'] == True: self.supplicant.select_network(wlan['id']) elif wlan['flags'] == '': self.supplicant.add_trusted_network(wlan) else: key = self._passphrase_dialog(wlan['essid']) if key: self.supplicant.add_trusted_network(wlan, key) def _passphrase_dialog(self, essid): dialog = gtk.Dialog('Wireless Network Key required', None, gtk.DIALOG_NO_SEPARATOR, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT, gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT)) dialog.set_default_response(gtk.RESPONSE_ACCEPT) dialog.set_border_width(12) hbox = gtk.HBox(False, 12) image = gtk.image_new_from_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_DIALOG) image.set_alignment(0.5, 0) hbox.pack_start(image) vbox = gtk.VBox(False, 12) label = gtk.Label('Passphrase required by Wireless Network') label.set_line_wrap(True) font = label.get_style().font_desc font.set_weight(pango.WEIGHT_BOLD) font.set_size(int(font.get_size() * pango.SCALE_LARGE)) label.modify_font(font) vbox.pack_start(label) message = gtk.Label('A passphrase or encryption key is required to access the wireless network "' + essid + '".') message.set_line_wrap(True) message.set_alignment(0,0) vbox.pack_start(message) entry = gtk.Entry() vbox.pack_start(entry) hbox.pack_start(vbox) dialog.vbox.pack_start(hbox) dialog.show_all() response = dialog.run() dialog.destroy() if response == gtk.RESPONSE_ACCEPT: return entry.get_text() else: return None def _menu(self, wlans): menu = gtk.Menu() group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) if len(wlans) == 0: label = gtk.Label('No networks found') menuitem = gtk.MenuItem() menuitem.add(label) menuitem.show_all() menu.append(menuitem) return menu for wlan in wlans: essid=gtk.Label(wlan['essid']) level=gtk.ProgressBar() level.set_fraction(wlan['level'] / 256.0) if wlan['flags'] in ['[WEP]', '[WPA-PSK-TKIP]', '[WPA-PSK-CCMP]']: encrypted = gtk.image_new_from_stock(gtk.STOCK_DIALOG_AUTHENTICATION, gtk.ICON_SIZE_MENU) else: encrypted = gtk.Label('') group.add_widget(encrypted) menuitem = gtk.ImageMenuItem() if wlan['connected'] == True: menuitem.set_image(gtk.image_new_from_stock(gtk.STOCK_CONNECT, gtk.ICON_SIZE_MENU)) elif wlan['configured']: menuitem.set_image(gtk.image_new_from_stock(gtk.STOCK_DISCONNECT, gtk.ICON_SIZE_MENU)) hbox = gtk.HBox(False, 6) hbox.pack_start(essid, False, False) hbox.pack_end(encrypted, False, False) hbox.pack_end(level, False, False) menuitem.add(hbox) menuitem.connect("button-release-event", self.network_selected, wlan) menuitem.show_all() menu.append(menuitem) return menu import socket, os, select class WpaSupplicantControler: def __init__(self, interface): self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0); self.socket.bind('/tmp/wpa_ctrl_' + str(os.getpid()) + '-0') self.socket.connect('/var/run/wpa_supplicant/' + interface) self.socket.setblocking(0) self.interface = interface self.callbacks = [] self.event_socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0); self.event_socket.bind('/tmp/wpa_ctrl_' + str(os.getpid()) + '-1') self.event_socket.connect('/var/run/wpa_supplicant/' + interface) self.event_socket.send('ATTACH') gobject.io_add_watch(self.event_socket.fileno(), gobject.IO_IN, self.event_dispatcher, self.event_socket) def event_dispatcher(self, source, condition, socket): recived_event = socket.recv(512) for event, callback in self.callbacks: if recived_event.find(event): callback() return True def connect(self, event, callback): self.callbacks.append((event, callback)) def request(self, request): self.socket.send(request) select.select([self.socket],[],[]) return self.socket.recv(512) def get_status(self): status = {} for line in self.request('STATUS').split('\n')[:-1]: key, value = line.split('=') status[key] = value return status def get_trusted_networks(self): tmp = {} for l in self.request('LIST_NETWORKS').split('\n')[1:-1]: t = l.split('\t') network = {} network['id'] = int(t[0]) network['bssid'] = t[2] network['flags'] = t[3] tmp[t[1]] = network return tmp def get_available_networks(self): status = self.get_status() trusted_networks = self.get_trusted_networks() wlans = [] for line in self.request('SCAN_RESULTS').split('\n')[1:-1]: t = line.split('\t') wlan = {} wlan['bssid'] = t[0] wlan['freq'] = t[1] wlan['level'] = int(t[2]) wlan['flags'] = t[3] wlan['essid'] = t[4] wlan['connected'] = False if status['wpa_state'] == 'COMPLETED': if wlan['bssid'] == status['bssid']: wlan['connected'] = True if wlan['essid'] in trusted_networks.keys(): wlan['configured'] = True wlan['id'] = trusted_networks[wlan['essid']]['id'] else: wlan['configured'] = False wlans.append(wlan) return wlans def add_trusted_network(self, network, key=None): options = {'ssid': '"' + network['essid'] +'"'} if network['flags'] == '': options['key_mgmt'] = 'NONE' elif network['flags'] in ['[WPA-PSK-TKIP]', '[WPA-PSK-CCMP]']: if len(key) == 64 and is_hex_string(key): # hex key psk = key elif len(key) > 8 and len(key) < 64: # passphrase psk = '"' + key + '"' else: print "add_trusted_network: invalid key" return options['proto'] = 'WPA RSN' options['key_mgmt'] = 'WPA-PSK' options['pairwise'] = 'CCMP TKIP' options['group'] = 'TKIP CCMP WEP104 WEP40' options['eapol_flags'] = '3' options['eap_workaround'] = '-1' options['psk'] = psk elif network['flags'] == '[WEP]': if (len(key) == 10 or len(key) == 26) and is_hex_string(key): wepkey = key elif len(key) == 10 or len(key) == 26: wepkey = '"' + key + '"' elif len(key) > 0: wepkey = wep_key_from_passphrase(key) else: print "add_trusted_network: invalid key" return options['key_mgmt'] = 'NONE' options['wep_key0'] = wepkey id = self.add_network() self.set_network(id, options) self.select_network(id) self.save_config() def select_network(self, id): self.request('SELECT_NETWORK ' + str(id)) def save_config(self): if self.request('SAVE_CONFIG') != 'OK\n': print "save_config: error" def add_network(self): id = self.request('ADD_NETWORK').strip() if id == 'FAIL': print "add_network: failure" return None else: return int(id) def set_network(self, id, options): for key, value in options.items(): if self.request('SET_NETWORK ' + str(id) + ' ' + key + ' ' + value) != 'OK\n': print "set_network: error" def get_network(self, id, key): return self.request('GET_NETWORK ' + str(id) + ' ' + key) def interface_link_quality(self): """Returns the link quality for the interface""" for line in open('/proc/net/wireless'): values = line.split() if values[0] == self.interface + ':': link = int(values[3][:-1]) if link < 1: return 0 quality = math.log(link / math.log(92)) * 100.0 return int(quality) # Execution shouldn't reach this point return None import dbus class DeviceManager: """Creates instances of Unplugged for each wireless network device present in the system when instansiated. DeviceManager also detects devices when they are hotplugged and creates Unplugged instances for them. When a device is removed from the system DeviceManager deletes it's corresponding Unplugged instance.""" def __init__(self): self.managed_devices = {} self.bus = dbus.SystemBus() self.hal_service = self.bus.get_service('org.freedesktop.Hal') self.hal_manager = self.hal_service.get_object('/org/freedesktop/Hal/Manager', 'org.freedesktop.Hal.Manager') devices = self.hal_manager.FindDeviceByCapability('net.80211') for d in devices: hal_device = self.hal_service.get_object(d, 'org.freedesktop.Hal.Device') self.managed_devices[d] = Unplugged(hal_device.GetProperty('net.interface')) self.bus.add_signal_receiver (self.device_added, 'DeviceAdded', 'org.freedesktop.Hal.Manager', 'org.freedesktop.Hal', '/org/freedesktop/Hal/Manager') self.bus.add_signal_receiver (self.device_removed, 'DeviceRemoved', 'org.freedesktop.Hal.Manager', 'org.freedesktop.Hal', '/org/freedesktop/Hal/Manager') def device_added(self, interface, signal_name, service, path, message): [udi] = message.get_args_list () hal_device = self.hal_service.get_object(udi, 'org.freedesktop.Hal.Device') if hal_device.QueryCapability('net.80211'): self.managed_devices[udi] = Unplugged( hal_device.GetProperty('net.interface')) def device_removed(self, interface, signal_name, service, path, message): [udi] = message.get_args_list () if udi in self.managed_devices.keys(): del self.managed_devices['udi'] radio0 = [ "" "GdkP" "\0\0\2e" "\2\1\0\2" "\0\0\0@" "\0\0\0\20" "\0\0\0\20" "\203\0\0\0\0\12\214\214\214W\214\214\214}\214\214\214\237\214\214\214" "\300\214\214\214\341\214\214\214\352\214\214\214\301\214\214\214\240" "\214\214\214~\214\214\214Y\203\0\0\0\0\3\214\214\214\15\214\214\214j" "\214\214\214\323\212\214\214\214\377\4\214\214\214\326\214\214\214m\214" "\214\214\17\214\214\214\240\203\214\214\214\377\10\214\214\214\326\214" "\214\214\251\214\214\214\207\214\214\214f\214\214\214\\\214\214\214\206" "\214\214\214\250\214\214\214\312\203\214\214\214\377\5\214\214\214\251" "\214\214\214=\214\214\214\366\214\214\214\237\214\214\2145\203\0\0\0" "\0\2\214\214\214\2\214\214\214\16\203\0\0\0\0\13\214\214\2142\214\214" "\214\233\213\213\213\364\214\214\214E\0\0\0\0\214\214\214\22\0\0\0\0" "\214\214\214\32\214\214\214\227\214\214\214\312\214\214\214\353\202\214" "\214\214\377\6\214\214\214\354\214\214\214\313\214\214\214\231\214\214" "\214\33\0\0\0\0\214\214\214\20\203\0\0\0\0\2\214\214\214\201\214\214" "\214\376\210\214\214\214\377\2\214\214\214\376\214\214\214\205\204\0" "\0\0\0\14\214\214\214t\214\214\214\377\214\214\214\370\214\214\214\224" "\214\214\214n\214\214\214M\214\214\214A\214\214\214m\214\214\214\223" "\214\214\214\367\214\214\214\377\214\214\214y\204\0\0\0\0\14\214\214" "\214\13\214\214\214y\214\214\214\6\214\214\214\10\214\214\2143\214\214" "\214a\214\214\214U\214\214\2143\214\214\214\10\214\214\214\6\214\214" "\214b\214\214\214\26\206\0\0\0\0\2\214\214\214\214\214\214\214\363\204" "\214\214\214\377\2\214\214\214\363\214\214\214\213\210\0\0\0\0\1\214" "\214\214\251\202\214\214\214\377\2\214\214\214\370\214\214\214\376\202" "\214\214\214\377\1\214\214\214\251\210\0\0\0\0\3\214\214\214:\214\214" "\214\203\214\214\214%\202\0\0\0\0\3\214\214\214%\214\214\214\203\214" "\214\214:\212\0\0\0\0\4\214\214\214\14\214\214\214Z\214\214\214s\214" "\214\214\21\213\0\0\0\0\2\214\214\214\7\214\214\214\351\202\214\214\214" "\377\2\214\214\214\372\214\214\214\33\213\0\0\0\0\1\214\214\214a\202" "\214\214\214\377\1\214\214\214\217\214\0\0\0\0\4\214\214\214\2\214\214" "\214\313\214\214\214\352\214\214\214\20\215\0\0\0\0\2\214\214\214;\214" "\214\214f\207\0\0\0\0" ][0] radio1 = [ "" "GdkP" "\0\0\2e" "\2\1\0\2" "\0\0\0@" "\0\0\0\20" "\0\0\0\20" "\203\0\0\0\0\12\214\214\214W\214\214\214}\214\214\214\237\214\214\214" "\300\214\214\214\341\214\214\214\352\214\214\214\301\214\214\214\240" "\214\214\214~\214\214\214Y\203\0\0\0\0\3\214\214\214\15\214\214\214j" "\214\214\214\323\212\214\214\214\377\4\214\214\214\326\214\214\214m\214" "\214\214\17\214\214\214\240\203\214\214\214\377\10\214\214\214\326\214" "\214\214\251\214\214\214\207\214\214\214f\214\214\214\\\214\214\214\206" "\214\214\214\250\214\214\214\312\203\214\214\214\377\5\214\214\214\251" "\214\214\214=\214\214\214\366\214\214\214\237\214\214\2145\203\0\0\0" "\0\2\214\214\214\2\214\214\214\16\203\0\0\0\0\13\214\214\2142\214\214" "\214\233\213\213\213\364\214\214\214E\0\0\0\0\214\214\214\22\0\0\0\0" "\214\214\214\32\214\214\214\227\214\214\214\312\214\214\214\353\202\214" "\214\214\377\6\214\214\214\354\214\214\214\313\214\214\214\231\214\214" "\214\33\0\0\0\0\214\214\214\20\203\0\0\0\0\2\214\214\214\201\214\214" "\214\376\210\214\214\214\377\2\214\214\214\376\214\214\214\205\204\0" "\0\0\0\14\214\214\214t\214\214\214\377\214\214\214\370\214\214\214\224" "\214\214\214n\214\214\214M\214\214\214A\214\214\214m\214\214\214\223" "\214\214\214\367\214\214\214\377\214\214\214y\204\0\0\0\0\14\214\214" "\214\13\214\214\214y\214\214\214\6\214\214\214\10\214\214\2143\214\214" "\214a\214\214\214U\214\214\2143\214\214\214\10\214\214\214\6\214\214" "\214b\214\214\214\26\206\0\0\0\0\2\214\214\214\214\214\214\214\363\204" "\214\214\214\377\2\214\214\214\363\214\214\214\213\210\0\0\0\0\1\214" "\214\214\251\202\214\214\214\377\2\214\214\214\370\214\214\214\376\202" "\214\214\214\377\1\214\214\214\251\210\0\0\0\0\3\214\214\214:\214\214" "\214\203\214\214\214%\202\0\0\0\0\3\214\214\214%\214\214\214\203\214" "\214\214:\212\0\0\0\0\4\0\0\0\14\0\0\0Z\0\0\0s\0\0\0\21\213\0\0\0\0\2" "\0\0\0\7\0\0\0\351\202\0\0\0\377\2\0\0\0\372\0\0\0\33\213\0\0\0\0\1\0" "\0\0a\202\0\0\0\377\1\0\0\0\217\214\0\0\0\0\4\0\0\0\2\0\0\0\313\0\0\0" "\352\0\0\0\20\215\0\0\0\0\2\0\0\0;\0\0\0f\207\0\0\0\0" ][0] radio2 = [ "" "GdkP" "\0\0\2e" "\2\1\0\2" "\0\0\0@" "\0\0\0\20" "\0\0\0\20" "\203\0\0\0\0\12\214\214\214W\214\214\214}\214\214\214\237\214\214\214" "\300\214\214\214\341\214\214\214\352\214\214\214\301\214\214\214\240" "\214\214\214~\214\214\214Y\203\0\0\0\0\3\214\214\214\15\214\214\214j" "\214\214\214\323\212\214\214\214\377\4\214\214\214\326\214\214\214m\214" "\214\214\17\214\214\214\240\203\214\214\214\377\10\214\214\214\326\214" "\214\214\251\214\214\214\207\214\214\214f\214\214\214\\\214\214\214\206" "\214\214\214\250\214\214\214\312\203\214\214\214\377\5\214\214\214\251" "\214\214\214=\214\214\214\366\214\214\214\237\214\214\2145\203\0\0\0" "\0\2\214\214\214\2\214\214\214\16\203\0\0\0\0\13\214\214\2142\214\214" "\214\233\213\213\213\364\214\214\214E\0\0\0\0\214\214\214\22\0\0\0\0" "\214\214\214\32\214\214\214\227\214\214\214\312\214\214\214\353\202\214" "\214\214\377\6\214\214\214\354\214\214\214\313\214\214\214\231\214\214" "\214\33\0\0\0\0\214\214\214\20\203\0\0\0\0\2\214\214\214\201\214\214" "\214\376\210\214\214\214\377\2\214\214\214\376\214\214\214\205\204\0" "\0\0\0\14\214\214\214t\214\214\214\377\214\214\214\370\214\214\214\224" "\214\214\214n\214\214\214M\214\214\214A\214\214\214m\214\214\214\223" "\214\214\214\367\214\214\214\377\214\214\214y\204\0\0\0\0\14\214\214" "\214\13\214\214\214y\214\214\214\6\0\0\0\10\0\0\0""3\0\0\0a\0\0\0U\0" "\0\0""3\0\0\0\10\214\214\214\6\214\214\214b\214\214\214\26\206\0\0\0" "\0\2\0\0\0\214\0\0\0\363\204\0\0\0\377\2\0\0\0\363\0\0\0\213\210\0\0" "\0\0\1\0\0\0\251\202\0\0\0\377\2\0\0\0\370\0\0\0\376\202\0\0\0\377\1" "\0\0\0\251\210\0\0\0\0\3\0\0\0:\0\0\0\203\0\0\0%\202\0\0\0\0\3\0\0\0" "%\0\0\0\203\0\0\0:\212\0\0\0\0\4\0\0\0\14\0\0\0Z\0\0\0s\0\0\0\21\213" "\0\0\0\0\2\0\0\0\7\0\0\0\351\202\0\0\0\377\2\0\0\0\372\0\0\0\33\213\0" "\0\0\0\1\0\0\0a\202\0\0\0\377\1\0\0\0\217\214\0\0\0\0\4\0\0\0\2\0\0\0" "\313\0\0\0\352\0\0\0\20\215\0\0\0\0\2\0\0\0;\0\0\0f\207\0\0\0\0" ][0] radio3 = [ "" "GdkP" "\0\0\2e" "\2\1\0\2" "\0\0\0@" "\0\0\0\20" "\0\0\0\20" "\203\0\0\0\0\12\214\214\214W\214\214\214}\214\214\214\237\214\214\214" "\300\214\214\214\341\214\214\214\352\214\214\214\301\214\214\214\240" "\214\214\214~\214\214\214Y\203\0\0\0\0\3\214\214\214\15\214\214\214j" "\214\214\214\323\212\214\214\214\377\4\214\214\214\326\214\214\214m\214" "\214\214\17\214\214\214\240\203\214\214\214\377\10\214\214\214\326\214" "\214\214\251\214\214\214\207\214\214\214f\214\214\214\\\214\214\214\206" "\214\214\214\250\214\214\214\312\203\214\214\214\377\5\214\214\214\251" "\214\214\214=\214\214\214\366\214\214\214\237\214\214\2145\203\0\0\0" "\0\2\0\0\0\2\0\0\0\16\203\0\0\0\0\13\214\214\2142\214\214\214\233\213" "\213\213\364\214\214\214E\0\0\0\0\214\214\214\22\0\0\0\0\0\0\0\32\0\0" "\0\227\0\0\0\312\0\0\0\353\202\0\0\0\377\6\0\0\0\354\0\0\0\313\0\0\0" "\231\0\0\0\33\0\0\0\0\214\214\214\20\203\0\0\0\0\2\0\0\0\201\0\0\0\376" "\210\0\0\0\377\2\0\0\0\376\0\0\0\205\204\0\0\0\0\14\0\0\0t\0\0\0\377" "\0\0\0\370\0\0\0\224\0\0\0n\0\0\0M\0\0\0A\0\0\0m\0\0\0\223\0\0\0\367" "\0\0\0\377\0\0\0y\204\0\0\0\0\14\0\0\0\13\0\0\0y\0\0\0\6\0\0\0\10\0\0" "\0""3\0\0\0a\0\0\0U\0\0\0""3\0\0\0\10\0\0\0\6\0\0\0b\0\0\0\26\206\0\0" "\0\0\2\0\0\0\214\0\0\0\363\204\0\0\0\377\2\0\0\0\363\0\0\0\213\210\0" "\0\0\0\1\0\0\0\251\202\0\0\0\377\2\0\0\0\370\0\0\0\376\202\0\0\0\377" "\1\0\0\0\251\210\0\0\0\0\3\0\0\0:\0\0\0\203\0\0\0%\202\0\0\0\0\3\0\0" "\0%\0\0\0\203\0\0\0:\212\0\0\0\0\4\0\0\0\14\0\0\0Z\0\0\0s\0\0\0\21\213" "\0\0\0\0\2\0\0\0\7\0\0\0\351\202\0\0\0\377\2\0\0\0\372\0\0\0\33\213\0" "\0\0\0\1\0\0\0a\202\0\0\0\377\1\0\0\0\217\214\0\0\0\0\4\0\0\0\2\0\0\0" "\313\0\0\0\352\0\0\0\20\215\0\0\0\0\2\0\0\0;\0\0\0f\207\0\0\0\0" ][0] radio4 = [ "" "GdkP" "\0\0\2e" "\2\1\0\2" "\0\0\0@" "\0\0\0\20" "\0\0\0\20" "\203\0\0\0\0\12\0\0\0W\0\0\0}\0\0\0\237\0\0\0\300\0\0\0\341\0\0\0\352" "\0\0\0\301\0\0\0\240\0\0\0~\0\0\0Y\203\0\0\0\0\3\0\0\0\15\0\0\0j\0\0" "\0\323\212\0\0\0\377\4\0\0\0\326\0\0\0m\0\0\0\17\0\0\0\240\203\0\0\0" "\377\10\0\0\0\326\0\0\0\251\0\0\0\207\0\0\0f\0\0\0\\\0\0\0\206\0\0\0" "\250\0\0\0\312\203\0\0\0\377\5\0\0\0\251\0\0\0=\0\0\0\366\0\0\0\237\0" "\0\0""5\203\0\0\0\0\2\0\0\0\2\0\0\0\16\203\0\0\0\0\13\0\0\0""2\0\0\0" "\233\0\0\0\364\0\0\0E\0\0\0\0\0\0\0\22\0\0\0\0\0\0\0\32\0\0\0\227\0\0" "\0\312\0\0\0\353\202\0\0\0\377\6\0\0\0\354\0\0\0\313\0\0\0\231\0\0\0" "\33\0\0\0\0\0\0\0\20\203\0\0\0\0\2\0\0\0\201\0\0\0\376\210\0\0\0\377" "\2\0\0\0\376\0\0\0\205\204\0\0\0\0\14\0\0\0t\0\0\0\377\0\0\0\370\0\0" "\0\224\0\0\0n\0\0\0M\0\0\0A\0\0\0m\0\0\0\223\0\0\0\367\0\0\0\377\0\0" "\0y\204\0\0\0\0\14\0\0\0\13\0\0\0y\0\0\0\6\0\0\0\10\0\0\0""3\0\0\0a\0" "\0\0U\0\0\0""3\0\0\0\10\0\0\0\6\0\0\0b\0\0\0\26\206\0\0\0\0\2\0\0\0\214" "\0\0\0\363\204\0\0\0\377\2\0\0\0\363\0\0\0\213\210\0\0\0\0\1\0\0\0\251" "\202\0\0\0\377\2\0\0\0\370\0\0\0\376\202\0\0\0\377\1\0\0\0\251\210\0" "\0\0\0\3\0\0\0:\0\0\0\203\0\0\0%\202\0\0\0\0\3\0\0\0%\0\0\0\203\0\0\0" ":\212\0\0\0\0\4\0\0\0\14\0\0\0Z\0\0\0s\0\0\0\21\213\0\0\0\0\2\0\0\0\7" "\0\0\0\351\202\0\0\0\377\2\0\0\0\372\0\0\0\33\213\0\0\0\0\1\0\0\0a\202" "\0\0\0\377\1\0\0\0\217\214\0\0\0\0\4\0\0\0\2\0\0\0\313\0\0\0\352\0\0" "\0\20\215\0\0\0\0\2\0\0\0;\0\0\0f\207\0\0\0\0" ][0] pixbuf = lambda d : gtk.gdk.pixbuf_new_from_inline(len(d), d, False) radio0p = pixbuf(radio0) radio1p = pixbuf(radio1) radio2p = pixbuf(radio2) radio3p = pixbuf(radio3) radio4p = pixbuf(radio4) if __name__ == "__main__": DeviceManager() gtk.main()