diff options
Diffstat (limited to 'plugins/shotwell-publishing/YouTubePublishing.vala')
-rw-r--r-- | plugins/shotwell-publishing/YouTubePublishing.vala | 215 |
1 files changed, 44 insertions, 171 deletions
diff --git a/plugins/shotwell-publishing/YouTubePublishing.vala b/plugins/shotwell-publishing/YouTubePublishing.vala index e50d17a..f0a9866 100644 --- a/plugins/shotwell-publishing/YouTubePublishing.vala +++ b/plugins/shotwell-publishing/YouTubePublishing.vala @@ -5,14 +5,7 @@ */ public class YouTubeService : Object, Spit.Pluggable, Spit.Publishing.Service { - private const string ICON_FILENAME = "youtube.png"; - - private static Gdk.Pixbuf[] icon_pixbuf_set = null; - - public YouTubeService(GLib.File resource_directory) { - if (icon_pixbuf_set == null) - icon_pixbuf_set = Resources.load_from_resource - (Resources.RESOURCE_PATH + "/" + ICON_FILENAME); + public YouTubeService() { } public int get_pluggable_interface(int min_host_interface, int max_host_interface) { @@ -21,23 +14,20 @@ public class YouTubeService : Object, Spit.Pluggable, Spit.Publishing.Service { } public unowned string get_id() { - return "org.yorba.shotwell.publishing.youtube"; + return "org.gnome.shotwell.publishing.youtube"; } public unowned string get_pluggable_name() { return "YouTube"; } - public void get_info(ref Spit.PluggableInfo info) { + public Spit.PluggableInfo get_info() { + var info = new Spit.PluggableInfo(); info.authors = "Jani Monoses, Lucas Beeler"; info.copyright = _("Copyright 2016 Software Freedom Conservancy Inc."); - info.translators = Resources.TRANSLATORS; - info.version = _VERSION; - info.website_name = Resources.WEBSITE_NAME; - info.website_url = Resources.WEBSITE_URL; - info.is_license_wordwrapped = false; - info.license = Resources.LICENSE; - info.icons = icon_pixbuf_set; + info.icon_name = "youtube"; + + return info; } public Spit.Publishing.Publisher create_publisher(Spit.Publishing.PluginHost host) { @@ -60,10 +50,23 @@ private const string DEVELOPER_KEY = private enum PrivacySetting { PUBLIC, UNLISTED, - PRIVATE + PRIVATE; + + public string to_string() { + switch (this) { + case PUBLIC: + return "public"; + case UNLISTED: + return "unlisted"; + case PRIVATE: + return "private"; + default: + assert_not_reached(); + } + } } -private class PublishingParameters { +internal class PublishingParameters { private PrivacySetting privacy; private string? user_name; @@ -89,44 +92,14 @@ private class PublishingParameters { } } -internal class YouTubeAuthorizer : GData.Authorizer, Object { - private RESTSupport.GoogleSession session; - private Spit.Publishing.Authenticator authenticator; - - public YouTubeAuthorizer(RESTSupport.GoogleSession session, Spit.Publishing.Authenticator authenticator) { - this.session = session; - this.authenticator = authenticator; - } - - public bool is_authorized_for_domain(GData.AuthorizationDomain domain) { - return domain.scope.has_suffix ("auth/youtube"); - } - - public void process_request(GData.AuthorizationDomain? domain, - Soup.Message message) { - if (domain == null) { - return; - } - - var header = "Bearer %s".printf(session.get_access_token()); - message.request_headers.replace("Authorization", header); - } - - public bool refresh_authorization (GLib.Cancellable? cancellable = null) throws GLib.Error { - this.authenticator.refresh(); - return true; - } -} - public class YouTubePublisher : Publishing.RESTSupport.GooglePublisher { private bool running; private PublishingParameters publishing_parameters; private Spit.Publishing.ProgressCallback? progress_reporter; private Spit.Publishing.Authenticator authenticator; - private GData.YouTubeService youtube_service; public YouTubePublisher(Spit.Publishing.Service service, Spit.Publishing.PluginHost host) { - base(service, host, "https://gdata.youtube.com/"); + base(service, host, "https://www.googleapis.com/upload/youtube/v3/videos"); this.running = false; this.publishing_parameters = new PublishingParameters(); @@ -161,8 +134,6 @@ public class YouTubePublisher : Publishing.RESTSupport.GooglePublisher { publishing_parameters.set_user_name(get_session().get_user_name()); - this.youtube_service = new GData.YouTubeService(DEVELOPER_KEY, - new YouTubeAuthorizer(get_session(), this.authenticator)); do_show_publishing_options_pane(); } @@ -181,7 +152,7 @@ public class YouTubePublisher : Publishing.RESTSupport.GooglePublisher { if (!is_running()) return; - do_upload(); + do_upload.begin(); } private void on_upload_status_updated(int file_number, double completed_fraction) { @@ -195,32 +166,6 @@ public class YouTubePublisher : Publishing.RESTSupport.GooglePublisher { progress_reporter(file_number, completed_fraction); } - private void on_upload_complete(Publishing.RESTSupport.BatchUploader uploader, - int num_published) { - uploader.upload_complete.disconnect(on_upload_complete); - uploader.upload_error.disconnect(on_upload_error); - - debug("EVENT: uploader reports upload complete; %d items published.", num_published); - - if (!is_running()) - return; - - do_show_success_pane(); - } - - private void on_upload_error(Publishing.RESTSupport.BatchUploader uploader, - Spit.Publishing.PublishingError err) { - uploader.upload_complete.disconnect(on_upload_complete); - uploader.upload_error.disconnect(on_upload_error); - - if (!is_running()) - return; - - debug("EVENT: uploader reports upload error = '%s'.", err.message); - - get_host().post_error(err); - } - private void do_show_publishing_options_pane() { debug("ACTION: showing publishing options pane."); @@ -245,7 +190,7 @@ public class YouTubePublisher : Publishing.RESTSupport.GooglePublisher { get_host().set_service_locked(false); } - private void do_upload() { + private async void do_upload() { debug("ACTION: uploading media items to remote server."); get_host().set_service_locked(true); @@ -261,12 +206,24 @@ public class YouTubePublisher : Publishing.RESTSupport.GooglePublisher { return; Spit.Publishing.Publishable[] publishables = get_host().get_publishables(); - Uploader uploader = new Uploader(this.youtube_service, get_session(), publishables, publishing_parameters); + Uploader uploader = new Uploader(get_session(), publishables, publishing_parameters); + + try { + var num_published = yield uploader.upload_async(on_upload_status_updated); + debug("EVENT: uploader reports upload complete; %d items published.", num_published); + + if (!is_running()) + return; + + do_show_success_pane(); + } catch (Error err) { + if (!is_running()) + return; - uploader.upload_complete.connect(on_upload_complete); - uploader.upload_error.connect(on_upload_error); + debug("EVENT: uploader reports upload error = '%s'.", err.message); - uploader.upload(on_upload_status_updated); + get_host().post_error(err); + } } private void do_show_success_pane() { @@ -397,104 +354,20 @@ internal class PublishingOptionsPane : Spit.Publishing.DialogPane, GLib.Object { } } -internal class UploadTransaction : Publishing.RESTSupport.GooglePublisher.AuthenticatedTransaction { - private const string ENDPOINT_URL = "https://uploads.gdata.youtube.com/feeds/api/users/default/uploads"; - private PublishingParameters parameters; - private Publishing.RESTSupport.GoogleSession session; - private Spit.Publishing.Publishable publishable; - private GData.YouTubeService youtube_service; - - public UploadTransaction(GData.YouTubeService youtube_service, Publishing.RESTSupport.GoogleSession session, - PublishingParameters parameters, Spit.Publishing.Publishable publishable) { - base(session, ENDPOINT_URL, Publishing.RESTSupport.HttpMethod.POST); - assert(session.is_authenticated()); - this.session = session; - this.parameters = parameters; - this.publishable = publishable; - this.youtube_service = youtube_service; - } - - public override void execute() throws Spit.Publishing.PublishingError { - var video = new GData.YouTubeVideo(null); - - var slug = publishable.get_param_string(Spit.Publishing.Publishable.PARAM_STRING_BASENAME); - // Set title to publishing name, but if that's empty default to filename. - string title = publishable.get_publishing_name(); - if (title == "") { - title = publishable.get_param_string(Spit.Publishing.Publishable.PARAM_STRING_BASENAME); - } - video.title = title; - - video.is_private = (parameters.get_privacy() == PrivacySetting.PRIVATE); - - if (parameters.get_privacy() == PrivacySetting.UNLISTED) { - video.set_access_control("list", GData.YouTubePermission.DENIED); - } else if (!video.is_private) { - video.set_access_control("list", GData.YouTubePermission.ALLOWED); - } - - var file = publishable.get_serialized_file(); - - try { - var info = file.query_info(FileAttribute.STANDARD_CONTENT_TYPE + "," + - FileAttribute.STANDARD_SIZE, FileQueryInfoFlags.NONE); - var upload_stream = this.youtube_service.upload_video(video, slug, - info.get_content_type()); - var input_stream = file.read(); - - // Yuck... - var loop = new MainLoop(null, false); - this.splice_with_progress.begin(info, input_stream, upload_stream, (obj, res) => { - try { - this.splice_with_progress.end(res); - } catch (Error error) { - critical("Failed to upload: %s", error.message); - } - loop.quit(); - }); - loop.run(); - video = this.youtube_service.finish_video_upload(upload_stream); - } catch (Error error) { - critical("Upload failed: %s", error.message); - } - } - - private async void splice_with_progress(GLib.FileInfo info, GLib.InputStream input, GLib.OutputStream output) throws Error { - var total_bytes = info.get_size(); - var bytes_to_write = total_bytes; - uint8 buffer[8192]; - - while (bytes_to_write > 0) { - var bytes_read = yield input.read_async(buffer); - if (bytes_read == 0) - break; - - var bytes_written = yield output.write_async(buffer[0:bytes_read]); - bytes_to_write -= bytes_written; - chunk_transmitted((int)(total_bytes - bytes_to_write), (int) total_bytes); - } - - yield output.close_async(); - yield input.close_async(); - } -} - internal class Uploader : Publishing.RESTSupport.BatchUploader { private PublishingParameters parameters; - private GData.YouTubeService youtube_service; - public Uploader(GData.YouTubeService youtube_service, Publishing.RESTSupport.GoogleSession session, + public Uploader(Publishing.RESTSupport.GoogleSession session, Spit.Publishing.Publishable[] publishables, PublishingParameters parameters) { base(session, publishables); this.parameters = parameters; - this.youtube_service = youtube_service; } protected override Publishing.RESTSupport.Transaction create_transaction( Spit.Publishing.Publishable publishable) { - return new UploadTransaction(this.youtube_service, (Publishing.RESTSupport.GoogleSession) get_session(), - parameters, get_current_publishable()); + return new UploadTransaction((Publishing.RESTSupport.GoogleSession) get_session(), + parameters, get_current_publishable()); } } |