Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Schampijer <simon@schampijer.de>2010-09-22 10:40:38 (GMT)
committer Simon Schampijer <simon@schampijer.de>2010-09-22 10:40:38 (GMT)
commit824ac2a6a6dddf36c9f795cf0249eb5bebe60f54 (patch)
tree165a6a7519226c210d302225576bad26d3d599cf
parentf76678cbbbaa91a83575b59fdfd31abd74610fab (diff)
Add default Ad-hoc networks #9845
This patch adds three default Ad-hoc networks, for channel 1, 6 and 11. They are represented with designated icons in the neighborhood view. This will mimic the mesh behavior on devices where mesh hardware is not available and make the "under a tree"-scenario possible in those cases. If Sugar sees no "known" network when it starts, it does autoconnect to an Ad-hoc network.
-rw-r--r--data/sugar.schemas.in13
-rw-r--r--extensions/deviceicon/network.py119
-rw-r--r--src/jarabe/desktop/meshbox.py298
-rw-r--r--src/jarabe/model/Makefile.am1
-rw-r--r--src/jarabe/model/network.py40
5 files changed, 339 insertions, 132 deletions
diff --git a/data/sugar.schemas.in b/data/sugar.schemas.in
index e5b1e88..454375a 100644
--- a/data/sugar.schemas.in
+++ b/data/sugar.schemas.in
@@ -271,6 +271,19 @@
</locale>
</schema>
+ <schema>
+ <key>/schemas/desktop/sugar/network/adhoc</key>
+ <applyto>/desktop/sugar/network/adhoc</applyto>
+ <owner>sugar</owner>
+ <type>bool</type>
+ <default>true</default>
+ <locale name="C">
+ <short>Show Sugar Ad-hoc networks</short>
+ <long>If TRUE, Sugar will show default Ad-hoc networks for
+ channel 1,6 and 11. If Sugar sees no "known" network when
+ it starts, it does autoconnect to an Ad-hoc network.</long>
+ </locale>
+ </schema>
</schemalist>
</gconfschemafile>
diff --git a/extensions/deviceicon/network.py b/extensions/deviceicon/network.py
index f194a19..12ea9f6 100644
--- a/extensions/deviceicon/network.py
+++ b/extensions/deviceicon/network.py
@@ -64,24 +64,15 @@ _GSM_STATE_CONNECTING = 2
_GSM_STATE_CONNECTED = 3
_GSM_STATE_NEED_AUTH = 4
-def frequency_to_channel(frequency):
- ftoc = { 2412: 1, 2417: 2, 2422: 3, 2427: 4,
- 2432: 5, 2437: 6, 2442: 7, 2447: 8,
- 2452: 9, 2457: 10, 2462: 11, 2467: 12,
- 2472: 13}
- return ftoc[frequency]
-
class WirelessPalette(Palette):
__gtype_name__ = 'SugarWirelessPalette'
__gsignals__ = {
'deactivate-connection' : (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE, ([])),
- 'create-connection' : (gobject.SIGNAL_RUN_FIRST,
- gobject.TYPE_NONE, ([])),
+ gobject.TYPE_NONE, ([]))
}
- def __init__(self, primary_text, can_create=True):
+ def __init__(self, primary_text):
Palette.__init__(self, label=primary_text)
self._disconnect_item = None
@@ -112,12 +103,6 @@ class WirelessPalette(Palette):
self._disconnect_item.connect('activate', self.__disconnect_activate_cb)
self.menu.append(self._disconnect_item)
- if can_create:
- self._adhoc_item = gtk.MenuItem(_('Create new wireless network'))
- self._adhoc_item.connect('activate', self.__adhoc_activate_cb)
- self.menu.append(self._adhoc_item)
- self._adhoc_item.show()
-
def set_connecting(self):
self.props.secondary_text = _('Connecting...')
@@ -144,12 +129,9 @@ class WirelessPalette(Palette):
def __disconnect_activate_cb(self, menuitem):
self.emit('deactivate-connection')
- def __adhoc_activate_cb(self, menuitem):
- self.emit('create-connection')
-
def _set_frequency(self, frequency):
try:
- channel = frequency_to_channel(frequency)
+ channel = network.frequency_to_channel(frequency)
except KeyError:
channel = 0
self._set_channel(channel)
@@ -312,7 +294,6 @@ class GsmPalette(Palette):
class WirelessDeviceView(ToolButton):
- _ICON_NAME = 'network-wireless'
FRAME_POSITION_RELATIVE = 302
def __init__(self, device):
@@ -331,7 +312,7 @@ class WirelessDeviceView(ToolButton):
self._active_ap_op = None
self._icon = PulsingIcon()
- self._icon.props.icon_name = get_icon_state(self._ICON_NAME, 0)
+ self._icon.props.icon_name = get_icon_state('network-wireless', 0)
self._inactive_color = xocolor.XoColor( \
"%s,%s" % (style.COLOR_BUTTON_GREY.get_svg(),
style.COLOR_TRANSPARENT.get_svg()))
@@ -345,8 +326,6 @@ class WirelessDeviceView(ToolButton):
self._palette = WirelessPalette(self._name)
self._palette.connect('deactivate-connection',
self.__deactivate_connection_cb)
- self._palette.connect('create-connection',
- self.__create_connection_cb)
self.set_palette(self._palette)
self._palette.set_group_id('frame')
@@ -415,11 +394,6 @@ class WirelessDeviceView(ToolButton):
def __ap_properties_changed_cb(self, properties):
self._update_properties(properties)
- def _name_encodes_colors(self):
- """Match #XXXXXX,#YYYYYY at the end of the network name"""
- return self._name[-7] == '#' and self._name[-8] == ',' \
- and self._name[-15] == '#'
-
def _update_properties(self, properties):
if 'Mode' in properties:
self._mode = properties['Mode']
@@ -435,11 +409,9 @@ class WirelessDeviceView(ToolButton):
self._frequency = properties['Frequency']
if self._color == None:
- if self._mode == network.NM_802_11_MODE_ADHOC \
- and self._name_encodes_colors():
- encoded_color = self._name.split("#", 1)
- if len(encoded_color) == 2:
- self._color = xocolor.XoColor('#' + encoded_color[1])
+ if self._mode == network.NM_802_11_MODE_ADHOC and \
+ self._name.startswith('Ad-hoc Network'):
+ self._color = profile.get_color()
else:
sh = sha.new()
data = self._name + hex(self._flags)
@@ -475,14 +447,27 @@ class WirelessDeviceView(ToolButton):
else:
state = network.DEVICE_STATE_UNKNOWN
- if state == network.DEVICE_STATE_ACTIVATED:
- icon_name = '%s-connected' % self._ICON_NAME
- else:
- icon_name = self._ICON_NAME
+ if self._mode != network.NM_802_11_MODE_ADHOC and \
+ self._name.startswith('Ad-hoc Network') == False:
+ if state == network.DEVICE_STATE_ACTIVATED:
+ icon_name = '%s-connected' % 'network-wireless'
+ else:
+ icon_name = 'network-wireless'
- icon_name = get_icon_state(icon_name, self._strength)
- if icon_name:
- self._icon.props.icon_name = icon_name
+ icon_name = get_icon_state(icon_name, self._strength)
+ if icon_name:
+ self._icon.props.icon_name = icon_name
+ else:
+ try:
+ channel = network.frequency_to_channel(self._frequency)
+ except KeyError:
+ channel = 1
+ if state == network.DEVICE_STATE_ACTIVATED:
+ self._icon.props.icon_name = 'network-adhoc-%s-connected' \
+ % channel
+ else:
+ self._icon.props.icon_name = 'network-adhoc-%s' % channel
+ self._icon.props.base_color = profile.get_color()
if state == network.DEVICE_STATE_PREPARE or \
state == network.DEVICE_STATE_CONFIG or \
@@ -526,54 +511,6 @@ class WirelessDeviceView(ToolButton):
netmgr.DeactivateConnection(conn_o)
break
- def __create_connection_cb(self, palette, data=None):
- """Create an 802.11 IBSS network.
-
- The user's color is encoded at the end of the network name. The network
- name is truncated so that it does not exceed the 32 byte SSID limit.
- """
- client = gconf.client_get_default()
- nick = client.get_string('/desktop/sugar/user/nick').decode('utf-8')
- color = client.get_string('/desktop/sugar/user/color')
- color_suffix = ' %s' % color
-
- format = _('%s\'s network').encode('utf-8')
- extra_length = (len(format) - len('%s')) + len(color_suffix)
- name_limit = 32 - extra_length
-
- # truncate the nick and use a regex to drop any partial characters
- # at the end
- nick = nick.encode('utf-8')[:name_limit]
- pattern = "([\xf6-\xf7][\x80-\xbf]{0,2}|[\xe0-\xef][\x80-\xbf]{0,1}|[\xc0-\xdf])$"
- nick = re.sub(pattern, '', nick)
-
- connection_name = format % nick
- connection_name += color_suffix
-
- connection = network.find_connection_by_ssid(connection_name)
- if connection is None:
- settings = Settings()
- settings.connection.id = 'Auto ' + connection_name
- uuid = settings.connection.uuid = unique_id()
- settings.connection.type = '802-11-wireless'
- settings.wireless.ssid = dbus.ByteArray(connection_name)
- settings.wireless.band = 'bg'
- settings.wireless.mode = 'adhoc'
- settings.ip4_config = IP4Config()
- settings.ip4_config.method = 'link-local'
-
- connection = network.add_connection(uuid, settings)
-
- obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
- netmgr = dbus.Interface(obj, _NM_IFACE)
-
- netmgr.ActivateConnection(network.SETTINGS_SERVICE,
- connection.path,
- self._device.object_path,
- '/',
- reply_handler=self.__activate_reply_cb,
- error_handler=self.__activate_error_cb)
-
def __activate_reply_cb(self, connection):
logging.debug('Network created: %s', connection)
@@ -604,7 +541,7 @@ class OlpcMeshDeviceView(ToolButton):
self._icon.show()
self.set_palette_invoker(FrameWidgetInvoker(self))
- self._palette = WirelessPalette(_("Mesh Network"), can_create=False)
+ self._palette = WirelessPalette(_("Mesh Network"))
self._palette.connect('deactivate-connection',
self.__deactivate_connection)
self.set_palette(self._palette)
diff --git a/src/jarabe/desktop/meshbox.py b/src/jarabe/desktop/meshbox.py
index a3965f7..764aa2e 100644
--- a/src/jarabe/desktop/meshbox.py
+++ b/src/jarabe/desktop/meshbox.py
@@ -1,6 +1,6 @@
# Copyright (C) 2006-2007 Red Hat, Inc.
# Copyright (C) 2009 Tomeu Vizoso, Simon Schampijer
-# Copyright (C) 2009 One Laptop per Child
+# Copyright (C) 2009-2010 One Laptop per Child
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@ import dbus
import hippo
import gobject
import gtk
+import gconf
from sugar.graphics.icon import CanvasIcon, Icon
from sugar.graphics.xocolor import XoColor
@@ -54,6 +55,7 @@ from jarabe.model.network import WirelessSecurity
from jarabe.model.network import AccessPoint
from jarabe.model.network import OlpcMesh as OlpcMeshSettings
from jarabe.model.olpcmesh import OlpcMeshManager
+from jarabe.model.adhoc import get_adhoc_manager_instance
_NM_SERVICE = 'org.freedesktop.NetworkManager'
_NM_IFACE = 'org.freedesktop.NetworkManager'
@@ -89,11 +91,9 @@ class WirelessNetworkView(CanvasPulsingIcon):
self._device_state = None
self._color = None
- if self._mode == network.NM_802_11_MODE_ADHOC \
- and self._name_encodes_colors():
- encoded_color = self._name.split("#", 1)
- if len(encoded_color) == 2:
- self._color = xocolor.XoColor('#' + encoded_color[1])
+ if self._mode == network.NM_802_11_MODE_ADHOC and \
+ network.is_sugar_adhoc_network(self._name):
+ self._color = profile.get_color()
else:
sh = sha.new()
data = self._name + hex(self._flags)
@@ -137,11 +137,6 @@ class WirelessNetworkView(CanvasPulsingIcon):
path=self._device.object_path,
dbus_interface=_NM_WIRELESS_IFACE)
- def _name_encodes_colors(self):
- """Match #XXXXXX,#YYYYYY at the end of the network name"""
- return self._name[-7] == '#' and self._name[-8] == ',' \
- and self._name[-15] == '#'
-
def _create_palette(self):
icon_name = get_icon_state(_AP_ICON_NAME, self._strength)
self._palette_icon = Icon(icon_name=icon_name,
@@ -214,21 +209,32 @@ class WirelessNetworkView(CanvasPulsingIcon):
else:
state = network.DEVICE_STATE_UNKNOWN
- if state == network.DEVICE_STATE_ACTIVATED:
- connection = network.find_connection_by_ssid(self._name)
- if connection:
- if self._mode == network.NM_802_11_MODE_INFRA:
- connection.set_connected()
-
- icon_name = '%s-connected' % _AP_ICON_NAME
- else:
- icon_name = _AP_ICON_NAME
-
- icon_name = get_icon_state(icon_name, self._strength)
- if icon_name:
+ if self._mode == network.NM_802_11_MODE_ADHOC and \
+ network.is_sugar_adhoc_network(self._name):
+ channel = max([1] + [ap.channel for ap in
+ self._access_points.values()])
+ if state == network.DEVICE_STATE_ACTIVATED:
+ icon_name = 'network-adhoc-%s-connected' % channel
+ else:
+ icon_name = 'network-adhoc-%s' % channel
self.props.icon_name = icon_name
icon = self._palette.props.icon
icon.props.icon_name = icon_name
+ else:
+ if state == network.DEVICE_STATE_ACTIVATED:
+ connection = network.find_connection_by_ssid(self._name)
+ if connection:
+ if self._mode == network.NM_802_11_MODE_INFRA:
+ connection.set_connected()
+ icon_name = '%s-connected' % _AP_ICON_NAME
+ else:
+ icon_name = _AP_ICON_NAME
+
+ icon_name = get_icon_state(icon_name, self._strength)
+ if icon_name:
+ self.props.icon_name = icon_name
+ icon = self._palette.props.icon
+ icon.props.icon_name = icon_name
if state == network.DEVICE_STATE_PREPARE or \
state == network.DEVICE_STATE_CONFIG or \
@@ -260,12 +266,16 @@ class WirelessNetworkView(CanvasPulsingIcon):
self.props.base_color = self._color
def _update_badge(self):
- if network.find_connection_by_ssid(self._name) is not None:
- self.props.badge_name = "emblem-favorite"
- self._palette_icon.props.badge_name = "emblem-favorite"
- elif self._flags == network.NM_802_11_AP_FLAGS_PRIVACY:
- self.props.badge_name = "emblem-locked"
- self._palette_icon.props.badge_name = "emblem-locked"
+ if self._mode != network.NM_802_11_MODE_ADHOC:
+ if network.find_connection_by_ssid(self._name) is not None:
+ self.props.badge_name = "emblem-favorite"
+ self._palette_icon.props.badge_name = "emblem-favorite"
+ elif self._flags == network.NM_802_11_AP_FLAGS_PRIVACY:
+ self.props.badge_name = "emblem-locked"
+ self._palette_icon.props.badge_name = "emblem-locked"
+ else:
+ self.props.badge_name = None
+ self._palette_icon.props.badge_name = None
else:
self.props.badge_name = None
self._palette_icon.props.badge_name = None
@@ -469,6 +479,140 @@ class WirelessNetworkView(CanvasPulsingIcon):
dbus_interface=_NM_WIRELESS_IFACE)
+class SugarAdhocView(CanvasPulsingIcon):
+ """To mimic the mesh behavior on devices where mesh hardware is
+ not available we support the creation of an Ad-hoc network on
+ three channels 1, 6, 11. This is the class for an icon
+ representing a channel in the neighborhood view.
+
+ """
+
+ _ICON_NAME = 'network-adhoc-'
+ _NAME = 'Ad-hoc Network '
+
+ def __init__(self, channel):
+ CanvasPulsingIcon.__init__(self,
+ icon_name=self._ICON_NAME + str(channel),
+ size=style.STANDARD_ICON_SIZE, cache=True)
+ self._bus = dbus.SystemBus()
+ self._channel = channel
+ self._disconnect_item = None
+ self._connect_item = None
+ self._palette_icon = None
+ self._greyed_out = False
+
+ get_adhoc_manager_instance().connect('members-changed',
+ self.__members_changed_cb)
+ get_adhoc_manager_instance().connect('state-changed',
+ self.__state_changed_cb)
+
+ self.connect('button-release-event', self.__button_release_event_cb)
+
+ pulse_color = XoColor('%s,%s' % (style.COLOR_BUTTON_GREY.get_svg(),
+ style.COLOR_TRANSPARENT.get_svg()))
+ self.props.pulse_color = pulse_color
+ self._state_color = XoColor('%s,%s' % \
+ (profile.get_color().get_stroke_color(),
+ style.COLOR_TRANSPARENT.get_svg()))
+ self.props.base_color = self._state_color
+ self._palette = self._create_palette()
+ self.set_palette(self._palette)
+ self._palette_icon.props.xo_color = self._state_color
+
+ def _create_palette(self):
+ self._palette_icon = Icon( \
+ icon_name=self._ICON_NAME + str(self._channel),
+ icon_size=style.STANDARD_ICON_SIZE)
+
+ palette_ = palette.Palette(_("Ad-hoc Network %d") % self._channel,
+ icon=self._palette_icon)
+
+ self._connect_item = MenuItem(_('Connect'), 'dialog-ok')
+ self._connect_item.connect('activate', self.__connect_activate_cb)
+ palette_.menu.append(self._connect_item)
+
+ self._disconnect_item = MenuItem(_('Disconnect'), 'media-eject')
+ self._disconnect_item.connect('activate',
+ self.__disconnect_activate_cb)
+ palette_.menu.append(self._disconnect_item)
+
+ return palette_
+
+ def __button_release_event_cb(self, icon, event):
+ get_adhoc_manager_instance().activate_channel(self._channel)
+
+ def __connect_activate_cb(self, icon):
+ get_adhoc_manager_instance().activate_channel(self._channel)
+
+ def __disconnect_activate_cb(self, icon):
+ get_adhoc_manager_instance().deactivate_active_channel()
+
+ def __state_changed_cb(self, adhoc_manager, channel, device_state):
+ if self._channel == channel:
+ state = device_state
+ else:
+ state = network.DEVICE_STATE_UNKNOWN
+
+ if state == network.DEVICE_STATE_ACTIVATED:
+ icon_name = '%s-connected' % (self._ICON_NAME + str(self._channel))
+ else:
+ icon_name = self._ICON_NAME + str(self._channel)
+
+ self.props.base_color = self._state_color
+ self._palette_icon.props.xo_color = self._state_color
+
+ if icon_name is not None:
+ self.props.icon_name = icon_name
+ icon = self._palette.props.icon
+ icon.props.icon_name = icon_name
+
+ if state in [network.DEVICE_STATE_PREPARE,
+ network.DEVICE_STATE_CONFIG,
+ network.DEVICE_STATE_NEED_AUTH,
+ network.DEVICE_STATE_IP_CONFIG]:
+ if self._disconnect_item:
+ self._disconnect_item.show()
+ self._connect_item.hide()
+ self._palette.props.secondary_text = _('Connecting...')
+ self.props.pulsing = True
+ elif state == network.DEVICE_STATE_ACTIVATED:
+ if self._disconnect_item:
+ self._disconnect_item.show()
+ self._connect_item.hide()
+ self._palette.props.secondary_text = _('Connected')
+ self.props.pulsing = False
+ else:
+ if self._disconnect_item:
+ self._disconnect_item.hide()
+ self._connect_item.show()
+ self._palette.props.secondary_text = None
+ self.props.pulsing = False
+
+ def _update_color(self):
+ if self._greyed_out:
+ self.props.base_color = XoColor('#D5D5D5,#D5D5D5')
+ else:
+ self.props.base_color = self._state_color
+
+ def __members_changed_cb(self, adhoc_manager, channel, has_members):
+ if channel == self._channel:
+ if has_members == True:
+ self._state_color = profile.get_color()
+ self.props.base_color = self._state_color
+ self._palette_icon.props.xo_color = self._state_color
+ else:
+ color = '%s,%s' % (profile.get_color().get_stroke_color(),
+ style.COLOR_TRANSPARENT.get_svg())
+ self._state_color = XoColor(color)
+ self.props.base_color = self._state_color
+ self._palette_icon.props.xo_color = self._state_color
+
+ def set_filter(self, query):
+ name = self._NAME + str(self._channel)
+ self._greyed_out = name.lower().find(query) == -1
+ self._update_color()
+
+
class OlpcMeshView(CanvasPulsingIcon):
def __init__(self, mesh_mgr, channel):
CanvasPulsingIcon.__init__(self, icon_name=_OLPC_MESH_ICON_NAME,
@@ -797,13 +941,19 @@ class MeshToolbar(gtk.Toolbar):
return False
-class DeviceObserver(object):
- def __init__(self, box, device):
- self._box = box
+class DeviceObserver(gobject.GObject):
+ __gsignals__ = {
+ 'access-point-added': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([gobject.TYPE_PYOBJECT])),
+ 'access-point-removed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
+ ([gobject.TYPE_PYOBJECT]))
+ }
+ def __init__(self, device):
+ gobject.GObject.__init__(self)
self._bus = dbus.SystemBus()
- self._device = device
+ self.device = device
- wireless = dbus.Interface(self._device, _NM_WIRELESS_IFACE)
+ wireless = dbus.Interface(device, _NM_WIRELESS_IFACE)
wireless.GetAccessPoints(reply_handler=self._get_access_points_reply_cb,
error_handler=self._get_access_points_error_cb)
@@ -819,30 +969,33 @@ class DeviceObserver(object):
def _get_access_points_reply_cb(self, access_points_o):
for ap_o in access_points_o:
ap = self._bus.get_object(_NM_SERVICE, ap_o)
- self._box.add_access_point(self._device, ap)
+ self.emit('access-point-added', ap)
def _get_access_points_error_cb(self, err):
logging.error('Failed to get access points: %s', err)
def __access_point_added_cb(self, access_point_o):
ap = self._bus.get_object(_NM_SERVICE, access_point_o)
- self._box.add_access_point(self._device, ap)
+ self.emit('access-point-added', ap)
def __access_point_removed_cb(self, access_point_o):
- self._box.remove_access_point(access_point_o)
+ self.emit('access-point-removed', access_point_o)
def disconnect(self):
self._bus.remove_signal_receiver(self.__access_point_added_cb,
signal_name='AccessPointAdded',
- path=self._device.object_path,
+ path=self.device.object_path,
dbus_interface=_NM_WIRELESS_IFACE)
self._bus.remove_signal_receiver(self.__access_point_removed_cb,
signal_name='AccessPointRemoved',
- path=self._device.object_path,
+ path=self.device.object_path,
dbus_interface=_NM_WIRELESS_IFACE)
class NetworkManagerObserver(object):
+
+ _SHOW_ADHOC_GCONF_KEY = '/desktop/sugar/network/adhoc'
+
def __init__(self, box):
self._box = box
self._bus = dbus.SystemBus()
@@ -850,6 +1003,9 @@ class NetworkManagerObserver(object):
self._netmgr = None
self._olpc_mesh_device_o = None
+ client = gconf.client_get_default()
+ self._have_adhoc_networks = client.get_bool(self._SHOW_ADHOC_GCONF_KEY)
+
def listen(self):
try:
obj = self._bus.get_object(_NM_SERVICE, _NM_PATH)
@@ -867,6 +1023,9 @@ class NetworkManagerObserver(object):
self._bus.add_signal_receiver(self.__device_removed_cb,
signal_name='DeviceRemoved',
dbus_interface=_NM_IFACE)
+ self._bus.add_signal_receiver(self.__properties_changed_cb,
+ signal_name='PropertiesChanged',
+ dbus_interface=_NM_IFACE)
settings = network.get_settings()
if settings is not None:
@@ -909,7 +1068,13 @@ class NetworkManagerObserver(object):
device_type = props.Get(_NM_DEVICE_IFACE, 'DeviceType')
if device_type == network.DEVICE_TYPE_802_11_WIRELESS:
- self._devices[device_o] = DeviceObserver(self._box, device)
+ self._devices[device_o] = DeviceObserver(device)
+ self._devices[device_o].connect('access-point-added',
+ self.__ap_added_cb)
+ self._devices[device_o].connect('access-point-removed',
+ self.__ap_removed_cb)
+ if self._have_adhoc_networks:
+ self._box.add_adhoc_networks(device)
elif device_type == network.DEVICE_TYPE_802_11_OLPC_MESH:
self._olpc_mesh_device_o = device_o
self._box.enable_olpc_mesh(device)
@@ -925,11 +1090,29 @@ class NetworkManagerObserver(object):
observer = self._devices[device_o]
observer.disconnect()
del self._devices[device_o]
+ if self._have_adhoc_networks:
+ self._box.remove_adhoc_networks()
return
if self._olpc_mesh_device_o == device_o:
self._box.disable_olpc_mesh(device_o)
+ def __ap_added_cb(self, device_observer, access_point):
+ self._box.add_access_point(device_observer.device, access_point)
+
+ def __ap_removed_cb(self, device_observer, access_point_o):
+ self._box.remove_access_point(access_point_o)
+
+ def __properties_changed_cb(self, properties):
+ if 'WirelessHardwareEnabled' in properties:
+ if properties['WirelessHardwareEnabled']:
+ if not self._have_adhoc_networks:
+ self._box.remove_adhoc_networks()
+ elif properties['WirelessHardwareEnabled']:
+ for device in self._devices:
+ if self._have_adhoc_networks:
+ self._box.add_adhoc_networks(device)
+
class MeshBox(gtk.VBox):
__gtype_name__ = 'SugarMeshBox'
@@ -940,6 +1123,8 @@ class MeshBox(gtk.VBox):
gobject.GObject.__init__(self)
self.wireless_networks = {}
+ self._adhoc_manager = None
+ self._adhoc_networks = []
self._model = neighborhood.get_model()
self._buddies = {}
@@ -1097,6 +1282,15 @@ class MeshBox(gtk.VBox):
ap.disconnect()
return
+ if self._adhoc_manager is not None and \
+ network.is_sugar_adhoc_network(ap.name) and \
+ ap.mode == network.NM_802_11_MODE_ADHOC:
+ if old_hash is None: # new Ad-hoc network finished initializing
+ self._adhoc_manager.add_access_point(ap)
+ # we are called as well in other cases but we do not need to
+ # act here as we don't display signal strength for Ad-hoc networks
+ return
+
if old_hash is None: # new AP finished initializing
self._add_ap_to_network(ap)
return
@@ -1119,6 +1313,11 @@ class MeshBox(gtk.VBox):
ap.initialize()
def remove_access_point(self, ap_o):
+ if self._adhoc_manager is not None:
+ if self._adhoc_manager.is_sugar_adhoc_access_point(ap_o):
+ self._adhoc_manager.remove_access_point(ap_o)
+ return
+
# we don't keep an index of ap object path to network, but since
# we'll only ever have a handful of networks, just try them all...
for net in self.wireless_networks.values():
@@ -1135,6 +1334,25 @@ class MeshBox(gtk.VBox):
# it (e.g. olpc-mesh adhoc network)
logging.debug('Can not remove access point %s' % ap_o)
+ def add_adhoc_networks(self, device):
+ if self._adhoc_manager is None:
+ self._adhoc_manager = get_adhoc_manager_instance()
+ self._adhoc_manager.start_listening(device)
+ self._add_adhoc_network_icon(1)
+ self._add_adhoc_network_icon(6)
+ self._add_adhoc_network_icon(11)
+ self._adhoc_manager.autoconnect()
+
+ def remove_adhoc_networks(self):
+ for icon in self._adhoc_networks:
+ self._layout.remove(icon)
+ self._adhoc_networks = []
+
+ def _add_adhoc_network_icon(self, channel):
+ icon = SugarAdhocView(channel)
+ self._layout.add(icon)
+ self._adhoc_networks.append(icon)
+
def _add_olpc_mesh_icon(self, mesh_mgr, channel):
icon = OlpcMeshView(mesh_mgr, channel)
self._layout.add(icon)
diff --git a/src/jarabe/model/Makefile.am b/src/jarabe/model/Makefile.am
index 18d44da..1df2cde 100644
--- a/src/jarabe/model/Makefile.am
+++ b/src/jarabe/model/Makefile.am
@@ -1,5 +1,6 @@
sugardir = $(pythondir)/jarabe/model
sugar_PYTHON = \
+ adhoc.py \
__init__.py \
buddy.py \
bundleregistry.py \
diff --git a/src/jarabe/model/network.py b/src/jarabe/model/network.py
index 8af2591..f0297c9 100644
--- a/src/jarabe/model/network.py
+++ b/src/jarabe/model/network.py
@@ -1,6 +1,6 @@
# Copyright (C) 2008 Red Hat, Inc.
# Copyright (C) 2009 Tomeu Vizoso, Simon Schampijer
-# Copyright (C) 2009 One Laptop per Child
+# Copyright (C) 2009-2010 One Laptop per Child
# Copyright (C) 2009 Paraguay Educa, Martin Abente
#
# This program is free software; you can redistribute it and/or modify
@@ -100,6 +100,38 @@ GSM_PUK_PATH = '/desktop/sugar/network/gsm/puk'
_nm_settings = None
_conn_counter = 0
+def frequency_to_channel(frequency):
+ """Returns the channel matching a given radio channel frequency. If a
+ frequency is not in the dictionary channel 1 will be returned.
+
+ Keyword arguments:
+ frequency -- The radio channel frequency in MHz.
+
+ Return: Channel
+
+ """
+ ftoc = {2412: 1, 2417: 2, 2422: 3, 2427: 4,
+ 2432: 5, 2437: 6, 2442: 7, 2447: 8,
+ 2452: 9, 2457: 10, 2462: 11, 2467: 12,
+ 2472: 13}
+ if frequency not in ftoc:
+ logging.warning("The frequency %s can not be mapped to a channel, " \
+ "defaulting to channel 1.", frequency)
+ return 1
+ return ftoc[frequency]
+
+def is_sugar_adhoc_network(ssid):
+ """Checks whether an access point is a sugar Ad-hoc network.
+
+ Keyword arguments:
+ ssid -- Ssid of the access point.
+
+ Return: Boolean
+
+ """
+ return ssid.startswith('Ad-hoc Network')
+
+
class WirelessSecurity(object):
def __init__(self):
self.key_mgmt = None
@@ -127,6 +159,7 @@ class Wireless(object):
self.security = None
self.mode = None
self.band = None
+ self.channel = None
def get_dict(self):
wireless = {'ssid': self.ssid}
@@ -136,6 +169,8 @@ class Wireless(object):
wireless['mode'] = self.mode
if self.band:
wireless['band'] = self.band
+ if self.channel:
+ wireless['channel'] = self.channel
return wireless
class OlpcMesh(object):
@@ -509,6 +544,7 @@ class AccessPoint(gobject.GObject):
self.wpa_flags = 0
self.rsn_flags = 0
self.mode = 0
+ self.channel = 0
def initialize(self):
model_props = dbus.Interface(self.model, dbus.PROPERTIES_IFACE)
@@ -577,6 +613,8 @@ class AccessPoint(gobject.GObject):
self.rsn_flags = properties['RsnFlags']
if 'Mode' in properties:
self.mode = properties['Mode']
+ if 'Frequency' in properties:
+ self.channel = frequency_to_channel(properties['Frequency'])
self._initialized = True
self.emit('props-changed', old_hash)