Hi ----- Original Message ----- > So, spice-gtk has supported file transfers from client to guest for > quite a while. But there's a longstanding issue that the user has no > feedback about whether the file is actually being transferred, or how > long it will take. The only real feedback that a user gets is after the > file transfer is completed: the vdagent will generally open a file > browser window to reveal the transferred file. > > So I was poking around a bit with adding a file transfer progress > indication to virt-viewer, and I found that the file transfer API in > spice-gtk does not make this very easy. The main API involved here is > this: > > void spice_main_file_copy_async(SpiceMainChannel *channel, > GFile **sources, > GFileCopyFlags flags, > GCancellable *cancellable, > GFileProgressCallback progress_callback, > gpointer progress_callback_data, > GAsyncReadyCallback callback, > gpointer user_data); > > At first glance, it looks like this gives us everything we need, but > there are a few issues with it. The main ones are: Just want to mention this API was originally designed with single file copy in mind (at this time no plan for multiple files), and there was no support for monitoring/notification of progress from listeners either (only the caller could get the progress). > > > 1. It's possible to pass an array of files to be transferred, but the > progress_callback is called for each file separately. But the > GFileProgressCallback function signature does not provide any way for > the caller to determine which file a given progress_callback() call is > associated with. For example, if you tried to transfer 2 different files > with sizes 100 and 200, you might get the following: > - progress_callback(0, 100, progress_callback_data) > - progress_callback(0, 200, progress_callback_data) > - progress_callback(50, 100, progress_callback_data) > - progress_callback(50, 200, progress_callback_data) > - progress_callback(100, 100, progress_callback_data) > - progress_callback(100, 200, progress_callback_data) > - progress_callback(150, 200, progress_callback_data) > - progress_callback(200, 200, progress_callback_data) > > In this case, you could apply some heuristics to figure out which > callback applied to which file by examining the file sizes, but that is > not ideal, and is not always going to work. A workaround for this is to > sum up total progress internally and pass these values to the > progress_callback. In that case, you'd get something more like this: > - progress_callback(0, 300, progress_callback_data) > - progress_callback(0, 300, progress_callback_data) > - progress_callback(50, 300, progress_callback_data) > - progress_callback(100, 300, progress_callback_data) > - progress_callback(150, 300, progress_callback_data) > - progress_callback(200, 300, progress_callback_data) > - progress_callback(250, 300, progress_callback_data) > - progress_callback(300, 300, progress_callback_data) > > That seems OK, but see #3 below as to why this isn't really a full > solution. > > > > 2. spice_main_file_copy_async() looks like a single transaction, so you > would expect it to call 'callback' after all files are finished being > transferred. But in reality, 'callback' is called once for each file > that is being transferred. This makes it difficult for the application > to keep track of the status of the entire transaction. It would be much > better to make it behave like every other gio-style async API and have a > single _async() call paired to a single _finish() call. > > > > 3. Even if the spice_main_file_copy_async() API mentioned above did not > have any problems, it's difficult for an application to make use of it > if they also use the SpiceDisplay widget. This is because the > SpiceDisplay widget automatically handles drag-and-drop of files onto > the display. When a file is dropped, it immediately starts a file > transfer. This means that the application cannot use in its own > 'progress_callback' or 'callback' functions in order to monitor and > display the file transfer progress. There's currently no way to disable > this automatic handling of drag-and-drop on the widget. > > > ========== > > We could deprecate this API, but I don't want to remove or break public > API. So we still need to support transfers created with the current > function. I'd like to propose a complementary API: > > Add a new public object SpiceFileTransferTask with the following > characteristics: > - it represents the transfer of a single file > - it has a "progress" property, which represents the percentage of the > file that has been transferred. The application can connect to the > "notify::progress" signal to be notified when the progress of a transfer > changes. > - it has a "finished" signal so that the application can tell when the > transfer of that file has completed > - it has a "filename" property so that the application can display the > filename next to the progress of the transfer if desired > - it has a "cancel()" method, so that an application can cancel an > individual file transfer[0] > > In addition to this new object, add a "new-file-transfer" signal to > SpiceMainChannel. This signal will be emitted whenever a new file > transfer task has been initiated (presumably by the drag-and-drop > handler of the SpiceDisplay widget). > > This should allow us to keep our API stable and still allow applications > to monitor and display feedback of file transfers. Objections? Alternate > suggestions? > > Since you managed to read this whole long-winded message, here's a > little screencast of a preliminary implementation in spicy using the > above approach: > http://people.freedesktop.org/~jjongsma/spicy-file-transfer-progress.ogv > > Thanks, > Jonathon > > _______________________________________________ > Spice-devel mailing list > Spice-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/spice-devel > _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel