From 0aa340be4c58839bb05b1d5a64e48e71ab87f804 Mon Sep 17 00:00:00 2001
From: Manuel Kaufmann <humitos@gmail.com>
Date: Wed, 5 Dec 2012 18:00:32 -0300
Subject: [PATCH sugar] "Send to Fried" from Journal fixed SL #4242
- Fix some issues related to the port to Gio (introspected): argument
numbers andd order and method names.
- Use 'Gio.InputStream.read_bytes_async' and
'Gio.OutputStream.write_bytes_async' to transfer the data.
http://developer.gnome.org/gio/stable/GInputStream.html#g-input-stream-read-bytes-async
Signed-off-by: Manuel Kaufmann <humitos@gmail.com>
---
src/jarabe/model/filetransfer.py | 70 ++++++++++++++++++++++++----------------
1 file changed, 42 insertions(+), 28 deletions(-)
diff --git a/src/jarabe/model/filetransfer.py b/src/jarabe/model/filetransfer.py
index 820df74..c4dd518 100644
a
|
b
|
import socket |
20 | 20 | |
21 | 21 | from gi.repository import GObject |
22 | 22 | from gi.repository import Gio |
| 23 | from gi.repository import GLib |
23 | 24 | import dbus |
24 | 25 | from telepathy.interfaces import CONNECTION_INTERFACE_REQUESTS, CHANNEL |
25 | 26 | from telepathy.constants import CONNECTION_HANDLE_TYPE_CONTACT, \ |
… |
… |
from sugar3 import dispatch |
33 | 34 | from jarabe.util.telepathy import connection_watcher |
34 | 35 | from jarabe.model import neighborhood |
35 | 36 | |
| 37 | # Avoid "Fatal Python error: GC object already tracked" |
| 38 | # http://stackoverflow.com/questions/7496629/gstreamer-appsrc-causes-random-crashes |
| 39 | GObject.threads_init() |
36 | 40 | |
37 | 41 | FT_STATE_NONE = 0 |
38 | 42 | FT_STATE_PENDING = 1 |
… |
… |
class StreamSplicer(GObject.GObject): |
73 | 77 | self._pending_buffers = [] |
74 | 78 | |
75 | 79 | def start(self): |
76 | | self._input_stream.read_async(self._CHUNK_SIZE, self.__read_async_cb, |
77 | | GObject.PRIORITY_LOW) |
78 | | |
79 | | def __read_async_cb(self, input_stream, result): |
80 | | data = input_stream.read_finish(result) |
81 | | |
82 | | if not data: |
83 | | logging.debug('closing input stream') |
84 | | self._input_stream.close() |
| 80 | self._input_stream.read_bytes_async( |
| 81 | self._CHUNK_SIZE, GLib.PRIORITY_LOW, |
| 82 | None, self.__read_async_cb, None) |
| 83 | |
| 84 | def __read_async_cb(self, input_stream, result, user_data): |
| 85 | data = input_stream.read_bytes_finish(result) |
| 86 | |
| 87 | if data is None: |
| 88 | # TODO: an error occured. Report something |
| 89 | logging.error('An error occured in the file transfer.') |
| 90 | elif data.get_size() == 0: |
| 91 | # We read the file completely |
| 92 | logging.debug('Closing input stream. Reading finished.') |
| 93 | self._input_stream.close(None) |
85 | 94 | else: |
| 95 | logging.debug('Data received (bytes): %s', data.get_size()) |
86 | 96 | self._pending_buffers.append(data) |
87 | | self._input_stream.read_async(self._CHUNK_SIZE, |
88 | | self.__read_async_cb, |
89 | | GObject.PRIORITY_LOW) |
| 97 | self._input_stream.read_bytes_async( |
| 98 | self._CHUNK_SIZE, GLib.PRIORITY_LOW, |
| 99 | None, self.__read_async_cb, None) |
90 | 100 | self._write_next_buffer() |
91 | 101 | |
92 | 102 | def __write_async_cb(self, output_stream, result, user_data): |
93 | | count_ = output_stream.write_finish(result) |
| 103 | size = output_stream.write_bytes_finish(result) |
| 104 | logging.debug('Size written (bytes): %s', size) |
94 | 105 | |
95 | 106 | if not self._pending_buffers and \ |
96 | 107 | not self._output_stream.has_pending() and \ |
97 | 108 | not self._input_stream.has_pending(): |
98 | | logging.debug('closing output stream') |
99 | | output_stream.close() |
| 109 | logging.debug('Closing output stream. Writing finished.') |
| 110 | output_stream.close(None) |
100 | 111 | self.emit('finished') |
101 | 112 | else: |
102 | 113 | self._write_next_buffer() |
… |
… |
class StreamSplicer(GObject.GObject): |
104 | 115 | def _write_next_buffer(self): |
105 | 116 | if self._pending_buffers and not self._output_stream.has_pending(): |
106 | 117 | data = self._pending_buffers.pop(0) |
107 | | # TODO: we pass the buffer as user_data because of |
108 | | # http://bugzilla.gnome.org/show_bug.cgi?id=564102 |
109 | | self._output_stream.write_async(data, self.__write_async_cb, |
110 | | GObject.PRIORITY_LOW, |
111 | | user_data=data) |
| 118 | self._output_stream.write_bytes_async( |
| 119 | data, GLib.PRIORITY_LOW, None, |
| 120 | self.__write_async_cb, None) |
112 | 121 | |
113 | 122 | |
114 | 123 | class BaseFileTransfer(GObject.GObject): |
… |
… |
class IncomingFileTransfer(BaseFileTransfer): |
215 | 224 | # close the fd when it goes out of scope |
216 | 225 | self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
217 | 226 | self._socket.connect(self._socket_address) |
218 | | input_stream = Gio.unix.InputStream(self._socket.fileno(), True) |
| 227 | input_stream = Gio.UnixInputStream.new(self._socket.fileno(), True) |
219 | 228 | |
220 | | destination_file = Gio.File(self.destination_path) |
| 229 | destination_file = Gio.File.new_for_path(self.destination_path) |
221 | 230 | if self.initial_offset == 0: |
222 | | output_stream = destination_file.create() |
| 231 | output_stream = destination_file.create( |
| 232 | Gio.FileCreateFlags.PRIVATE, None) |
223 | 233 | else: |
224 | 234 | output_stream = destination_file.append_to() |
225 | 235 | |
… |
… |
class OutgoingFileTransfer(BaseFileTransfer): |
277 | 287 | # closes the fd when it goes out of scope |
278 | 288 | self._socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) |
279 | 289 | self._socket.connect(self._socket_address) |
280 | | output_stream = Gio.unix.OutputStream(self._socket.fileno(), True) |
| 290 | output_stream = Gio.UnixOutputStream.new( |
| 291 | self._socket.fileno(), True) |
281 | 292 | |
282 | 293 | logging.debug('opening %s for reading', self._file_name) |
283 | | input_stream = Gio.File(self._file_name).read() |
| 294 | input_stream = Gio.File.new_for_path(self._file_name).read(None) |
284 | 295 | if self.initial_offset > 0: |
285 | 296 | input_stream.skip(self.initial_offset) |
286 | 297 | |
… |
… |
def file_transfer_available(): |
356 | 367 | if __name__ == '__main__': |
357 | 368 | import tempfile |
358 | 369 | |
359 | | test_file_name = '/home/tomeu/isos/Soas2-200904031934.iso' |
360 | | test_input_stream = Gio.File(test_file_name).read() |
361 | | test_output_stream = Gio.File(tempfile.mkstemp()[1]).append_to() |
| 370 | test_file_name = '/home/humitos/test.py' |
| 371 | test_temp_file = tempfile.mkstemp()[1] |
| 372 | print test_temp_file |
| 373 | test_input_stream = Gio.File.new_for_path(test_file_name).read(None) |
| 374 | test_output_stream = Gio.File.new_for_path(test_temp_file)\ |
| 375 | .append_to(Gio.FileCreateFlags.PRIVATE, None) |
362 | 376 | |
363 | 377 | # TODO: Use splice_async when it gets implemented |
364 | 378 | splicer = StreamSplicer(test_input_stream, test_output_stream) |