Line 262: |
Line 262: |
| [[Image:stream-tube-in-annotate-activity.jpg | How annotate's stream tube will be used]] | | [[Image:stream-tube-in-annotate-activity.jpg | How annotate's stream tube will be used]] |
| | | |
− | Notice that the stream tube exists as a complement to the [http://en.wikipedia.org/wiki/Internet_socket socket architecture] used by Unix systems to facilitate internet communication. | + | Notice that the stream tube exists on top of the [http://en.wikipedia.org/wiki/Internet_socket socket architecture] used by Unix systems to facilitate internet communication. |
| | | |
| ==== Step 2: Define or identify the classes you will use to serve data and receive data through your stream tube. ==== | | ==== Step 2: Define or identify the classes you will use to serve data and receive data through your stream tube. ==== |
Line 305: |
Line 305: |
| | | |
| ==== Step 3: Coordinate sharing and joining in your activity using stream tubes and the client/server classes defined above. ==== | | ==== Step 3: Coordinate sharing and joining in your activity using stream tubes and the client/server classes defined above. ==== |
| + | |
| + | On the sharing instance, the following must happen: |
| + | * Once the activity has been shared by the user, the sharing instance should detect the "shared" signal and setup for sharing. |
| + | * To setup for sharing, the sharing instance needs to instantiate a new server (in Annotate, this is an AnnotateHTTPServer) that will deliver content to any client activities. |
| + | * The newly instantiated server should listen on a given port and that port should be connected to a new stream tube. The stream tube can be created by calling the iface.OfferStreamTube() method. |
| + | |
| + | |
| + | For the joining activity, it must coordinate several steps once the "joined" signal has been detected: |
| + | * The joining activity needs to wait for a valid stream tube that is provided under the service ANNOTATE_STREAM_SERVICE. |
| + | * When such a tube is available, the joining activity should specify the path where the downloaded data will be saved. |
| + | * Create a listening client on the address and port associated with the stream tube that has been found. In our case, we create a sugar.network.GlibURLDownloader instance that will manage downloading from the stream tube. |
| + | |
| <pre> | | <pre> |
| ANNOTATE_STREAM_SERVICE = 'annotate-activity-http' | | ANNOTATE_STREAM_SERVICE = 'annotate-activity-http' |
Line 314: |
Line 326: |
| | | |
| ... | | ... |
− |
| |
| | | |
| #Joining activity needs to know which stream tubes are available for downloading | | #Joining activity needs to know which stream tubes are available for downloading |
Line 372: |
Line 383: |
| # instance | | # instance |
| def _joined_cb(self, also_self): | | def _joined_cb(self, also_self): |
− | self._update_chat_text('SYSTEM', '_joined_cb()')
| |
| self.watch_for_tubes() | | self.watch_for_tubes() |
| self._want_document = True; | | self._want_document = True; |
Line 380: |
Line 390: |
| # a stream tube is made available. | | # a stream tube is made available. |
| def watch_for_tubes(self): | | def watch_for_tubes(self): |
− | self._update_chat_text('SYSTEM', '_watch_for_tubes()')
| |
| tubes_chan = self._shared_activity.telepathy_tubes_chan | | tubes_chan = self._shared_activity.telepathy_tubes_chan |
| | | |
Line 394: |
Line 403: |
| | | |
| def _list_tubes_error_cb(self, e): | | def _list_tubes_error_cb(self, e): |
− | self._update_chat_text('System', '_list_tubes_error_cb(): ListTubes() failed: '+str(e))
| |
| | | |
| #### Method _new_tube_cb, which is called once a stream tube is available | | #### Method _new_tube_cb, which is called once a stream tube is available |
Line 400: |
Line 408: |
| def _new_tube_cb(self, tube_id, initiator, tube_type, service, params, | | def _new_tube_cb(self, tube_id, initiator, tube_type, service, params, |
| state): | | state): |
− | self._update_chat_text('SYSTEM', '_new_tube_cb() -- ID:' + str(tube_id) + '; Initiator: ' + str(initiator) + '; tube_type: ' + str(tube_type) + '; Service: ' + str(service))
| |
− |
| |
| # If the available tube is the stream tube we set up in sharing activity, then | | # If the available tube is the stream tube we set up in sharing activity, then |
| # let's download from it. | | # let's download from it. |
− | if service == ANNOTATE_STREAM_SERVICE: | + | if service == ANNOTATE_STREAM_SERVICE: |
− | self._update_chat_text('SYSTEM', 'I could download from that tube')
| |
− |
| |
| # Add the newly found stream tube to the available tubes we can download from | | # Add the newly found stream tube to the available tubes we can download from |
| self.unused_download_tubes.add(tube_id) | | self.unused_download_tubes.add(tube_id) |
Line 419: |
Line 423: |
| # obtained and saved in self.unused_download_tubes. | | # obtained and saved in self.unused_download_tubes. |
| def _get_document(self): | | def _get_document(self): |
− | self._update_chat_text('SYSTEM', '_get_document()')
| |
| if not self._want_document: | | if not self._want_document: |
| return False | | return False |
Line 431: |
Line 434: |
| tube_id = self.unused_download_tubes.pop() | | tube_id = self.unused_download_tubes.pop() |
| except (ValueError, KeyError), e: | | except (ValueError, KeyError), e: |
− | self._update_chat_text('System', 'No tubes to get the document from right now: '+str(e))
| |
| return False | | return False |
| | | |
Line 442: |
Line 444: |
| #### Method _download_result_cb, which is called once downloading is complete. | | #### Method _download_result_cb, which is called once downloading is complete. |
| def _download_result_cb(self, getter, tempfile, suggested_name, tube_id): | | def _download_result_cb(self, getter, tempfile, suggested_name, tube_id): |
− | self._update_chat_text('SYSTEM', '_download_result_cb() -- tempfile = ' + tempfile)
| |
| del self.unused_download_tubes | | del self.unused_download_tubes |
− |
| |
− | self._update_chat_text('SYSTEM', "Got document %s (%s) from tube %u",
| |
− | tempfile, suggested_name, tube_id)
| |
| self.save() | | self.save() |
| | | |
Line 453: |
Line 451: |
| # FIXME: signal the expected size somehow, so we can draw a progress | | # FIXME: signal the expected size somehow, so we can draw a progress |
| # bar | | # bar |
− | self._update_chat_text("Downloaded " + str(bytes_downloaded) + " bytes from tube " + str(tube_id)) | + | return True; |
| | | |
| #### Method _download_error_cb, which is called if there was an error downloading. | | #### Method _download_error_cb, which is called if there was an error downloading. |
Line 466: |
Line 464: |
| # FIXME: should ideally have the CM listen on a Unix socket | | # FIXME: should ideally have the CM listen on a Unix socket |
| # instead of IPv4 (might be more compatible with Rainbow) | | # instead of IPv4 (might be more compatible with Rainbow) |
− | self._update_chat_text('SYSTEM', '_download_document() -- ' + path)
| |
| chan = self._shared_activity.telepathy_tubes_chan | | chan = self._shared_activity.telepathy_tubes_chan |
| iface = chan[telepathy.CHANNEL_TYPE_TUBES] | | iface = chan[telepathy.CHANNEL_TYPE_TUBES] |
Line 487: |
Line 484: |
| getter.connect("progress", self._download_progress_cb, tube_id) | | getter.connect("progress", self._download_progress_cb, tube_id) |
| getter.connect("error", self._download_error_cb, tube_id) | | getter.connect("error", self._download_error_cb, tube_id) |
− | self._update_chat_text('System', "Starting download to "+str(path))
| |
| getter.start(path) | | getter.start(path) |
| return False | | return False |
Line 500: |
Line 496: |
| === Where do I get more information regarding sugar activity sharing and the technologies that support it? === | | === Where do I get more information regarding sugar activity sharing and the technologies that support it? === |
| * A [[Shared_Sugar_Activities | brief tutorial]] on activity sharing for the OLPC laptop. | | * A [[Shared_Sugar_Activities | brief tutorial]] on activity sharing for the OLPC laptop. |
| + | |
| + | === I can't get tubes to work. Are there unresolved issues? === |