OSDN Git Service

IMediaItemクラスを介してファイル・MemoryImageの投稿に対応した
authorspx <spx268@gmail.com>
Tue, 30 Jun 2015 18:00:09 +0000 (03:00 +0900)
committerKimura Youichi <kim.upsilon@bucyou.net>
Sat, 4 Jul 2015 03:11:20 +0000 (12:11 +0900)
※Imgurのみ、投稿方法が違っているので未対応

16 files changed:
OpenTween/Connection/HttpConnection.cs
OpenTween/Connection/HttpConnectionOAuth.cs
OpenTween/Connection/HttpTwitter.cs
OpenTween/Connection/IHttpConnection.cs
OpenTween/Connection/IMediaUploadService.cs
OpenTween/Connection/Imgur.cs
OpenTween/Connection/Mobypicture.cs
OpenTween/Connection/TwipplePhoto.cs
OpenTween/Connection/TwitterPhoto.cs
OpenTween/Connection/imgly.cs
OpenTween/Connection/yfrog.cs
OpenTween/MediaItem.cs [new file with mode: 0644]
OpenTween/MediaSelector.cs
OpenTween/OpenTween.csproj
OpenTween/Tween.cs
OpenTween/Twitter.cs

index 191d5e5..c31c38e 100644 (file)
@@ -138,7 +138,7 @@ namespace OpenTween
         protected HttpWebRequest CreateRequest(string method,
                                                Uri requestUri,
                                                Dictionary<string, string> param,
-                                               List<KeyValuePair<String, FileInfo>> binaryFileInfo)
+                                               List<KeyValuePair<String, IMediaItem>> binaryFileInfo)
         {
             Networking.CheckInitialized();
 
@@ -177,7 +177,7 @@ namespace OpenTween
                     //POST送信するバイナリデータを作成
                     if (binaryFileInfo != null)
                     {
-                        foreach (KeyValuePair<string, FileInfo> kvp in binaryFileInfo)
+                        foreach (KeyValuePair<string, IMediaItem> kvp in binaryFileInfo)
                         {
                             string postData = "";
                             byte[] crlfByte = Encoding.UTF8.GetBytes("\r\n");
@@ -245,17 +245,7 @@ namespace OpenTween
                             byte[] postBytes = Encoding.UTF8.GetBytes(postData);
                             reqStream.Write(postBytes, 0, postBytes.Length);
                             //ファイルを読み出してHTTPのストリームに書き込み
-                            using (FileStream fs = new FileStream(kvp.Value.FullName, FileMode.Open, FileAccess.Read))
-                            {
-                                int readSize = 0;
-                                byte[] readBytes = new byte[0x1000];
-                                while (true)
-                                {
-                                    readSize = fs.Read(readBytes, 0, readBytes.Length);
-                                    if (readSize == 0) break;
-                                    reqStream.Write(readBytes, 0, readSize);
-                                }
-                            }
+                            kvp.Value.CopyTo(reqStream);
                             reqStream.Write(crlfByte, 0, crlfByte.Length);
                         }
                     }
index 0a64125..983f467 100644 (file)
@@ -162,7 +162,7 @@ namespace OpenTween
                public HttpStatusCode GetContent( string method,
                                                  Uri requestUri,
                                                  Dictionary< string, string > param,
-                                                 List< KeyValuePair< string, FileInfo > > binary, 
+                                                 List< KeyValuePair< string, IMediaItem > > binary, 
                                                  ref string content,
                                                  Dictionary< string, string > headerInfo,
                                                  CallbackDelegate callback )
index 1058536..5e5d4d4 100644 (file)
@@ -182,7 +182,7 @@ namespace OpenTween
                 null);
         }
 
-        public HttpStatusCode UpdateStatusWithMedia(string status, long? replyToId, FileInfo mediaFile, ref string content)
+        public HttpStatusCode UpdateStatusWithMedia(string status, long? replyToId, IMediaItem item, ref string content)
         {
             //画像投稿用エンドポイント
             Dictionary<string, string> param = new Dictionary<string, string>();
@@ -191,8 +191,8 @@ namespace OpenTween
             param.Add("include_entities", "true");
             //if (AppendSettingDialog.Instance.ShortenTco && AppendSettingDialog.Instance.UrlConvertAuto) param.Add("wrap_links", "true")
 
-            List<KeyValuePair<string, FileInfo>> binary = new List<KeyValuePair<string, FileInfo>>();
-            binary.Add(new KeyValuePair<string, FileInfo>("media[]", mediaFile));
+            var binary = new List<KeyValuePair<string, IMediaItem>>();
+            binary.Add(new KeyValuePair<string, IMediaItem>("media[]", item));
 
             return httpCon.GetContent(PostMethod,
                 this.CreateTwitterUri("/1.1/statuses/update_with_media.json"),
@@ -203,11 +203,11 @@ namespace OpenTween
                 this.CreateApiCalllback("/statuses/update_with_media"));
         }
 
-        public HttpStatusCode UploadMedia(FileInfo mediaFile, ref string content)
+        public HttpStatusCode UploadMedia(IMediaItem item, ref string content)
         {
             //画像投稿専用エンドポイント
-            List<KeyValuePair<string, FileInfo>> binary = new List<KeyValuePair<string, FileInfo>>();
-            binary.Add(new KeyValuePair<string, FileInfo>("media", mediaFile));
+            var binary = new List<KeyValuePair<string, IMediaItem>>();
+            binary.Add(new KeyValuePair<string, IMediaItem>("media", item));
 
             return httpCon.GetContent(PostMethod,
                 this.CreateTwitterUploadUri("/1.1/media/upload.json"),
@@ -796,8 +796,8 @@ namespace OpenTween
 
         public HttpStatusCode UpdateProfileImage(FileInfo imageFile, ref string content)
         {
-            List<KeyValuePair<string, FileInfo>> binary = new List<KeyValuePair<string, FileInfo>>();
-            binary.Add(new KeyValuePair<string, FileInfo>("image", imageFile));
+            var binary = new List<KeyValuePair<string, IMediaItem>>();
+            binary.Add(new KeyValuePair<string, IMediaItem>("image", new FileMediaItem(imageFile)));
 
             return httpCon.GetContent(PostMethod,
                 this.CreateTwitterUri("/1.1/account/update_profile_image.json"),
index f098a44..dfc1d27 100644 (file)
@@ -49,7 +49,7 @@ namespace OpenTween
         HttpStatusCode GetContent(string method,
                 Uri requestUri,
                 Dictionary<string, string> param,
-                List<KeyValuePair<string, FileInfo>> binary,
+                List<KeyValuePair<string, IMediaItem>> binary,
                 ref string content,
                 Dictionary<string, string> headerInfo,
                 CallbackDelegate callback);
index b515d89..db38bba 100644 (file)
@@ -68,7 +68,7 @@ namespace OpenTween.Connection
         /// メディアのアップロードとツイートの投稿を行います
         /// </summary>
         /// <exception cref="WebApiException"/>
-        Task PostStatusAsync(string text, long? inReplyToStatusId, string[] filePaths);
+        Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems);
 
         /// <summary>
         /// 画像URLのために確保する必要のある文字数を返します
index cf2d06b..6f9b2a5 100644 (file)
@@ -93,20 +93,23 @@ namespace OpenTween.Connection
             return MaxFileSize;
         }
 
-        public async Task PostStatusAsync(string text, long? inReplyToStatusId, string[] filePaths)
+        public async Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems)
         {
-            if (filePaths.Length != 1)
-                throw new ArgumentOutOfRangeException("filePaths");
+            if (mediaItems.Length != 1)
+                throw new ArgumentOutOfRangeException("mediaItems");
 
-            var file = new FileInfo(filePaths[0]);
+            var item = mediaItems[0] as FileMediaItem;
 
-            if (!file.Exists)
-                throw new ArgumentException("File isn't exists.", "filePaths[0]");
+            if (item == null)
+                throw new NotImplementedException();
+
+            if (!item.Exists)
+                throw new ArgumentException("File isn't exists.", "mediaItems[0]");
 
             XDocument xml;
             try
             {
-                xml = await this.UploadFileAsync(file, text)
+                xml = await this.UploadFileAsync(item.FileInfo, text)
                     .ConfigureAwait(false);
             }
             catch (HttpRequestException ex)
index c3b5820..5ba48c1 100644 (file)
@@ -122,17 +122,17 @@ namespace OpenTween.Connection
             return MaxFileSize;
         }
 
-        public async Task PostStatusAsync(string text, long? inReplyToStatusId, string[] filePaths)
+        public async Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems)
         {
-            if (filePaths.Length != 1)
-                throw new ArgumentOutOfRangeException("filePaths");
+            if (mediaItems.Length != 1)
+                throw new ArgumentOutOfRangeException("mediaItems");
 
-            var file = new FileInfo(filePaths[0]);
+            var item = mediaItems[0];
 
-            if (!file.Exists)
+            if (!item.Exists)
                 throw new ArgumentException("Err:File isn't exists.", "filePaths[0]");
 
-            var xml = await this.mobypictureApi.UploadFileAsync(file, text)
+            var xml = await this.mobypictureApi.UploadFileAsync(item, text)
                 .ConfigureAwait(false);
 
             var imageUrlElm = xml.XPathSelectElement("/rsp/media/mediaurl");
@@ -173,7 +173,7 @@ namespace OpenTween.Connection
             /// </summary>
             /// <exception cref="WebApiException"/>
             /// <exception cref="XmlException"/>
-            public async Task<XDocument> UploadFileAsync(FileInfo file, string message)
+            public async Task<XDocument> UploadFileAsync(IMediaItem item, string message)
             {
                 // 参照: http://developers.mobypicture.com/documentation/2-0/upload/
 
@@ -182,9 +182,9 @@ namespace OpenTween.Connection
                     {"key", ApplicationSettings.MobypictureKey},
                     {"message", message},
                 };
-                var paramFiles = new List<KeyValuePair<string, FileInfo>>
+                var paramFiles = new List<KeyValuePair<string, IMediaItem>>
                 {
-                    new KeyValuePair<string, FileInfo>("media", file),
+                    new KeyValuePair<string, IMediaItem>("media", item),
                 };
                 var response = "";
 
index 61fe1fe..ee27035 100644 (file)
@@ -102,17 +102,17 @@ namespace OpenTween.Connection
             return MaxFileSize;
         }
 
-        public async Task PostStatusAsync(string text, long? inReplyToStatusId, string[] filePaths)
+        public async Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems)
         {
-            if (filePaths.Length != 1)
-                throw new ArgumentOutOfRangeException("filePaths");
+            if (mediaItems.Length != 1)
+                throw new ArgumentOutOfRangeException("mediaItems");
 
-            var file = new FileInfo(filePaths[0]);
+            var item = mediaItems[0];
 
-            if (!file.Exists)
+            if (!item.Exists)
                 throw new ArgumentException("Err:File isn't exists.", "filePaths[0]");
 
-            var xml = await this.twippleApi.UploadFileAsync(file)
+            var xml = await this.twippleApi.UploadFileAsync(item)
                 .ConfigureAwait(false);
 
             var imageUrlElm = xml.XPathSelectElement("/rsp/mediaurl");
@@ -153,7 +153,7 @@ namespace OpenTween.Connection
             /// </summary>
             /// <exception cref="WebApiException"/>
             /// <exception cref="XmlException"/>
-            public async Task<XDocument> UploadFileAsync(FileInfo file)
+            public async Task<XDocument> UploadFileAsync(IMediaItem item)
             {
                 // 参照: http://p.twipple.jp/wiki/API_Upload2/ja
 
@@ -161,9 +161,9 @@ namespace OpenTween.Connection
                 {
                     {"upload_from", Application.ProductName},
                 };
-                var paramFiles = new List<KeyValuePair<string, FileInfo>>
+                var paramFiles = new List<KeyValuePair<string, IMediaItem>>
                 {
-                    new KeyValuePair<string, FileInfo>("media", file),
+                    new KeyValuePair<string, IMediaItem>("media", item),
                 };
                 var response = "";
 
index 5bde80a..63e1046 100644 (file)
@@ -76,28 +76,23 @@ namespace OpenTween.Connection
             return this.twitterConfig.PhotoSizeLimit;
         }
 
-        public async Task PostStatusAsync(string text, long? inReplyToStatusId, string[] filePaths)
+        public async Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems)
         {
-            if (filePaths == null || filePaths.Length == 0 || string.IsNullOrEmpty(filePaths[0]))
-                throw new ArgumentException("Err:File isn't specified.", "filePaths");
+            if (mediaItems == null || mediaItems.Length == 0)
+                throw new ArgumentException("Err:Media isn't specified.", "mediaItems");
 
-            var mediaFiles = new List<FileInfo>();
-
-            foreach (var filePath in filePaths)
+            foreach (var item in mediaItems)
             {
-                if (string.IsNullOrEmpty(filePath)) continue;
-
-                var mediaFile = new FileInfo(filePath);
-
-                if (!mediaFile.Exists)
-                    throw new ArgumentException("Err:File isn't exists.", "filePaths");
+                if (item == null)
+                    throw new ArgumentException("Err:Media isn't specified.", "mediaItems");
 
-                mediaFiles.Add(mediaFile);
+                if (!item.Exists)
+                    throw new ArgumentException("Err:File isn't exists.", "mediaItems");
             }
 
             await Task.Run(() =>
                 {
-                    var res = this.tw.PostStatusWithMultipleMedia(text, inReplyToStatusId, mediaFiles);
+                    var res = this.tw.PostStatusWithMultipleMedia(text, inReplyToStatusId, mediaItems);
                     if (!string.IsNullOrEmpty(res))
                         throw new WebApiException(res);
                 })
index d25175e..5ae8f8d 100644 (file)
@@ -85,17 +85,17 @@ namespace OpenTween.Connection
             return MaxFileSize;
         }
 
-        public async Task PostStatusAsync(string text, long? inReplyToStatusId, string[] filePaths)
+        public async Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems)
         {
-            if (filePaths.Length != 1)
-                throw new ArgumentOutOfRangeException("filePaths");
+            if (mediaItems.Length != 1)
+                throw new ArgumentOutOfRangeException("mediaItems");
 
-            var file = new FileInfo(filePaths[0]);
+            var item = mediaItems[0];
 
-            if (!file.Exists)
+            if (!item.Exists)
                 throw new ArgumentException("Err:File isn't exists.", "filePaths[0]");
 
-            var xml = await this.imglyApi.UploadFileAsync(file, text)
+            var xml = await this.imglyApi.UploadFileAsync(item, text)
                 .ConfigureAwait(false);
 
             var imageUrlElm = xml.XPathSelectElement("/image/url");
@@ -136,7 +136,7 @@ namespace OpenTween.Connection
             /// </summary>
             /// <exception cref="WebApiException"/>
             /// <exception cref="XmlException"/>
-            public async Task<XDocument> UploadFileAsync(FileInfo file, string message)
+            public async Task<XDocument> UploadFileAsync(IMediaItem item, string message)
             {
                 // 参照: http://img.ly/api
 
@@ -144,9 +144,9 @@ namespace OpenTween.Connection
                 {
                     {"message", message},
                 };
-                var paramFiles = new List<KeyValuePair<string, FileInfo>>
+                var paramFiles = new List<KeyValuePair<string, IMediaItem>>
                 {
-                    new KeyValuePair<string, FileInfo>("media", file),
+                    new KeyValuePair<string, IMediaItem>("media", item),
                 };
                 var response = "";
 
index 0c3947e..9c766ae 100644 (file)
@@ -85,17 +85,17 @@ namespace OpenTween.Connection
             return MaxFileSize;
         }
 
-        public async Task PostStatusAsync(string text, long? inReplyToStatusId, string[] filePaths)
+        public async Task PostStatusAsync(string text, long? inReplyToStatusId, IMediaItem[] mediaItems)
         {
-            if (filePaths.Length != 1)
-                throw new ArgumentOutOfRangeException("filePaths");
+            if (mediaItems.Length != 1)
+                throw new ArgumentOutOfRangeException("mediaItems");
 
-            var file = new FileInfo(filePaths[0]);
+            var item = mediaItems[0];
 
-            if (!file.Exists)
+            if (!item.Exists)
                 throw new ArgumentException("Err:File isn't exists.", "filePaths[0]");
 
-            var xml = await this.yfrogApi.UploadFileAsync(file, text)
+            var xml = await this.yfrogApi.UploadFileAsync(item, text)
                 .ConfigureAwait(false);
 
             var imageUrlElm = xml.XPathSelectElement("/rsp/mediaurl");
@@ -136,7 +136,7 @@ namespace OpenTween.Connection
             /// </summary>
             /// <exception cref="WebApiException"/>
             /// <exception cref="XmlException"/>
-            public async Task<XDocument> UploadFileAsync(FileInfo file, string message)
+            public async Task<XDocument> UploadFileAsync(IMediaItem item, string message)
             {
                 // 参照: http://twitter.yfrog.com/page/api#a1
 
@@ -144,9 +144,9 @@ namespace OpenTween.Connection
                 {
                     {"key", ApplicationSettings.YfrogApiKey},
                 };
-                var paramFiles = new List<KeyValuePair<string, FileInfo>>
+                var paramFiles = new List<KeyValuePair<string, IMediaItem>>
                 {
-                    new KeyValuePair<string, FileInfo>("media", file),
+                    new KeyValuePair<string, IMediaItem>("media", item),
                 };
                 var response = "";
 
diff --git a/OpenTween/MediaItem.cs b/OpenTween/MediaItem.cs
new file mode 100644 (file)
index 0000000..66a9c15
--- /dev/null
@@ -0,0 +1,224 @@
+// OpenTween - Client of Twitter
+// Copyright (c) 2015 spx (@5px)
+// All rights reserved.
+// 
+// This file is part of OpenTween.
+// 
+// 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 the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+// 
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details. 
+// 
+// You should have received a copy of the GNU General Public License along
+// with this program. If not, see <http://www.gnu.org/licenses/>, or write to
+// the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+// Boston, MA 02110-1301, USA.
+
+using System;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Threading;
+
+namespace OpenTween
+{
+    public interface IMediaItem
+    {
+        /// <summary>
+        /// メディアへの絶対パス
+        /// </summary>
+        string Path { get; }
+
+        /// <summary>
+        /// メディア名
+        /// </summary>
+        string Name { get; }
+
+        /// <summary>
+        /// メディアの拡張子
+        /// </summary>
+        string Extension { get; }
+
+        /// <summary>
+        /// メディアが存在するかどうかを示す真偽値
+        /// </summary>
+        bool Exists { get; }
+
+        /// <summary>
+        /// メディアのサイズ(バイト単位)
+        /// </summary>
+        long Size { get; }
+
+        /// <summary>
+        /// 表示用の MemoryImage を作成する
+        /// </summary>
+        MemoryImage CreateImage();
+
+        /// <summary>
+        /// メディアの内容を Stream へ書き込む
+        /// </summary>
+        void CopyTo(Stream stream);
+    }
+
+    /// <summary>
+    /// ファイル用の MediaItem クラス
+    /// </summary>
+    public class FileMediaItem : IMediaItem
+    {
+        private FileInfo _fileInfo = null;
+
+        public FileMediaItem(string path)
+        {
+            this._fileInfo = new FileInfo(path);
+        }
+
+        public FileMediaItem(FileInfo fileInfo)
+            : this(fileInfo.FullName)
+        {
+        }
+
+        public virtual string Path
+        {
+            get { return this._fileInfo.FullName; }
+        }
+
+        public virtual string Name
+        {
+            get { return this._fileInfo.Name; }
+        }
+
+        public virtual string Extension
+        {
+            get { return this._fileInfo.Extension; }
+        }
+
+        public virtual bool Exists
+        {
+            get { return this._fileInfo.Exists; }
+        }
+
+        public virtual long Size
+        {
+            get { return this._fileInfo.Length; }
+        }
+
+        public virtual MemoryImage CreateImage()
+        {
+            using (var fs = this._fileInfo.OpenRead())
+            {
+                return MemoryImage.CopyFromStream(fs);
+            }
+        }
+
+        public virtual void CopyTo(Stream stream)
+        {
+            using (var fs = this._fileInfo.OpenRead())
+            {
+                fs.CopyTo(stream);
+            }
+        }
+
+        public FileInfo FileInfo
+        {
+            get { return this._fileInfo; }
+        }
+    }
+
+    /// <summary>
+    /// MemoryImage 用の MediaItem クラス
+    /// </summary>
+    /// <remarks>
+    /// 用途の関係上、メモリ使用量が大きくなるため、不要になればできるだけ破棄すること
+    /// </remarks>
+    public class MemoryImageMediaItem : IMediaItem, IDisposable
+    {
+        public static readonly string PathPrefix = "<>MemoryImage://";
+        private static int _fileNumber = 0;
+
+        private bool _disposed = false;
+
+        private string _path;
+        private MemoryImage _image;
+
+        public MemoryImageMediaItem(Image image)
+        {
+            if (image == null)
+                throw new ArgumentNullException("image");
+
+            // image から png 形式の MemoryImage を生成
+            using (var bitmap = new Bitmap(image))
+            {
+                this._image = MemoryImage.CopyFromBitmap(bitmap);
+            }
+
+            var num = Interlocked.Increment(ref _fileNumber);
+            this._path = PathPrefix + num + this._image.ImageFormatExt;
+        }
+
+        public virtual string Path
+        {
+            get { return this._path; }
+        }
+
+        public virtual string Name
+        {
+            get { return this._path.Substring(PathPrefix.Length); }
+        }
+
+        public virtual string Extension
+        {
+            get { return this._image.ImageFormatExt; }
+        }
+
+        public virtual bool Exists
+        {
+            get { return this._image != null; }
+        }
+
+        public virtual long Size
+        {
+            get { return this._image.Stream.Length; }
+        }
+
+        public virtual MemoryImage CreateImage()
+        {
+            return this._image.Clone();
+        }
+
+        public virtual void CopyTo(Stream stream)
+        {
+            this._image.Stream.Seek(0, SeekOrigin.Begin);
+            this._image.Stream.CopyTo(stream);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (this._disposed) return;
+
+            if (disposing)
+            {
+                this._image.Dispose();
+            }
+
+            this._disposed = true;
+        }
+
+        public void Dispose()
+        {
+            this.Dispose(true);
+
+            // 明示的にDisposeが呼ばれた場合はファイナライザを使用しない
+            GC.SuppressFinalize(this);
+        }
+
+        ~MemoryImageMediaItem()
+        {
+            this.Dispose(false);
+        }
+    }
+}
index 3583cc9..611d36c 100644 (file)
@@ -88,25 +88,36 @@ namespace OpenTween
 
         private class SelectedMedia
         {
-            public string Path { get; set; }
+            public IMediaItem Item { get; set; }
             public MyCommon.UploadFileType Type { get; set; }
             public string Text { get; set; }
 
-            public SelectedMedia(string path, MyCommon.UploadFileType type, string text)
+            public SelectedMedia(IMediaItem item, MyCommon.UploadFileType type, string text)
             {
-                this.Path = path;
+                this.Item = item;
                 this.Type = type;
                 this.Text = text;
             }
 
             public SelectedMedia(string text)
-                : this("", MyCommon.UploadFileType.Invalid, text)
+                : this(null, MyCommon.UploadFileType.Invalid, text)
             {
             }
 
             public bool IsValid
             {
-                get { return this.Type != MyCommon.UploadFileType.Invalid; }
+                get
+                {
+                    return this.Item != null && this.Type != MyCommon.UploadFileType.Invalid;
+                }
+            }
+
+            public string Path
+            {
+                get
+                {
+                    return (this.Item != null) ? this.Item.Path : "";
+                }
             }
 
             public override string ToString()
@@ -206,60 +217,98 @@ namespace OpenTween
 
         /// <summary>
         /// 投稿するファイルとその投稿先を選択するためのコントロールを表示する。
-        /// D&Dをサポートする場合は引数にドロップされたファイル名を指定して呼ぶこと。
         /// </summary>
-        public void BeginSelection(string[] fileNames = null)
+        private void BeginSelection(IMediaItem[] items)
         {
-            if (fileNames != null && fileNames.Length > 0)
+            if (items == null || items.Length == 0)
             {
-                var serviceName = this.ServiceName;
-                if (string.IsNullOrEmpty(serviceName)) return;
-                var service = this.pictureService[serviceName];
+                BeginSelection();
+                return;
+            }
 
-                var count = Math.Min(fileNames.Length, service.MaxMediaCount);
-                if (!this.Visible || count > 1)
-                {
-                    // 非表示時または複数のファイル指定は新規選択として扱う
-                    SetImagePageCombo();
+            var serviceName = this.ServiceName;
+            if (string.IsNullOrEmpty(serviceName)) return;
+            var service = this.pictureService[serviceName];
 
-                    if (this.BeginSelecting != null)
-                        this.BeginSelecting(this, EventArgs.Empty);
+            var count = Math.Min(items.Length, service.MaxMediaCount);
+            if (!this.Visible || count > 1)
+            {
+                // 非表示時または複数のファイル指定は新規選択として扱う
+                SetImagePageCombo();
 
-                    this.Visible = true;
-                }
-                this.Enabled = true;
+                if (this.BeginSelecting != null)
+                    this.BeginSelecting(this, EventArgs.Empty);
 
-                if (count == 1)
-                {
-                    ImagefilePathText.Text = fileNames[0];
-                    ImageFromSelectedFile(false);
-                }
-                else
-                {
-                    for (int i = 0; i < count; i++)
-                    {
-                        var index = ImagePageCombo.Items.Count - 1;
-                        if (index == 0) ImagefilePathText.Text = fileNames[i];
-                        ImageFromSelectedFile(index, fileNames[i], false);
-                    }
-                }
+                this.Visible = true;
+            }
+            this.Enabled = true;
+
+            if (count == 1)
+            {
+                ImagefilePathText.Text = items[0].Path;
+                ImageFromSelectedFile(items[0], false);
             }
             else
             {
-                if (!this.Visible)
+                for (int i = 0; i < count; i++)
                 {
-                    if (this.BeginSelecting != null)
-                        this.BeginSelecting(this, EventArgs.Empty);
-
-                    this.Visible = true;
-                    this.Enabled = true;
-                    ImageFromSelectedFile(true);
-                    ImagefilePathText.Focus();
+                    var index = ImagePageCombo.Items.Count - 1;
+                    if (index == 0) ImagefilePathText.Text = items[i].Path;
+                    ImageFromSelectedFile(index, items[i], false);
                 }
             }
         }
 
         /// <summary>
+        /// 投稿するファイルとその投稿先を選択するためのコントロールを表示する(主にD&D用)。
+        /// </summary>
+        public void BeginSelection(string[] fileNames)
+        {
+            if (fileNames == null || fileNames.Length == 0)
+            {
+                BeginSelection();
+                return;
+            }
+
+            var items = fileNames.Select(x => CreateFileMediaItem(x, false)).OfType<IMediaItem>().ToArray();
+            BeginSelection(items);
+        }
+
+        /// <summary>
+        /// 投稿するファイルとその投稿先を選択するためのコントロールを表示する。
+        /// </summary>
+        public void BeginSelection(Image image)
+        {
+            if (image == null)
+            {
+                BeginSelection();
+                return;
+            }
+
+            var items = new [] { CreateMemoryImageMediaItem(image, false) }.OfType<IMediaItem>().ToArray();
+            BeginSelection(items);
+        }
+
+        /// <summary>
+        /// 投稿するファイルとその投稿先を選択するためのコントロールを表示する。
+        /// </summary>
+        public void BeginSelection()
+        {
+            if (!this.Visible)
+            {
+                if (this.BeginSelecting != null)
+                    this.BeginSelecting(this, EventArgs.Empty);
+
+                this.Visible = true;
+                this.Enabled = true;
+
+                var media = (SelectedMedia)ImagePageCombo.SelectedItem;
+                ImageFromSelectedFile(media.Item, true);
+                ImagefilePathText.Focus();
+            }
+        }
+
+        /// <summary>
         /// 選択処理を終了してコントロールを隠す。
         /// </summary>
         public void EndSelection()
@@ -280,26 +329,32 @@ namespace OpenTween
         }
 
         /// <summary>
-        /// é\81¸æ\8a\9eã\81\95ã\82\8cã\81\9fæ\8a\95稿å\85\88å\90\8dã\81¨æ\8a\95稿ã\83\95ã\82¡ã\82¤ã\83«å\90\8dã\82\92å\8f\96å¾\97ã\81\99ã\82\8b
+        /// é\81¸æ\8a\9eã\81\95ã\82\8cã\81\9fæ\8a\95稿å\85\88å\90\8dã\81¨æ\8a\95稿ã\81\99ã\82\8b MediaItem ã\82\92å\8f\96å¾\97ã\81\99ã\82\8bã\80\82MediaItem ã\81¯ä¸\8dè¦\81ã\81«ã\81ªã\81£ã\81\9fã\82\89å\91¼ã\81³å\87ºã\81\97å\81´ã\81«ã\81¦ç ´æ£\84ã\81\99ã\82\8bã\81\93ã\81¨
         /// </summary>
-        public bool TryGetSelectedMedia(out string imageService, out string[] imagePaths)
+        public bool TryGetSelectedMedia(out string imageService, out IMediaItem[] mediaItems)
         {
-            var validPaths = ImagePageCombo.Items.Cast<SelectedMedia>()
-                             .Where(x => x.IsValid).Select(x => x.Path).ToArray();
+            var validItems = ImagePageCombo.Items.Cast<SelectedMedia>()
+                             .Where(x => x.IsValid).Select(x => x.Item).OfType<IMediaItem>().ToArray();
 
-            if (validPaths.Length > 0 &&
+            if (validItems.Length > 0 &&
                 ImageServiceCombo.SelectedIndex > -1)
             {
                 var serviceName = this.ServiceName;
-                if (MessageBox.Show(string.Format(Properties.Resources.PostPictureConfirm1, serviceName, validPaths.Length),
+                if (MessageBox.Show(string.Format(Properties.Resources.PostPictureConfirm1, serviceName, validItems.Length),
                                    Properties.Resources.PostPictureConfirm2,
                                    MessageBoxButtons.OKCancel,
                                    MessageBoxIcon.Question,
                                    MessageBoxDefaultButton.Button1)
                                == DialogResult.OK)
                 {
+                    //収集した MediaItem が破棄されないように、予め null を代入しておく
+                    foreach (SelectedMedia media in ImagePageCombo.Items)
+                    {
+                        if (media != null) media.Item = null;
+                    }
+
                     imageService = serviceName;
-                    imagePaths = validPaths;
+                    mediaItems = validItems;
                     EndSelection();
                     SetImagePageCombo();
                     return true;
@@ -312,10 +367,66 @@ namespace OpenTween
 
             EndSelection();
             imageService = null;
-            imagePaths = null;
+            mediaItems = null;
             return false;
         }
 
+        private IMediaItem CreateMemoryImageMediaItem(Image image, bool noMsgBox)
+        {
+            if (image == null) return null;
+
+            try
+            {
+                return new MemoryImageMediaItem(image);
+            }
+            catch
+            {
+                if (!noMsgBox) MessageBox.Show("Unable to create MemoryImage.");
+                return null;
+            }
+        }
+
+        private IMediaItem CreateFileMediaItem(string path, bool noMsgBox)
+        {
+            if (string.IsNullOrEmpty(path)) return null;
+
+            try
+            {
+                return new FileMediaItem(path);
+            }
+            catch
+            {
+                if (!noMsgBox) MessageBox.Show("Invalid file path: " + path);
+                return null;
+            }
+        }
+
+        private void ValidateNewFileMediaItem(string path, bool noMsgBox)
+        {
+            var media = (SelectedMedia)ImagePageCombo.SelectedItem;
+            var item = media.Item;
+
+            if (path != media.Path)
+            {
+                DisposeMediaItem(media.Item);
+                media.Item = null;
+
+                item = CreateFileMediaItem(path, noMsgBox);
+            }
+
+            ImagefilePathText.Text = path;
+            ImageFromSelectedFile(item, noMsgBox);
+        }
+
+        private void DisposeMediaItem(IMediaItem item)
+        {
+            if (item != null)
+            {
+                var disposableItem = item as IDisposable;
+                if (disposableItem != null) disposableItem.Dispose();
+            }
+        }
+
         private void FilePickButton_Click(object sender, EventArgs e)
         {
             if (FilePickDialog == null || string.IsNullOrEmpty(this.ServiceName)) return;
@@ -336,8 +447,7 @@ namespace OpenTween
                     this.FilePickDialogClosed(this, EventArgs.Empty);
             }
 
-            ImagefilePathText.Text = FilePickDialog.FileName;
-            ImageFromSelectedFile(false);
+            ValidateNewFileMediaItem(FilePickDialog.FileName, false);
         }
 
         private void ImagefilePathText_Validating(object sender, CancelEventArgs e)
@@ -348,99 +458,111 @@ namespace OpenTween
                 return;
             }
 
-            ImageFromSelectedFile(false);
+            ValidateNewFileMediaItem(ImagefilePathText.Text.Trim(), false);
         }
 
-        private void ImageFromSelectedFile(bool suppressMsgBox)
+        private void ImageFromSelectedFile(IMediaItem item, bool noMsgBox)
         {
-            ImagefilePathText.Text = ImagefilePathText.Text.Trim();
-            ImageFromSelectedFile(-1, ImagefilePathText.Text, suppressMsgBox);
+            ImageFromSelectedFile(-1, item, noMsgBox);
         }
 
-        private void ImageFromSelectedFile(int index, string fileName, bool suppressMsgBox)
+        private void ImageFromSelectedFile(int index, IMediaItem item, bool noMsgBox)
         {
-            var serviceName = this.ServiceName;
-            if (string.IsNullOrEmpty(serviceName)) return;
+            var valid = false;
 
-            var selectedIndex = ImagePageCombo.SelectedIndex;
-            if (index < 0) index = selectedIndex;
+            try
+            {
+                var serviceName = this.ServiceName;
+                if (string.IsNullOrEmpty(serviceName)) return;
 
-            if (index >= ImagePageCombo.Items.Count)
-                throw new ArgumentOutOfRangeException("index");
+                var selectedIndex = ImagePageCombo.SelectedIndex;
+                if (index < 0) index = selectedIndex;
 
-            var imageService = this.pictureService[serviceName];
-            var isSelectedPage = (index == selectedIndex);
+                if (index >= ImagePageCombo.Items.Count)
+                    throw new ArgumentOutOfRangeException("index");
 
-            if (isSelectedPage)
-                this.ClearImageSelectedPicture();
+                var imageService = this.pictureService[serviceName];
+                var isSelectedPage = (index == selectedIndex);
 
-            if (string.IsNullOrEmpty(fileName))
-            {
-                ClearImagePage(index);
-                return;
-            }
+                if (isSelectedPage)
+                    this.ClearImageSelectedPicture();
 
-            try
-            {
-                FileInfo fl = new FileInfo(fileName);
-                string ext = fl.Extension;
+                if (item == null || string.IsNullOrEmpty(item.Path)) return;
 
-                if (!imageService.CheckFileExtension(ext))
+                try
                 {
-                    //画像以外の形式
-                    ClearImagePage(index);
-                    if (!suppressMsgBox)
+                    var ext = item.Extension;
+                    var size = item.Size;
+
+                    if (!imageService.CheckFileExtension(ext))
                     {
-                        MessageBox.Show(
-                            string.Format(Properties.Resources.PostPictureWarn3, serviceName, MakeAvailableServiceText(ext, fl.Length), ext, fl.Name),
-                            Properties.Resources.PostPictureWarn4,
-                            MessageBoxButtons.OK,
-                            MessageBoxIcon.Warning);
+                        //画像以外の形式
+                        if (!noMsgBox)
+                        {
+                            MessageBox.Show(
+                                string.Format(Properties.Resources.PostPictureWarn3, serviceName, MakeAvailableServiceText(ext, size), ext, item.Name),
+                                Properties.Resources.PostPictureWarn4,
+                                MessageBoxButtons.OK,
+                                MessageBoxIcon.Warning);
+                        }
+                        return;
                     }
-                    return;
-                }
 
-                if (!imageService.CheckFileSize(ext, fl.Length))
-                {
-                    // ファイルサイズが大きすぎる
-                    ClearImagePage(index);
-                    if (!suppressMsgBox)
+                    if (!imageService.CheckFileSize(ext, size))
                     {
-                        MessageBox.Show(
-                            string.Format(Properties.Resources.PostPictureWarn5, serviceName, MakeAvailableServiceText(ext, fl.Length), fl.Name),
-                            Properties.Resources.PostPictureWarn4,
-                            MessageBoxButtons.OK,
-                            MessageBoxIcon.Warning);
+                        // ファイルサイズが大きすぎる
+                        if (!noMsgBox)
+                        {
+                            MessageBox.Show(
+                                string.Format(Properties.Resources.PostPictureWarn5, serviceName, MakeAvailableServiceText(ext, size), item.Name),
+                                Properties.Resources.PostPictureWarn4,
+                                MessageBoxButtons.OK,
+                                MessageBoxIcon.Warning);
+                        }
+                        return;
                     }
-                    return;
-                }
 
-                try
-                {
-                    using (var fs = File.OpenRead(fileName))
+                    if (item is MemoryImageMediaItem)
                     {
-                        var image = MemoryImage.CopyFromStream(fs);
                         if (isSelectedPage)
-                            ImageSelectedPicture.Image = image;
-                        else
-                            image.Dispose();  //画像チェック後は使わないので破棄する
+                            ImageSelectedPicture.Image = item.CreateImage();
+                        SetImagePage(index, item, MyCommon.UploadFileType.Picture);
                     }
-                    SetImagePage(index, fileName, MyCommon.UploadFileType.Picture);
+                    else
+                    {
+                        try
+                        {
+                            var image = item.CreateImage();
+                            if (isSelectedPage)
+                                ImageSelectedPicture.Image = image;
+                            else
+                                image.Dispose();  //画像チェック後は使わないので破棄する
+                            SetImagePage(index, item, MyCommon.UploadFileType.Picture);
+                        }
+                        catch (InvalidImageException)
+                        {
+                            SetImagePage(index, item, MyCommon.UploadFileType.MultiMedia);
+                        }
+                    }
+
+                    valid = true;  //正常終了
                 }
-                catch (InvalidImageException)
+                catch (FileNotFoundException)
                 {
-                    SetImagePage(index, fileName, MyCommon.UploadFileType.MultiMedia);
+                    if (!noMsgBox) MessageBox.Show("File not found.");
+                }
+                catch (Exception)
+                {
+                    if (!noMsgBox) MessageBox.Show("The type of this file is not image.");
                 }
             }
-            catch (FileNotFoundException)
-            {
-                ClearImagePage(index);
-                if (!suppressMsgBox) MessageBox.Show("File not found.");
-            }
-            catch (Exception)
+            finally
             {
-                ClearImagePage(index);
-                if (!suppressMsgBox) MessageBox.Show("The type of this file is not image.");
+                if (!valid)
+                {
+                    ClearImagePage(index);
+                    DisposeMediaItem(item);
+                }
             }
         }
 
@@ -567,23 +689,32 @@ namespace OpenTween
                             else
                             {
                                 ImagePageCombo.Enabled = false;
+                                var valid = false;
 
                                 try
                                 {
-                                    FileInfo fi = new FileInfo(ImagefilePathText.Text.Trim());
-                                    string ext = fi.Extension;
-                                    var imageService = this.pictureService[serviceName];
-                                    if (!imageService.CheckFileExtension(ext) ||
-                                        !imageService.CheckFileSize(ext, fi.Length))
+                                    var item = ((SelectedMedia)ImagePageCombo.Items[0]).Item;
+                                    if (item != null)
                                     {
-                                        ClearImageSelectedPicture();
-                                        ClearSelectedImagePage();
+                                        var ext = item.Extension;
+                                        var imageService = this.pictureService[serviceName];
+                                        if (imageService.CheckFileExtension(ext) &&
+                                            imageService.CheckFileSize(ext, item.Size))
+                                        {
+                                            valid = true;
+                                        }
                                     }
                                 }
-                                catch (Exception)
+                                catch
+                                {
+                                }
+                                finally
                                 {
-                                    ClearImageSelectedPicture();
-                                    ClearSelectedImagePage();
+                                    if (!valid)
+                                    {
+                                        ClearImageSelectedPicture();
+                                        ClearSelectedImagePage();
+                                    }
                                 }
                             }
                         }
@@ -600,17 +731,20 @@ namespace OpenTween
             using (ControlTransaction.Update(ImagePageCombo))
             {
                 ImagePageCombo.Enabled = false;
-                ImagePageCombo.Items.Clear();
-                if (media != null)
-                {
-                    ImagePageCombo.Items.Add(media);
-                    ImagefilePathText.Text = media.Path;
-                }
-                else
+
+                foreach (SelectedMedia oldMedia in ImagePageCombo.Items)
                 {
-                    ImagePageCombo.Items.Add(new SelectedMedia("1"));
-                    ImagefilePathText.Text = "";
+                    if (oldMedia == null || oldMedia == media) continue;
+                    DisposeMediaItem(oldMedia.Item);
                 }
+                ImagePageCombo.Items.Clear();
+
+                if (media == null)
+                    media = new SelectedMedia("1");
+
+                ImagePageCombo.Items.Add(media);
+                ImagefilePathText.Text = media.Path;
+
                 ImagePageCombo.SelectedIndex = 0;
             }
         }
@@ -633,19 +767,23 @@ namespace OpenTween
             }
         }
 
-        private void SetSelectedImagePage(string path, MyCommon.UploadFileType type)
+        private void SetSelectedImagePage(IMediaItem item, MyCommon.UploadFileType type)
         {
-            SetImagePage(-1, path, type);
+            SetImagePage(-1, item, type);
         }
 
-        private void SetImagePage(int index, string path, MyCommon.UploadFileType type)
+        private void SetImagePage(int index, IMediaItem item, MyCommon.UploadFileType type)
         {
             var selectedIndex = ImagePageCombo.SelectedIndex;
             if (index < 0) index = selectedIndex;
 
-            var item = (SelectedMedia)ImagePageCombo.Items[index];
-            item.Path = path;
-            item.Type = type;
+            var media = (SelectedMedia)ImagePageCombo.Items[index];
+            if (media.Item != item)
+            {
+                DisposeMediaItem(media.Item);
+                media.Item = item;
+            }
+            media.Type = type;
 
             AddNewImagePage(index);
         }
@@ -660,9 +798,10 @@ namespace OpenTween
             var selectedIndex = ImagePageCombo.SelectedIndex;
             if (index < 0) index = selectedIndex;
 
-            var item = (SelectedMedia)ImagePageCombo.Items[index];
-            item.Path = "";
-            item.Type = MyCommon.UploadFileType.Invalid;
+            var media = (SelectedMedia)ImagePageCombo.Items[index];
+            DisposeMediaItem(media.Item);
+            media.Item = null;
+            media.Type = MyCommon.UploadFileType.Invalid;
 
             if (index == selectedIndex) ImagefilePathText.Text = "";
         }
@@ -670,10 +809,10 @@ namespace OpenTween
         private void ValidateSelectedImagePage()
         {
             var idx = ImagePageCombo.SelectedIndex;
-            var item = (SelectedMedia)ImagePageCombo.Items[idx];
+            var media = (SelectedMedia)ImagePageCombo.Items[idx];
             ImageServiceCombo.Enabled = (idx == 0);  // idx == 0 以外では投稿先サービスを選べないようにする
-            ImagefilePathText.Text = item.Path;
-            ImageFromSelectedFile(true);
+            ImagefilePathText.Text = media.Path;
+            ImageFromSelectedFile(media.Item, true);
         }
 
         private void ImagePageCombo_SelectedIndexChanged(object sender, EventArgs e)
index befe372..be9b64d 100644 (file)
     <Compile Include="FilterDialog.Designer.cs">
       <DependentUpon>FilterDialog.cs</DependentUpon>
     </Compile>
+    <Compile Include="MediaItem.cs" />
     <Compile Include="WaitingDialog.cs">
       <SubType>Form</SubType>
     </Compile>
index 4758a18..bfb1efa 100644 (file)
@@ -268,7 +268,7 @@ namespace OpenTween
             public long? inReplyToId = null;
             public string inReplyToName = null;
             public string imageService = "";      //画像投稿サービス名
-            public string[] imagePath = null;
+            public IMediaItem[] mediaItems = null;
             public PostingStatus()
             {
             }
@@ -2215,7 +2215,7 @@ namespace OpenTween
             if (ImageSelector.Visible)
             {
                 //画像投稿
-                if (!ImageSelector.TryGetSelectedMedia(out status.imageService, out status.imagePath))
+                if (!ImageSelector.TryGetSelectedMedia(out status.imageService, out status.mediaItems))
                     return;
             }
 
@@ -3141,7 +3141,7 @@ namespace OpenTween
             {
                 await Task.Run(async () =>
                 {
-                    if (status.imagePath == null || status.imagePath.Length == 0 || string.IsNullOrEmpty(status.imagePath[0]))
+                    if (status.mediaItems == null || status.mediaItems.Length == 0)
                     {
                         var err = this.tw.PostStatus(status.status, status.inReplyToId);
                         if (!string.IsNullOrEmpty(err))
@@ -3150,7 +3150,7 @@ namespace OpenTween
                     else
                     {
                         var service = ImageSelector.GetService(status.imageService);
-                        await service.PostStatusAsync(status.status, status.inReplyToId, status.imagePath)
+                        await service.PostStatusAsync(status.status, status.inReplyToId, status.mediaItems)
                             .ConfigureAwait(false);
                     }
                 });
@@ -3164,6 +3164,17 @@ namespace OpenTween
                 p.Report(errMsg);
                 this._myStatusError = true;
             }
+            finally
+            {
+                // 使い終わった MediaItem は破棄する
+                if (status.mediaItems != null)
+                {
+                    foreach (var disposableItem in status.mediaItems.OfType<IDisposable>())
+                    {
+                        disposableItem.Dispose();
+                    }
+                }
+            }
 
             if (ct.IsCancellationRequested)
                 return;
@@ -6811,12 +6822,6 @@ namespace OpenTween
                             // Webページを開く動作
                             OpenURLMenuItem_Click(null, null);
                             return true;
-                        case Keys.V:
-                            if( Focused == FocusedControl.StatusText ) {
-                                ProcClipboardFromStatusTextWhenCtrlPlusV();
-                                return true;
-                            }
-                            break;
                     }
                     //フォーカスList
                     if (Focused == FocusedControl.ListTab)
@@ -6863,6 +6868,9 @@ namespace OpenTween
                             case Keys.A:
                                 StatusText.SelectAll();
                                 return true;
+                            case Keys.V:
+                                ProcClipboardFromStatusTextWhenCtrlPlusV();
+                                return true;
                             case Keys.Up:
                             case Keys.Down:
                                 if (!string.IsNullOrWhiteSpace(StatusText.Text))
@@ -12731,22 +12739,22 @@ namespace OpenTween
         /// <summary>
         /// StatusTextでCtrl+Vが押下された時の処理
         /// </summary>
-        private void ProcClipboardFromStatusTextWhenCtrlPlusV() {
-            if( Clipboard.ContainsText() ) {
+        private void ProcClipboardFromStatusTextWhenCtrlPlusV()
+        {
+            if (Clipboard.ContainsText())
+            {
                 // clipboardにテキストがある場合は貼り付け処理
-                this.StatusText.Paste( Clipboard.GetText() );
-            } else if( Clipboard.ContainsImage() ) {
+                this.StatusText.Paste(Clipboard.GetText());
+            }
+            else if (Clipboard.ContainsImage())
+            {
                 // 画像があるので投稿処理を行う
 
                 // clipboardから画像を取得
-                var image = Clipboard.GetImage();
-                // 一時的に保存するためのパスを取得し、一旦保存を行う(png)
-                var path = string.Format( "{0}.png", Path.GetTempFileName() );
-                using( var fs = new FileStream( path, FileMode.Create ) ) {
-                    image.Save( fs, System.Drawing.Imaging.ImageFormat.Png );
-                }
-                // 保存したパスをImageSelectorに投げる
-                this.ImageSelector.BeginSelection( new string[] { path } );
+                using (var image = Clipboard.GetImage())
+                {
+                    this.ImageSelector.BeginSelection(image);
+                }
             }
         }
 #endregion
index bc85fda..8c324c6 100644 (file)
@@ -526,7 +526,7 @@ namespace OpenTween
             return "";
         }
 
-        public string PostStatusWithMedia(string postStr, long? reply_to, FileInfo mediaFile)
+        public string PostStatusWithMedia(string postStr, long? reply_to, IMediaItem item)
         {
             if (MyCommon._endingFlag) return "";
 
@@ -536,7 +536,7 @@ namespace OpenTween
             var content = "";
             try
             {
-                res = twCon.UpdateStatusWithMedia(postStr, reply_to, mediaFile, ref content);
+                res = twCon.UpdateStatusWithMedia(postStr, reply_to, item, ref content);
             }
             catch(Exception ex)
             {
@@ -577,7 +577,7 @@ namespace OpenTween
             return "";
         }
 
-        public string PostStatusWithMultipleMedia(string postStr, long? reply_to, List<FileInfo> mediaFiles)
+        public string PostStatusWithMultipleMedia(string postStr, long? reply_to, IMediaItem[] mediaItems)
         {
             if (MyCommon._endingFlag) return "";
 
@@ -590,10 +590,10 @@ namespace OpenTween
 
             var mediaIds = new List<long>();
 
-            foreach (var mediaFile in mediaFiles)
+            foreach (var item in mediaItems)
             {
                 long? mediaId = null;
-                var err = UploadMedia(mediaFile, ref mediaId);
+                var err = UploadMedia(item, ref mediaId);
                 if (!mediaId.HasValue || !string.IsNullOrEmpty(err)) return err;
                 mediaIds.Add(mediaId.Value);
             }
@@ -604,7 +604,7 @@ namespace OpenTween
             return PostStatus(postStr, reply_to, mediaIds);
         }
 
-        public string UploadMedia(FileInfo mediaFile, ref long? mediaId)
+        public string UploadMedia(IMediaItem item, ref long? mediaId)
         {
             if (MyCommon._endingFlag) return "";
 
@@ -614,7 +614,7 @@ namespace OpenTween
             var content = "";
             try
             {
-                res = twCon.UploadMedia(mediaFile, ref content);
+                res = twCon.UploadMedia(item, ref content);
             }
             catch (Exception ex)
             {