Merge lp:~kriomant/do-plugins/transmission into lp:do-plugins
- transmission
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 754 |
Proposed branch: | lp:~kriomant/do-plugins/transmission |
Merge into: | lp:do-plugins |
Diff against target: |
2699 lines (+2488/-0) (has conflicts) 30 files modified
.bzrignore (+9/-0) DoPlugins.mds (+4/-0) Makefile.am (+1/-0) Transmission/Makefile.am (+40/-0) Transmission/Resources/Transmission.addin.xml.in (+37/-0) Transmission/Transmission.mdp (+64/-0) Transmission/gtk-gui/Transmission.TransmissionConfig.cs (+161/-0) Transmission/gtk-gui/generated.cs (+82/-0) Transmission/gtk-gui/gui.stetic (+196/-0) Transmission/src/Config/TransmissionConfig.cs (+91/-0) Transmission/src/ITorrentEntry.cs (+16/-0) Transmission/src/JsonCollectionImporter.cs (+117/-0) Transmission/src/TorrentAbstractLimitSpeedAction.cs (+80/-0) Transmission/src/TorrentDirectoryItem.cs (+64/-0) Transmission/src/TorrentFileItem.cs (+97/-0) Transmission/src/TorrentFileSetPriorityAction.cs (+108/-0) Transmission/src/TorrentItem.cs (+72/-0) Transmission/src/TorrentItemSource.cs (+130/-0) Transmission/src/TorrentLimitDownloadSpeedAction.cs (+47/-0) Transmission/src/TorrentLimitUploadSpeedAction.cs (+47/-0) Transmission/src/TorrentMarkForDownloadAction.cs (+62/-0) Transmission/src/TorrentOperateAction.cs (+37/-0) Transmission/src/TorrentStartAction.cs (+42/-0) Transmission/src/TorrentStopAction.cs (+42/-0) Transmission/src/TorrentUnmarkForDownloadAction.cs (+62/-0) Transmission/src/TorrentVerifyAction.cs (+42/-0) Transmission/src/TransmissionAPI.cs (+575/-0) Transmission/src/TransmissionPlugin.cs (+50/-0) Transmission/src/Utils.cs (+111/-0) configure.ac (+2/-0) Text conflict in .bzrignore |
To merge this branch: | bzr merge lp:~kriomant/do-plugins/transmission |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Chris Halse Rogers | Needs Fixing | ||
Review via email: mp+30966@code.launchpad.net |
Commit message
Description of the change
Transmission plug-in.
Allows to control Transmission torrent client using XML-RPC API. Supports starting and stopping torrent downloads, choosing files to download, setting speed limits.
kriomant (kriomant) wrote : | # |
On 11 Dec 2011 10:16, "Chris Halse Rogers" <email address hidden> wrote:
>
> Review: Needs Fixing
>
> Oh, wow. Sorry for missing this for so long!
I thought development is completely stalled.
> This looks good. I've only got two minor niggles, and one larger one.
The two minor ones are: you should have copyright headers on the files
you've created, and I'd generally use a lot more automatic properties
rather than explicit private _foo variables.
>
> The major one is that it bundles a binary copy of Jayrock.Json. We
generally try to minimise the binaries we bundle in the source tree; most
distributions will not accept packages with binaries bundled like this.
How will you solve this? I haven't found JSON library for Mono in standard
Ubuntu distribution. Will you include source code of Jayrock?
> Given the terrible length of time that this has been waiting for a
review, I'm happy to make these changes myself if you don't want to. I
would like your email address, though, so that I can credit you in the
Authors file properly.
It would be good.
My address is "Mikhail Trishchenkov <email address hidden>"
One more question: should I write wiki page?
> --
> https:/
> You are the owner of lp:~kriomant/do-plugins/transmission.
Chris Halse Rogers (raof) wrote : | # |
I wouldn't bother writing a wiki page; I plan to take the wiki down, as it's become a hive of spam and villany and I don't have time to curate it properly.
I'll transfer the documentation into a local format, so it can be installed alongside the plugins. Once I've got that set up, you might want to add documentation there.
As for the JSON library, I'll see if Hyena.Json does what needs to be done here. If not, I'll grab the Jayrock source code and package it.
kriomant (kriomant) wrote : | # |
Is there any progress?
Chris Halse Rogers (raof) wrote : | # |
On Tue, 2012-01-10 at 17:33 +0000, kriomant wrote:
> Is there any progress?
Not on this, sorry. I'm slowly working my way through the blocker bugs
for the next core release. I hope to have that done this week or early
next week.
After I've done that I'll be able to work on plugins stuff, of which
this will be the first priority.
kriomant (kriomant) wrote : | # |
Bump
kriomant (kriomant) wrote : | # |
I have an impression that "this week" have already passed...
Chris Halse Rogers (raof) wrote : | # |
The longest week ever has ended!
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2010-06-29 08:19:20 +0000 |
3 | +++ .bzrignore 2010-07-26 16:47:47 +0000 |
4 | @@ -1,3 +1,4 @@ |
5 | +<<<<<<< TREE |
6 | Makefile.in |
7 | Makefile |
8 | *.pc |
9 | @@ -23,3 +24,11 @@ |
10 | *.addin.xml |
11 | *.gmo |
12 | m4/intltool.m4 |
13 | +======= |
14 | +Emesene.addin.xml |
15 | +Transmission/Makefile |
16 | +Transmission/Makefile.in |
17 | +Transmission/Transmission.pidb |
18 | +Transmission/bin |
19 | +Transmission/Resources/Transmission.addin.xml |
20 | +>>>>>>> MERGE-SOURCE |
21 | |
22 | === modified file 'DoPlugins.mds' |
23 | --- DoPlugins.mds 2009-11-08 23:58:01 +0000 |
24 | +++ DoPlugins.mds 2010-07-26 16:47:47 +0000 |
25 | @@ -78,6 +78,7 @@ |
26 | <Entry build="True" name="Baconator" configuration="Debug" /> |
27 | <Entry build="True" name="Chromium" configuration="Debug" /> |
28 | <Entry build="True" name="GNOME-Calculator" configuration="Debug" /> |
29 | + <Entry build="True" name="Transmission" configuration="Debug" /> |
30 | </Configuration> |
31 | <Configuration name="Release" ctype="CombineConfiguration"> |
32 | <Entry build="True" name="Rhythmbox" configuration="Release" /> |
33 | @@ -157,6 +158,7 @@ |
34 | <Entry build="True" name="Baconator" configuration="Release" /> |
35 | <Entry build="True" name="Chromium" configuration="Release" /> |
36 | <Entry build="True" name="GNOME-Calculator" configuration="Release" /> |
37 | + <Entry build="True" name="Transmission" configuration="Release" /> |
38 | </Configuration> |
39 | </Configurations> |
40 | <StartMode startupentry="Rhythmbox" single="True"> |
41 | @@ -237,6 +239,7 @@ |
42 | <Execute type="None" entry="Baconator" /> |
43 | <Execute type="None" entry="Chromium" /> |
44 | <Execute type="None" entry="GNOME-Calculator" /> |
45 | + <Execute type="None" entry="Transmission" /> |
46 | </StartMode> |
47 | <MonoDevelop.ChangeLogAddIn.ChangeLogInfo policy="UpdateNearestChangeLog" /> |
48 | <Entries> |
49 | @@ -317,5 +320,6 @@ |
50 | <Entry filename="Baconator/Baconator.mdp" /> |
51 | <Entry filename="Chromium/Chromium.mdp" /> |
52 | <Entry filename="GNOME-Calculator/GNOME-Calculator.mdp" /> |
53 | + <Entry filename="Transmission/Transmission.mdp" /> |
54 | </Entries> |
55 | </Combine> |
56 | \ No newline at end of file |
57 | |
58 | === modified file 'Makefile.am' |
59 | --- Makefile.am 2009-11-08 23:58:01 +0000 |
60 | +++ Makefile.am 2010-07-26 16:47:47 +0000 |
61 | @@ -70,6 +70,7 @@ |
62 | TinyUrl \ |
63 | Tracker \ |
64 | Translate \ |
65 | + Transmission \ |
66 | Tomboy \ |
67 | Vinagre \ |
68 | VirtualBox \ |
69 | |
70 | === added directory 'Transmission' |
71 | === added file 'Transmission/Makefile.am' |
72 | --- Transmission/Makefile.am 1970-01-01 00:00:00 +0000 |
73 | +++ Transmission/Makefile.am 2010-07-26 16:47:47 +0000 |
74 | @@ -0,0 +1,40 @@ |
75 | +include $(top_srcdir)/build.rules.mk |
76 | + |
77 | +ASSEMBLY=Transmission |
78 | + |
79 | +FILES = \ |
80 | + gtk-gui/Transmission.TransmissionConfig.cs \ |
81 | + gtk-gui/generated.cs \ |
82 | + src/Config/TransmissionConfig.cs \ |
83 | + src/ITorrentEntry.cs \ |
84 | + src/JsonCollectionImporter.cs \ |
85 | + src/Utils.cs \ |
86 | + src/TorrentDirectoryItem.cs \ |
87 | + src/TorrentFileItem.cs \ |
88 | + src/TorrentFileSetPriorityAction.cs \ |
89 | + src/TorrentItem.cs \ |
90 | + src/TorrentItemSource.cs \ |
91 | + src/TorrentAbstractLimitSpeedAction.cs \ |
92 | + src/TorrentLimitDownloadSpeedAction.cs \ |
93 | + src/TorrentLimitUploadSpeedAction.cs \ |
94 | + src/TorrentMarkForDownloadAction.cs \ |
95 | + src/TorrentStartAction.cs \ |
96 | + src/TorrentStopAction.cs \ |
97 | + src/TorrentUnmarkForDownloadAction.cs \ |
98 | + src/TorrentVerifyAction.cs \ |
99 | + src/TorrentOperateAction.cs \ |
100 | + src/TransmissionAPI.cs \ |
101 | + src/TransmissionPlugin.cs |
102 | + |
103 | +RESOURCES = \ |
104 | + Resources/Transmission.addin.xml \ |
105 | + gtk-gui/gui.stetic \ |
106 | + Resources/icons/transmission.png |
107 | + |
108 | +REFERENCES = \ |
109 | + System \ |
110 | + System.Core \ |
111 | + lib/Jayrock.Json.dll \ |
112 | + $(DO_PLATFORM_LINUX_LIBS) \ |
113 | + $(DO_UNIVERSE_LIBS) \ |
114 | + $(GTK_SHARP_20_LIBS) |
115 | |
116 | === added directory 'Transmission/Resources' |
117 | === added file 'Transmission/Resources/Transmission.addin.xml.in' |
118 | --- Transmission/Resources/Transmission.addin.xml.in 1970-01-01 00:00:00 +0000 |
119 | +++ Transmission/Resources/Transmission.addin.xml.in 2010-07-26 16:47:47 +0000 |
120 | @@ -0,0 +1,37 @@ |
121 | +<Addin |
122 | + id="Transmission" |
123 | + namespace="Do" |
124 | + version="0.1" |
125 | + name="Transmission" |
126 | + description="Control Transmission torrent client." |
127 | + author="Mikhail Trishchenkov" |
128 | + category="Community" |
129 | + defaultEnabled="true" |
130 | + url="http://do.davebsd.com/wiki/Transmission_Plugin" |
131 | + > |
132 | + |
133 | + <Runtime> |
134 | + <Import assembly="Transmission.dll"/> |
135 | + </Runtime> |
136 | + |
137 | + <!--Localizer type="Gettext" catalog="gnome-do-plugins" location="@expanded_datadir@/locale" /--> |
138 | + |
139 | + <Dependencies> |
140 | + <Addin id="Universe" version="1.0" /> |
141 | + </Dependencies> |
142 | + |
143 | + <Extension path="/Do/ItemSource"> |
144 | + <ItemSource type="Transmission.TorrentItemSource" /> |
145 | + </Extension> |
146 | + <Extension path="/Do/Action"> |
147 | + <Action type="Transmission.TorrentStopAction" /> |
148 | + <Action type="Transmission.TorrentStartAction" /> |
149 | + <Action type="Transmission.TorrentVerifyAction" /> |
150 | + <Action type="Transmission.TorrentLimitDownloadSpeedAction" /> |
151 | + <Action type="Transmission.TorrentLimitUploadSpeedAction" /> |
152 | + <Action type="Transmission.TorrentFileSetPriorityAction" /> |
153 | + <Action type="Transmission.TorrentMarkForDownloadAction" /> |
154 | + <Action type="Transmission.TorrentUnmarkForDownloadAction" /> |
155 | + <Action type="Transmission.TorrentOperateAction" /> |
156 | + </Extension> |
157 | +</Addin> |
158 | |
159 | === added directory 'Transmission/Resources/icons' |
160 | === added file 'Transmission/Resources/icons/transmission.png' |
161 | Binary files Transmission/Resources/icons/transmission.png 1970-01-01 00:00:00 +0000 and Transmission/Resources/icons/transmission.png 2010-07-26 16:47:47 +0000 differ |
162 | === added file 'Transmission/Transmission.mdp' |
163 | --- Transmission/Transmission.mdp 1970-01-01 00:00:00 +0000 |
164 | +++ Transmission/Transmission.mdp 2010-07-26 16:47:47 +0000 |
165 | @@ -0,0 +1,64 @@ |
166 | +<Project name="Transmission" fileversion="2.0" DefaultNamespace="Transmission" language="C#" targetFramework="3.5" ctype="DotNetProject"> |
167 | + <Configurations active="Debug"> |
168 | + <Configuration name="Debug" ctype="DotNetProjectConfiguration"> |
169 | + <Output directory="bin/Debug" assembly="Transmission" /> |
170 | + <Build debugmode="True" target="Library" /> |
171 | + <Execution consolepause="True" runwithwarnings="True" runtime="MsNet" /> |
172 | + <CodeGeneration compiler="Mcs" warninglevel="4" optimize="False" unsafecodeallowed="False" generateoverflowchecks="False" definesymbols="DEBUG" generatexmldocumentation="False" ctype="CSharpCompilerParameters" /> |
173 | + </Configuration> |
174 | + <Configuration name="Release" ctype="DotNetProjectConfiguration"> |
175 | + <Output directory="bin/Release" assembly="Transmission" /> |
176 | + <Build debugmode="False" target="Library" /> |
177 | + <Execution consolepause="True" runwithwarnings="True" runtime="MsNet" /> |
178 | + <CodeGeneration compiler="Mcs" warninglevel="4" optimize="False" unsafecodeallowed="False" generateoverflowchecks="False" generatexmldocumentation="False" ctype="CSharpCompilerParameters" /> |
179 | + </Configuration> |
180 | + </Configurations> |
181 | + <Contents> |
182 | + <File subtype="Directory" buildaction="Compile" name="src" /> |
183 | + <File subtype="Directory" buildaction="Compile" name="Resources" /> |
184 | + <File subtype="Code" buildaction="Nothing" name="Resources/Transmission.addin.xml" /> |
185 | + <File subtype="Code" buildaction="EmbedAsResource" name="gtk-gui/gui.stetic" /> |
186 | + <File subtype="Code" buildaction="Compile" name="gtk-gui/generated.cs" /> |
187 | + <File subtype="Code" buildaction="Compile" name="gtk-gui/Transmission.TransmissionConfig.cs" /> |
188 | + <File subtype="Code" buildaction="Compile" name="src/Config/TransmissionConfig.cs" /> |
189 | + <File subtype="Directory" buildaction="Compile" name="Resources/icons" /> |
190 | + <File subtype="Code" buildaction="Nothing" name="Resources/icons/transmission-add.png" /> |
191 | + <File subtype="Code" buildaction="Nothing" name="Resources/icons/transmission-remove.png" /> |
192 | + <File subtype="Code" buildaction="Nothing" name="Resources/icons/transmission-revisions.png" /> |
193 | + <File subtype="Code" buildaction="Nothing" name="Resources/icons/transmission-share.png" /> |
194 | + <File subtype="Code" buildaction="Nothing" name="Resources/icons/transmission-start.png" /> |
195 | + <File subtype="Code" buildaction="Nothing" name="Resources/icons/transmission-stop.png" /> |
196 | + <File subtype="Code" buildaction="Nothing" name="Resources/icons/transmission-web.png" /> |
197 | + <File subtype="Code" buildaction="Compile" name="src/ITorrentEntry.cs" /> |
198 | + <File subtype="Code" buildaction="Compile" name="src/JsonCollectionImporter.cs" /> |
199 | + <File subtype="Code" buildaction="Compile" name="src/TorrentDirectoryItem.cs" /> |
200 | + <File subtype="Code" buildaction="Compile" name="src/TorrentFileItem.cs" /> |
201 | + <File subtype="Code" buildaction="Compile" name="src/TorrentFileSetPriorityAction.cs" /> |
202 | + <File subtype="Code" buildaction="Compile" name="src/TorrentItem.cs" /> |
203 | + <File subtype="Code" buildaction="Compile" name="src/TorrentItemSource.cs" /> |
204 | + <File subtype="Code" buildaction="Compile" name="src/TorrentAbstractLimitSpeedAction.cs" /> |
205 | + <File subtype="Code" buildaction="Compile" name="src/TorrentLimitDownloadSpeedAction.cs" /> |
206 | + <File subtype="Code" buildaction="Compile" name="src/TorrentMarkForDownloadAction.cs" /> |
207 | + <File subtype="Code" buildaction="Compile" name="src/TorrentStartAction.cs" /> |
208 | + <File subtype="Code" buildaction="Compile" name="src/TorrentStopAction.cs" /> |
209 | + <File subtype="Code" buildaction="Compile" name="src/TorrentUnmarkForDownloadAction.cs" /> |
210 | + <File subtype="Code" buildaction="Compile" name="src/TorrentVerifyAction.cs" /> |
211 | + <File subtype="Code" buildaction="Compile" name="src/TransmissionAPI.cs" /> |
212 | + <File subtype="Code" buildaction="Compile" name="src/TransmissionPlugin.cs" /> |
213 | + <File subtype="Code" buildaction="Compile" name="src/Utils.cs" /> |
214 | + <File subtype="Code" buildaction="Compile" name="src/TorrentLimitUploadSpeedAction.cs" /> |
215 | + <File subtype="Code" buildaction="Compile" name="src/TorrentOperateAction.cs" /> |
216 | + </Contents> |
217 | + <References> |
218 | + <ProjectReference type="Gac" localcopy="True" refto="gtk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> |
219 | + <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" /> |
220 | + <ProjectReference type="Gac" localcopy="True" refto="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> |
221 | + <ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> |
222 | + <ProjectReference type="Gac" localcopy="True" refto="Mono.Addins, Version=0.4.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" /> |
223 | + <ProjectReference type="Gac" localcopy="True" refto="Do.Platform, Version=0.9.0.0, Culture=neutral" /> |
224 | + <ProjectReference type="Gac" localcopy="True" refto="Do.Universe, Version=0.9.0.0, Culture=neutral" /> |
225 | + <ProjectReference type="Gac" localcopy="True" refto="Do.Platform.Linux, Version=0.9.0.0, Culture=neutral" /> |
226 | + <ProjectReference type="Assembly" localcopy="True" specificVersion="False" refto="lib/Jayrock.Json.dll" /> |
227 | + </References> |
228 | + <GtkDesignInfo gettextClass="Mono.Addins.AddinManager.CurrentLocalizer" /> |
229 | +</Project> |
230 | \ No newline at end of file |
231 | |
232 | === added directory 'Transmission/gtk-gui' |
233 | === added file 'Transmission/gtk-gui/Transmission.TransmissionConfig.cs' |
234 | --- Transmission/gtk-gui/Transmission.TransmissionConfig.cs 1970-01-01 00:00:00 +0000 |
235 | +++ Transmission/gtk-gui/Transmission.TransmissionConfig.cs 2010-07-26 16:47:47 +0000 |
236 | @@ -0,0 +1,161 @@ |
237 | +// ------------------------------------------------------------------------------ |
238 | +// <autogenerated> |
239 | +// This code was generated by a tool. |
240 | +// |
241 | +// |
242 | +// Changes to this file may cause incorrect behavior and will be lost if |
243 | +// the code is regenerated. |
244 | +// </autogenerated> |
245 | +// ------------------------------------------------------------------------------ |
246 | + |
247 | +namespace Transmission { |
248 | + |
249 | + |
250 | + public partial class TransmissionConfig { |
251 | + |
252 | + private Gtk.Alignment alignment108; |
253 | + |
254 | + private Gtk.Table table1; |
255 | + |
256 | + private Gtk.HBox hbox1; |
257 | + |
258 | + private Gtk.Entry address_entry; |
259 | + |
260 | + private Gtk.Label remote_port_label; |
261 | + |
262 | + private Gtk.Entry port_entry; |
263 | + |
264 | + private Gtk.Label label1; |
265 | + |
266 | + private Gtk.Label label2; |
267 | + |
268 | + private Gtk.Label label3; |
269 | + |
270 | + private Gtk.Entry password_entry; |
271 | + |
272 | + private Gtk.Entry user_name_entry; |
273 | + |
274 | + protected virtual void Build() { |
275 | + Stetic.Gui.Initialize(this); |
276 | + // Widget Transmission.TransmissionConfig |
277 | + Stetic.BinContainer.Attach(this); |
278 | + this.Name = "Transmission.TransmissionConfig"; |
279 | + // Container child Transmission.TransmissionConfig.Gtk.Container+ContainerChild |
280 | + this.alignment108 = new Gtk.Alignment(0.5F, 0F, 1F, 0F); |
281 | + this.alignment108.Name = "alignment108"; |
282 | + // Container child alignment108.Gtk.Container+ContainerChild |
283 | + this.table1 = new Gtk.Table(((uint)(3)), ((uint)(2)), false); |
284 | + this.table1.Name = "table1"; |
285 | + this.table1.RowSpacing = ((uint)(6)); |
286 | + this.table1.ColumnSpacing = ((uint)(6)); |
287 | + // Container child table1.Gtk.Table+TableChild |
288 | + this.hbox1 = new Gtk.HBox(); |
289 | + this.hbox1.Name = "hbox1"; |
290 | + this.hbox1.Spacing = 6; |
291 | + // Container child hbox1.Gtk.Box+BoxChild |
292 | + this.address_entry = new Gtk.Entry(); |
293 | + this.address_entry.CanFocus = true; |
294 | + this.address_entry.Name = "address_entry"; |
295 | + this.address_entry.IsEditable = true; |
296 | + this.address_entry.InvisibleChar = '●'; |
297 | + this.hbox1.Add(this.address_entry); |
298 | + Gtk.Box.BoxChild w1 = ((Gtk.Box.BoxChild)(this.hbox1[this.address_entry])); |
299 | + w1.Position = 0; |
300 | + // Container child hbox1.Gtk.Box+BoxChild |
301 | + this.remote_port_label = new Gtk.Label(); |
302 | + this.remote_port_label.Name = "remote_port_label"; |
303 | + this.remote_port_label.LabelProp = Mono.Addins.AddinManager.CurrentLocalizer.GetString("Port"); |
304 | + this.hbox1.Add(this.remote_port_label); |
305 | + Gtk.Box.BoxChild w2 = ((Gtk.Box.BoxChild)(this.hbox1[this.remote_port_label])); |
306 | + w2.Position = 1; |
307 | + w2.Expand = false; |
308 | + w2.Fill = false; |
309 | + // Container child hbox1.Gtk.Box+BoxChild |
310 | + this.port_entry = new Gtk.Entry(); |
311 | + this.port_entry.CanFocus = true; |
312 | + this.port_entry.Name = "port_entry"; |
313 | + this.port_entry.IsEditable = true; |
314 | + this.port_entry.WidthChars = 5; |
315 | + this.port_entry.MaxLength = 5; |
316 | + this.port_entry.InvisibleChar = '●'; |
317 | + this.hbox1.Add(this.port_entry); |
318 | + Gtk.Box.BoxChild w3 = ((Gtk.Box.BoxChild)(this.hbox1[this.port_entry])); |
319 | + w3.Position = 2; |
320 | + w3.Expand = false; |
321 | + this.table1.Add(this.hbox1); |
322 | + Gtk.Table.TableChild w4 = ((Gtk.Table.TableChild)(this.table1[this.hbox1])); |
323 | + w4.LeftAttach = ((uint)(1)); |
324 | + w4.RightAttach = ((uint)(2)); |
325 | + w4.YOptions = ((Gtk.AttachOptions)(4)); |
326 | + // Container child table1.Gtk.Table+TableChild |
327 | + this.label1 = new Gtk.Label(); |
328 | + this.label1.Name = "label1"; |
329 | + this.label1.Xalign = 0F; |
330 | + this.label1.LabelProp = Mono.Addins.AddinManager.CurrentLocalizer.GetString("_Address"); |
331 | + this.label1.UseUnderline = true; |
332 | + this.table1.Add(this.label1); |
333 | + Gtk.Table.TableChild w5 = ((Gtk.Table.TableChild)(this.table1[this.label1])); |
334 | + w5.XOptions = ((Gtk.AttachOptions)(4)); |
335 | + w5.YOptions = ((Gtk.AttachOptions)(4)); |
336 | + // Container child table1.Gtk.Table+TableChild |
337 | + this.label2 = new Gtk.Label(); |
338 | + this.label2.Name = "label2"; |
339 | + this.label2.Xalign = 0F; |
340 | + this.label2.LabelProp = Mono.Addins.AddinManager.CurrentLocalizer.GetString("_Password"); |
341 | + this.label2.UseUnderline = true; |
342 | + this.table1.Add(this.label2); |
343 | + Gtk.Table.TableChild w6 = ((Gtk.Table.TableChild)(this.table1[this.label2])); |
344 | + w6.TopAttach = ((uint)(2)); |
345 | + w6.BottomAttach = ((uint)(3)); |
346 | + w6.XOptions = ((Gtk.AttachOptions)(4)); |
347 | + w6.YOptions = ((Gtk.AttachOptions)(4)); |
348 | + // Container child table1.Gtk.Table+TableChild |
349 | + this.label3 = new Gtk.Label(); |
350 | + this.label3.Name = "label3"; |
351 | + this.label3.Xalign = 0F; |
352 | + this.label3.LabelProp = Mono.Addins.AddinManager.CurrentLocalizer.GetString("_Login"); |
353 | + this.label3.UseUnderline = true; |
354 | + this.table1.Add(this.label3); |
355 | + Gtk.Table.TableChild w7 = ((Gtk.Table.TableChild)(this.table1[this.label3])); |
356 | + w7.TopAttach = ((uint)(1)); |
357 | + w7.BottomAttach = ((uint)(2)); |
358 | + w7.XOptions = ((Gtk.AttachOptions)(4)); |
359 | + w7.YOptions = ((Gtk.AttachOptions)(4)); |
360 | + // Container child table1.Gtk.Table+TableChild |
361 | + this.password_entry = new Gtk.Entry(); |
362 | + this.password_entry.CanFocus = true; |
363 | + this.password_entry.Name = "password_entry"; |
364 | + this.password_entry.IsEditable = true; |
365 | + this.password_entry.Visibility = false; |
366 | + this.password_entry.InvisibleChar = '●'; |
367 | + this.table1.Add(this.password_entry); |
368 | + Gtk.Table.TableChild w8 = ((Gtk.Table.TableChild)(this.table1[this.password_entry])); |
369 | + w8.TopAttach = ((uint)(2)); |
370 | + w8.BottomAttach = ((uint)(3)); |
371 | + w8.LeftAttach = ((uint)(1)); |
372 | + w8.RightAttach = ((uint)(2)); |
373 | + w8.YOptions = ((Gtk.AttachOptions)(4)); |
374 | + // Container child table1.Gtk.Table+TableChild |
375 | + this.user_name_entry = new Gtk.Entry(); |
376 | + this.user_name_entry.CanFocus = true; |
377 | + this.user_name_entry.Name = "user_name_entry"; |
378 | + this.user_name_entry.IsEditable = true; |
379 | + this.user_name_entry.InvisibleChar = '●'; |
380 | + this.table1.Add(this.user_name_entry); |
381 | + Gtk.Table.TableChild w9 = ((Gtk.Table.TableChild)(this.table1[this.user_name_entry])); |
382 | + w9.TopAttach = ((uint)(1)); |
383 | + w9.BottomAttach = ((uint)(2)); |
384 | + w9.LeftAttach = ((uint)(1)); |
385 | + w9.RightAttach = ((uint)(2)); |
386 | + w9.YOptions = ((Gtk.AttachOptions)(4)); |
387 | + this.alignment108.Add(this.table1); |
388 | + this.Add(this.alignment108); |
389 | + if ((this.Child != null)) { |
390 | + this.Child.ShowAll(); |
391 | + } |
392 | + this.Hide(); |
393 | + this.user_name_entry.Changed += new System.EventHandler(this.OnUserNameEntryChanged); |
394 | + this.password_entry.Changed += new System.EventHandler(this.OnPasswordEntryChanged); |
395 | + } |
396 | + } |
397 | +} |
398 | |
399 | === added file 'Transmission/gtk-gui/generated.cs' |
400 | --- Transmission/gtk-gui/generated.cs 1970-01-01 00:00:00 +0000 |
401 | +++ Transmission/gtk-gui/generated.cs 2010-07-26 16:47:47 +0000 |
402 | @@ -0,0 +1,82 @@ |
403 | +// ------------------------------------------------------------------------------ |
404 | +// <autogenerated> |
405 | +// This code was generated by a tool. |
406 | +// |
407 | +// |
408 | +// Changes to this file may cause incorrect behavior and will be lost if |
409 | +// the code is regenerated. |
410 | +// </autogenerated> |
411 | +// ------------------------------------------------------------------------------ |
412 | + |
413 | +namespace Stetic { |
414 | + |
415 | + |
416 | + internal class Gui { |
417 | + |
418 | + private static bool initialized; |
419 | + |
420 | + internal static void Initialize(Gtk.Widget iconRenderer) { |
421 | + if ((Stetic.Gui.initialized == false)) { |
422 | + Stetic.Gui.initialized = true; |
423 | + } |
424 | + } |
425 | + } |
426 | + |
427 | + internal class BinContainer { |
428 | + |
429 | + private Gtk.Widget child; |
430 | + |
431 | + private Gtk.UIManager uimanager; |
432 | + |
433 | + public static BinContainer Attach(Gtk.Bin bin) { |
434 | + BinContainer bc = new BinContainer(); |
435 | + bin.SizeRequested += new Gtk.SizeRequestedHandler(bc.OnSizeRequested); |
436 | + bin.SizeAllocated += new Gtk.SizeAllocatedHandler(bc.OnSizeAllocated); |
437 | + bin.Added += new Gtk.AddedHandler(bc.OnAdded); |
438 | + return bc; |
439 | + } |
440 | + |
441 | + private void OnSizeRequested(object sender, Gtk.SizeRequestedArgs args) { |
442 | + if ((this.child != null)) { |
443 | + args.Requisition = this.child.SizeRequest(); |
444 | + } |
445 | + } |
446 | + |
447 | + private void OnSizeAllocated(object sender, Gtk.SizeAllocatedArgs args) { |
448 | + if ((this.child != null)) { |
449 | + this.child.Allocation = args.Allocation; |
450 | + } |
451 | + } |
452 | + |
453 | + private void OnAdded(object sender, Gtk.AddedArgs args) { |
454 | + this.child = args.Widget; |
455 | + } |
456 | + |
457 | + public void SetUiManager(Gtk.UIManager uim) { |
458 | + this.uimanager = uim; |
459 | + this.child.Realized += new System.EventHandler(this.OnRealized); |
460 | + } |
461 | + |
462 | + private void OnRealized(object sender, System.EventArgs args) { |
463 | + if ((this.uimanager != null)) { |
464 | + Gtk.Widget w; |
465 | + w = this.child.Toplevel; |
466 | + if (((w != null) && typeof(Gtk.Window).IsInstanceOfType(w))) { |
467 | + ((Gtk.Window)(w)).AddAccelGroup(this.uimanager.AccelGroup); |
468 | + this.uimanager = null; |
469 | + } |
470 | + } |
471 | + } |
472 | + } |
473 | + |
474 | + internal class ActionGroups { |
475 | + |
476 | + public static Gtk.ActionGroup GetActionGroup(System.Type type) { |
477 | + return Stetic.ActionGroups.GetActionGroup(type.FullName); |
478 | + } |
479 | + |
480 | + public static Gtk.ActionGroup GetActionGroup(string name) { |
481 | + return null; |
482 | + } |
483 | + } |
484 | +} |
485 | |
486 | === added file 'Transmission/gtk-gui/gui.stetic' |
487 | --- Transmission/gtk-gui/gui.stetic 1970-01-01 00:00:00 +0000 |
488 | +++ Transmission/gtk-gui/gui.stetic 2010-07-26 16:47:47 +0000 |
489 | @@ -0,0 +1,196 @@ |
490 | +<?xml version="1.0" encoding="utf-8"?> |
491 | +<stetic-interface> |
492 | + <configuration> |
493 | + <images-root-path>..</images-root-path> |
494 | + <target-gtk-version>2.12</target-gtk-version> |
495 | + </configuration> |
496 | + <import> |
497 | + <widget-library name="Do.Platform.Linux, Version=0.9.0.0, Culture=neutral" /> |
498 | + <widget-library name="../bin/Debug/Transmission.dll" internal="true" /> |
499 | + </import> |
500 | + <widget class="Gtk.Bin" id="Transmission.TransmissionConfig" design-size="444 300"> |
501 | + <property name="MemberName" /> |
502 | + <property name="Visible">False</property> |
503 | + <child> |
504 | + <widget class="Gtk.Alignment" id="alignment108"> |
505 | + <property name="MemberName" /> |
506 | + <property name="Yscale">0</property> |
507 | + <property name="Yalign">0</property> |
508 | + <child> |
509 | + <widget class="Gtk.Table" id="table1"> |
510 | + <property name="MemberName" /> |
511 | + <property name="NRows">3</property> |
512 | + <property name="NColumns">2</property> |
513 | + <property name="RowSpacing">6</property> |
514 | + <property name="ColumnSpacing">6</property> |
515 | + <child> |
516 | + <widget class="Gtk.HBox" id="hbox1"> |
517 | + <property name="MemberName" /> |
518 | + <property name="Spacing">6</property> |
519 | + <child> |
520 | + <widget class="Gtk.Entry" id="address_entry"> |
521 | + <property name="MemberName" /> |
522 | + <property name="CanFocus">True</property> |
523 | + <property name="IsEditable">True</property> |
524 | + <property name="InvisibleChar">●</property> |
525 | + </widget> |
526 | + <packing> |
527 | + <property name="Position">0</property> |
528 | + <property name="AutoSize">True</property> |
529 | + </packing> |
530 | + </child> |
531 | + <child> |
532 | + <widget class="Gtk.Label" id="remote_port_label"> |
533 | + <property name="MemberName">remote_port_label</property> |
534 | + <property name="LabelProp" translatable="yes">Port</property> |
535 | + </widget> |
536 | + <packing> |
537 | + <property name="Position">1</property> |
538 | + <property name="AutoSize">True</property> |
539 | + <property name="Expand">False</property> |
540 | + <property name="Fill">False</property> |
541 | + </packing> |
542 | + </child> |
543 | + <child> |
544 | + <widget class="Gtk.Entry" id="port_entry"> |
545 | + <property name="MemberName">port_entry</property> |
546 | + <property name="CanFocus">True</property> |
547 | + <property name="IsEditable">True</property> |
548 | + <property name="WidthChars">5</property> |
549 | + <property name="MaxLength">5</property> |
550 | + <property name="InvisibleChar">●</property> |
551 | + </widget> |
552 | + <packing> |
553 | + <property name="Position">2</property> |
554 | + <property name="AutoSize">False</property> |
555 | + <property name="Expand">False</property> |
556 | + </packing> |
557 | + </child> |
558 | + </widget> |
559 | + <packing> |
560 | + <property name="LeftAttach">1</property> |
561 | + <property name="RightAttach">2</property> |
562 | + <property name="AutoSize">True</property> |
563 | + <property name="YOptions">Fill</property> |
564 | + <property name="XExpand">True</property> |
565 | + <property name="XFill">True</property> |
566 | + <property name="XShrink">False</property> |
567 | + <property name="YExpand">False</property> |
568 | + <property name="YFill">True</property> |
569 | + <property name="YShrink">False</property> |
570 | + </packing> |
571 | + </child> |
572 | + <child> |
573 | + <widget class="Gtk.Label" id="label1"> |
574 | + <property name="MemberName" /> |
575 | + <property name="Xalign">0</property> |
576 | + <property name="LabelProp" translatable="yes">_Address</property> |
577 | + <property name="UseUnderline">True</property> |
578 | + </widget> |
579 | + <packing> |
580 | + <property name="AutoSize">True</property> |
581 | + <property name="XOptions">Fill</property> |
582 | + <property name="YOptions">Fill</property> |
583 | + <property name="XExpand">False</property> |
584 | + <property name="XFill">True</property> |
585 | + <property name="XShrink">False</property> |
586 | + <property name="YExpand">False</property> |
587 | + <property name="YFill">True</property> |
588 | + <property name="YShrink">False</property> |
589 | + </packing> |
590 | + </child> |
591 | + <child> |
592 | + <widget class="Gtk.Label" id="label2"> |
593 | + <property name="MemberName" /> |
594 | + <property name="Xalign">0</property> |
595 | + <property name="LabelProp" translatable="yes">_Password</property> |
596 | + <property name="UseUnderline">True</property> |
597 | + </widget> |
598 | + <packing> |
599 | + <property name="TopAttach">2</property> |
600 | + <property name="BottomAttach">3</property> |
601 | + <property name="AutoSize">True</property> |
602 | + <property name="XOptions">Fill</property> |
603 | + <property name="YOptions">Fill</property> |
604 | + <property name="XExpand">False</property> |
605 | + <property name="XFill">True</property> |
606 | + <property name="XShrink">False</property> |
607 | + <property name="YExpand">False</property> |
608 | + <property name="YFill">True</property> |
609 | + <property name="YShrink">False</property> |
610 | + </packing> |
611 | + </child> |
612 | + <child> |
613 | + <widget class="Gtk.Label" id="label3"> |
614 | + <property name="MemberName" /> |
615 | + <property name="Xalign">0</property> |
616 | + <property name="LabelProp" translatable="yes">_Login</property> |
617 | + <property name="UseUnderline">True</property> |
618 | + </widget> |
619 | + <packing> |
620 | + <property name="TopAttach">1</property> |
621 | + <property name="BottomAttach">2</property> |
622 | + <property name="AutoSize">True</property> |
623 | + <property name="XOptions">Fill</property> |
624 | + <property name="YOptions">Fill</property> |
625 | + <property name="XExpand">False</property> |
626 | + <property name="XFill">True</property> |
627 | + <property name="XShrink">False</property> |
628 | + <property name="YExpand">False</property> |
629 | + <property name="YFill">True</property> |
630 | + <property name="YShrink">False</property> |
631 | + </packing> |
632 | + </child> |
633 | + <child> |
634 | + <widget class="Gtk.Entry" id="password_entry"> |
635 | + <property name="MemberName" /> |
636 | + <property name="CanFocus">True</property> |
637 | + <property name="IsEditable">True</property> |
638 | + <property name="Visibility">False</property> |
639 | + <property name="InvisibleChar">●</property> |
640 | + <signal name="Changed" handler="OnPasswordEntryChanged" /> |
641 | + </widget> |
642 | + <packing> |
643 | + <property name="TopAttach">2</property> |
644 | + <property name="BottomAttach">3</property> |
645 | + <property name="LeftAttach">1</property> |
646 | + <property name="RightAttach">2</property> |
647 | + <property name="AutoSize">True</property> |
648 | + <property name="YOptions">Fill</property> |
649 | + <property name="XExpand">True</property> |
650 | + <property name="XFill">True</property> |
651 | + <property name="XShrink">False</property> |
652 | + <property name="YExpand">False</property> |
653 | + <property name="YFill">True</property> |
654 | + <property name="YShrink">False</property> |
655 | + </packing> |
656 | + </child> |
657 | + <child> |
658 | + <widget class="Gtk.Entry" id="user_name_entry"> |
659 | + <property name="MemberName" /> |
660 | + <property name="CanFocus">True</property> |
661 | + <property name="IsEditable">True</property> |
662 | + <property name="InvisibleChar">●</property> |
663 | + <signal name="Changed" handler="OnUserNameEntryChanged" /> |
664 | + </widget> |
665 | + <packing> |
666 | + <property name="TopAttach">1</property> |
667 | + <property name="BottomAttach">2</property> |
668 | + <property name="LeftAttach">1</property> |
669 | + <property name="RightAttach">2</property> |
670 | + <property name="AutoSize">True</property> |
671 | + <property name="YOptions">Fill</property> |
672 | + <property name="XExpand">True</property> |
673 | + <property name="XFill">True</property> |
674 | + <property name="XShrink">False</property> |
675 | + <property name="YExpand">False</property> |
676 | + <property name="YFill">True</property> |
677 | + <property name="YShrink">False</property> |
678 | + </packing> |
679 | + </child> |
680 | + </widget> |
681 | + </child> |
682 | + </widget> |
683 | + </child> |
684 | + </widget> |
685 | +</stetic-interface> |
686 | \ No newline at end of file |
687 | |
688 | === added directory 'Transmission/lib' |
689 | === added file 'Transmission/lib/Jayrock.Json.dll' |
690 | Binary files Transmission/lib/Jayrock.Json.dll 1970-01-01 00:00:00 +0000 and Transmission/lib/Jayrock.Json.dll 2010-07-26 16:47:47 +0000 differ |
691 | === added file 'Transmission/lib/Jayrock.Json.pdb' |
692 | Binary files Transmission/lib/Jayrock.Json.pdb 1970-01-01 00:00:00 +0000 and Transmission/lib/Jayrock.Json.pdb 2010-07-26 16:47:47 +0000 differ |
693 | === added directory 'Transmission/src' |
694 | === added directory 'Transmission/src/Config' |
695 | === added file 'Transmission/src/Config/TransmissionConfig.cs' |
696 | --- Transmission/src/Config/TransmissionConfig.cs 1970-01-01 00:00:00 +0000 |
697 | +++ Transmission/src/Config/TransmissionConfig.cs 2010-07-26 16:47:47 +0000 |
698 | @@ -0,0 +1,91 @@ |
699 | +using System; |
700 | +using System.IO; |
701 | +using System.Text; |
702 | + |
703 | +using Mono.Addins; |
704 | + |
705 | +using Gtk; |
706 | + |
707 | +using Do.Platform; |
708 | + |
709 | +namespace Transmission |
710 | +{ |
711 | + |
712 | + [System.ComponentModel.Category("File")] |
713 | + [System.ComponentModel.ToolboxItem(true)] |
714 | + public partial class TransmissionConfig : Gtk.Bin |
715 | + { |
716 | + public static string home_path = Environment.GetFolderPath (Environment.SpecialFolder.Personal); |
717 | + public static string settings_path = System.IO.Path.Combine (home_path, ".config/transmission/settings.json"); |
718 | + |
719 | + static IPreferences prefs; |
720 | + |
721 | + public TransmissionConfig() |
722 | + { |
723 | + Build(); |
724 | + RefreshView(); |
725 | + } |
726 | + |
727 | + private void RefreshView() |
728 | + { |
729 | + address_entry.Text = Address; |
730 | + port_entry.Text = Port.ToString(); |
731 | + user_name_entry.Text = UserName; |
732 | + password_entry.Text = Password; |
733 | + } |
734 | + |
735 | + static TransmissionConfig() |
736 | + { |
737 | + prefs = Services.Preferences.Get<TransmissionConfig>(); |
738 | + } |
739 | + |
740 | + public static string Address |
741 | + { |
742 | + get { return prefs.Get<string>("Address", "127.0.0.1"); } |
743 | + set { prefs.Set<string> ("Address", value); } |
744 | + } |
745 | + |
746 | + public static int Port |
747 | + { |
748 | + get { return prefs.Get<int>("Port", TransmissionAPI.DEFAULT_PORT); } |
749 | + set { prefs.Set<int> ("Port", value); } |
750 | + } |
751 | + |
752 | + public static string UserName |
753 | + { |
754 | + get { return prefs.Get<string>("UserName", ""); } |
755 | + set { prefs.Set<string> ("UserName", value); } |
756 | + } |
757 | + |
758 | + public static string Password |
759 | + { |
760 | + get { return prefs.Get<string>("Password", ""); } |
761 | + set { prefs.Set<string> ("Password", value); } |
762 | + } |
763 | + |
764 | + protected virtual void OnAddressEntryChanged (object sender, System.EventArgs e) |
765 | + { |
766 | + Address = address_entry.Text; |
767 | + TransmissionPlugin.ResetConnection(); |
768 | + } |
769 | + |
770 | + protected virtual void OnUserNameEntryChanged (object sender, System.EventArgs e) |
771 | + { |
772 | + UserName = user_name_entry.Text; |
773 | + TransmissionPlugin.ResetConnection(); |
774 | + } |
775 | + |
776 | + protected virtual void OnPasswordEntryChanged (object sender, System.EventArgs e) |
777 | + { |
778 | + Password = password_entry.Text; |
779 | + TransmissionPlugin.ResetConnection(); |
780 | + } |
781 | + |
782 | + protected virtual void OnPortEntryChanged (object sender, System.EventArgs e) |
783 | + { |
784 | + Port = int.Parse(port_entry.Text); |
785 | + TransmissionPlugin.ResetConnection(); |
786 | + } |
787 | + |
788 | + } |
789 | +} |
790 | |
791 | === added file 'Transmission/src/ITorrentEntry.cs' |
792 | --- Transmission/src/ITorrentEntry.cs 1970-01-01 00:00:00 +0000 |
793 | +++ Transmission/src/ITorrentEntry.cs 2010-07-26 16:47:47 +0000 |
794 | @@ -0,0 +1,16 @@ |
795 | +using System.Collections.Generic; |
796 | + |
797 | +namespace Transmission { |
798 | + |
799 | + public interface ITorrentEntry { |
800 | + // Owner torrent. |
801 | + TorrentItem Torrent { get; } |
802 | + |
803 | + // Path on FS. |
804 | + string Path { get; } |
805 | + |
806 | + // Get all files under this entry (recursively). |
807 | + // For files return file itself. |
808 | + IEnumerable<TorrentFileItem> GetFiles(); |
809 | + } |
810 | +} |
811 | |
812 | === added file 'Transmission/src/JsonCollectionImporter.cs' |
813 | --- Transmission/src/JsonCollectionImporter.cs 1970-01-01 00:00:00 +0000 |
814 | +++ Transmission/src/JsonCollectionImporter.cs 2010-07-26 16:47:47 +0000 |
815 | @@ -0,0 +1,117 @@ |
816 | +namespace Transmission |
817 | +{ |
818 | + #region Imports |
819 | + |
820 | + using System; |
821 | + using System.Collections.Generic; |
822 | + using System.Diagnostics; |
823 | + using Jayrock.Json; |
824 | + using Jayrock.Json.Conversion; |
825 | + using Jayrock.Json.Conversion.Converters; |
826 | + |
827 | + #endregion |
828 | + |
829 | + /// <summary> |
830 | + /// An abstract base class for importer implementations that can import |
831 | + /// a concrete collection instance from a JSON array. |
832 | + /// </summary> |
833 | + |
834 | + |
835 | + public abstract class CollectionImporterBase : ImporterBase |
836 | + { |
837 | + private readonly Type _elementType; |
838 | + |
839 | + |
840 | + public CollectionImporterBase(Type outputType, Type elementType) : |
841 | + base(outputType) |
842 | + { |
843 | + if (elementType == null) throw new ArgumentNullException("elementType"); |
844 | + |
845 | + _elementType = elementType; |
846 | + } |
847 | + |
848 | + |
849 | + public Type ElementType |
850 | + { |
851 | + get { return _elementType; } |
852 | + } |
853 | + |
854 | + |
855 | + protected override object ImportFromArray(ImportContext context, JsonReader reader) |
856 | + { |
857 | + if (context == null) throw new ArgumentNullException("context"); |
858 | + if (reader == null) throw new ArgumentNullException("reader"); |
859 | + |
860 | + |
861 | + object collection = CreateCollection(); |
862 | + |
863 | + |
864 | + reader.ReadToken(JsonTokenClass.Array); |
865 | + |
866 | + |
867 | + ImportElements(collection, context, reader); |
868 | + |
869 | + |
870 | + if (reader.TokenClass != JsonTokenClass.EndArray) |
871 | + throw new Exception("Implementation error."); |
872 | + |
873 | + |
874 | + reader.Read(); |
875 | + return collection; |
876 | + } |
877 | + |
878 | + |
879 | + protected abstract object CreateCollection(); |
880 | + protected abstract void ImportElements(object collection, ImportContext context, JsonReader reader); |
881 | + } |
882 | + |
883 | + |
884 | + /// <summary> |
885 | + /// An importer for importing a collection of elements from a JSON array. |
886 | + /// </summary> |
887 | + |
888 | + |
889 | + public class CollectionImporter<Collection, Element> : CollectionImporterBase |
890 | + where Collection : ICollection<Element>, new() |
891 | + { |
892 | + public CollectionImporter() : |
893 | + base(typeof(Collection), typeof(Element)) { } |
894 | + |
895 | + |
896 | + protected override object CreateCollection() |
897 | + { |
898 | + return new Collection(); |
899 | + } |
900 | + |
901 | + |
902 | + protected override void ImportElements(object collection, ImportContext context, JsonReader reader) |
903 | + { |
904 | + if (collection == null) throw new ArgumentNullException("collection"); |
905 | + if (context == null) throw new ArgumentNullException("context"); |
906 | + if (reader == null) throw new ArgumentNullException("reader"); |
907 | + |
908 | + |
909 | + ImportElements((ICollection<Element>) collection, context, reader); |
910 | + } |
911 | + |
912 | + |
913 | + private static void ImportElements(ICollection<Element> collection, ImportContext context, JsonReader reader) |
914 | + { |
915 | + Debug.Assert(collection != null); |
916 | + Debug.Assert(context != null); |
917 | + Debug.Assert(reader != null); |
918 | + |
919 | + |
920 | + while (reader.TokenClass != JsonTokenClass.EndArray) |
921 | + collection.Add((Element) context.Import(typeof(Element), reader)); |
922 | + } |
923 | + } |
924 | + |
925 | + /// <summary> |
926 | + /// Imports <see cref="List{T}"/> from a JSON array. |
927 | + /// </summary> |
928 | + |
929 | + public class ListImporter<T> : CollectionImporter<List<T>, T> |
930 | + where T : new() { } |
931 | + |
932 | +} |
933 | \ No newline at end of file |
934 | |
935 | === added file 'Transmission/src/TorrentAbstractLimitSpeedAction.cs' |
936 | --- Transmission/src/TorrentAbstractLimitSpeedAction.cs 1970-01-01 00:00:00 +0000 |
937 | +++ Transmission/src/TorrentAbstractLimitSpeedAction.cs 2010-07-26 16:47:47 +0000 |
938 | @@ -0,0 +1,80 @@ |
939 | + |
940 | +using System; |
941 | +using System.Linq; |
942 | +using System.Collections.Generic; |
943 | +using System.Text.RegularExpressions; |
944 | + |
945 | +using Mono.Addins; |
946 | + |
947 | +using Do.Platform; |
948 | +using Do.Universe; |
949 | + |
950 | +namespace Transmission { |
951 | + |
952 | + public abstract class TorrentAbstractLimitSpeedAction: Act { |
953 | + |
954 | + public override IEnumerable<Type> SupportedItemTypes { |
955 | + get { yield return typeof (TorrentItem); } |
956 | + } |
957 | + |
958 | + public override IEnumerable<Type> SupportedModifierItemTypes { |
959 | + get { |
960 | + yield return typeof (ITextItem); |
961 | + yield return typeof (PredefinedSpeed); |
962 | + } |
963 | + } |
964 | + |
965 | + public override bool ModifierItemsOptional { |
966 | + get { return false; } |
967 | + } |
968 | + |
969 | + protected abstract PredefinedSpeed GetCurrentSpeedItem(TorrentItem torrent); |
970 | + |
971 | + public override IEnumerable<Item> DynamicModifierItemsForItem(Item item) { |
972 | + TorrentItem torrent = (TorrentItem)item; |
973 | + |
974 | + yield return new PredefinedSpeed(0, "Unlimited", "Turn download speed limit off"); |
975 | + yield return GetCurrentSpeedItem(torrent); |
976 | + foreach (PredefinedSpeed speed in Utils.PredefinedSpeedItems) |
977 | + yield return speed; |
978 | + } |
979 | + |
980 | + protected abstract void SetSpeedLimit(TransmissionAPI api, IEnumerable<TorrentItem> torrents, int speed); |
981 | + |
982 | + public override IEnumerable<Item> Perform(IEnumerable<Item> items, IEnumerable<Item> modItems) { |
983 | + int? speed = null; |
984 | + |
985 | + // Get speed item, it can be either ITextItem or PredefinedSpeed. |
986 | + Item modItem = modItems.First(); |
987 | + if (modItem is PredefinedSpeed) { |
988 | + speed = ((PredefinedSpeed)modItem).Value; |
989 | + } else { |
990 | + string speed_str = ((ITextItem)modItem).Text; |
991 | + |
992 | + try { |
993 | + // Try to parse entered speed value. |
994 | + speed = Utils.ParseSpeed(speed_str); |
995 | + |
996 | + } catch (ArgumentException) { |
997 | + Log<TransmissionPlugin>.Debug("Invalid speed string: {0}", speed_str); |
998 | + |
999 | + // Show notification about invalid speed value with some hints on |
1000 | + // accepted formats. |
1001 | + string message = AddinManager.CurrentLocalizer.GetString( |
1002 | + "Can't recognize \"{0}\" as speed\nUse values like: 100k, 50 kb, 20m, 10 mib" |
1003 | + ); |
1004 | + Services.Notifications.Notify("Transmission", string.Format(message, speed_str), "transmission"); |
1005 | + } |
1006 | + } |
1007 | + |
1008 | + // If speed is recognized successfully, set speed limit and update item. |
1009 | + if (speed.HasValue) { |
1010 | + TransmissionAPI api = TransmissionPlugin.getTransmission(); |
1011 | + IEnumerable<TorrentItem> torrents = items.Cast<TorrentItem>(); |
1012 | + SetSpeedLimit(api, torrents, speed.Value); |
1013 | + } |
1014 | + |
1015 | + yield break; |
1016 | + } |
1017 | + } |
1018 | +} |
1019 | |
1020 | === added file 'Transmission/src/TorrentDirectoryItem.cs' |
1021 | --- Transmission/src/TorrentDirectoryItem.cs 1970-01-01 00:00:00 +0000 |
1022 | +++ Transmission/src/TorrentDirectoryItem.cs 2010-07-26 16:47:47 +0000 |
1023 | @@ -0,0 +1,64 @@ |
1024 | + |
1025 | +using System; |
1026 | +using System.Collections.Generic; |
1027 | + |
1028 | +using Do.Universe; |
1029 | + |
1030 | +namespace Transmission { |
1031 | + |
1032 | + public class TorrentDirectoryItem: Item, ITorrentEntry { |
1033 | + |
1034 | + private TorrentItem _torrent; |
1035 | + private TorrentDirectoryItem _parent; |
1036 | + private string _name; |
1037 | + private IList<Item> _files; |
1038 | + |
1039 | + public TorrentDirectoryItem(TorrentItem torrent, TorrentDirectoryItem parent, string name) { |
1040 | + _torrent = torrent; |
1041 | + _parent = parent; |
1042 | + _name = name; |
1043 | + _files = new List<Item>(); |
1044 | + } |
1045 | + |
1046 | + public TorrentItem Torrent { |
1047 | + get { return _torrent; } |
1048 | + } |
1049 | + |
1050 | + public IEnumerable<TorrentFileItem> GetFiles() { |
1051 | + foreach (ITorrentEntry entry in _files) |
1052 | + foreach (TorrentFileItem file in entry.GetFiles()) |
1053 | + yield return file; |
1054 | + } |
1055 | + |
1056 | + public override string Name { |
1057 | + get { return _name; } |
1058 | + } |
1059 | + |
1060 | + public override string Description { |
1061 | + get { return string.Empty; } |
1062 | + } |
1063 | + |
1064 | + public override string Icon { |
1065 | + get { return "folder"; } |
1066 | + } |
1067 | + |
1068 | + public IList<Item> Files { |
1069 | + get { return _files; } |
1070 | + } |
1071 | + |
1072 | + public string Path { |
1073 | + get { |
1074 | + if (_parent != null) { |
1075 | + return _parent.Path + '/' + _name; |
1076 | + } else { |
1077 | + return _name; |
1078 | + } |
1079 | + } |
1080 | + } |
1081 | + |
1082 | + public string Uri { |
1083 | + get { return "file://" + Path; } |
1084 | + } |
1085 | + } |
1086 | + |
1087 | +} |
1088 | |
1089 | === added file 'Transmission/src/TorrentFileItem.cs' |
1090 | --- Transmission/src/TorrentFileItem.cs 1970-01-01 00:00:00 +0000 |
1091 | +++ Transmission/src/TorrentFileItem.cs 2010-07-26 16:47:47 +0000 |
1092 | @@ -0,0 +1,97 @@ |
1093 | + |
1094 | +using System; |
1095 | +using System.Collections.Generic; |
1096 | + |
1097 | +using Do.Universe; |
1098 | + |
1099 | +namespace Transmission { |
1100 | + |
1101 | + public class TorrentFileItem: Item, ITorrentEntry { |
1102 | + |
1103 | + // Owner torrent. |
1104 | + private TorrentItem _torrent; |
1105 | + // Position of this file within torrents file list. |
1106 | + private int _index; |
1107 | + |
1108 | + private TorrentDirectoryItem _parent; |
1109 | + private string _name; |
1110 | + private long _size, _downloaded; |
1111 | + private bool _wanted; |
1112 | + private TransmissionAPI.FilePriority _priority; |
1113 | + |
1114 | + public TorrentFileItem( |
1115 | + TorrentItem torrent, int index, TorrentDirectoryItem parent, |
1116 | + string name, TransmissionAPI.TorrentFileInfo info |
1117 | + ) { |
1118 | + _torrent = torrent; |
1119 | + _index = index; |
1120 | + |
1121 | + _parent = parent; |
1122 | + _name = name; |
1123 | + _size = info.Length; |
1124 | + _downloaded = info.BytesCompleted; |
1125 | + |
1126 | + _wanted = info.Wanted; |
1127 | + _priority = info.Priority; |
1128 | + } |
1129 | + |
1130 | + public TorrentItem Torrent { |
1131 | + get { return _torrent; } |
1132 | + } |
1133 | + |
1134 | + public int Index { |
1135 | + get { return _index; } |
1136 | + } |
1137 | + |
1138 | + public TransmissionAPI.FilePriority Priority { |
1139 | + get { return _priority; } |
1140 | + } |
1141 | + |
1142 | + public IEnumerable<TorrentFileItem> GetFiles() { |
1143 | + yield return this; |
1144 | + } |
1145 | + |
1146 | + public override string Name { |
1147 | + get { return _name; } |
1148 | + } |
1149 | + |
1150 | + public override string Description { |
1151 | + get { |
1152 | + // I don't use special percentage format string, because it rounds |
1153 | + // value and I don't want to get "100%" until file is really downloaded. |
1154 | + // High precision isn't needed, because info is mostly out-of-date. |
1155 | + |
1156 | + if (_downloaded == _size) |
1157 | + return string.Format("Complete, {0}", Utils.FormatSize(_size)); |
1158 | + |
1159 | + else if (_wanted) |
1160 | + return string.Format("{0} of {1} complete ({2:0}%)", |
1161 | + Utils.FormatSize(_downloaded), Utils.FormatSize(_size), |
1162 | + Math.Floor(100.0 * _downloaded / _size) |
1163 | + ); |
1164 | + |
1165 | + else if (_downloaded != 0) |
1166 | + return string.Format("Skipped, {0} of {1} complete ({2:0}%)", |
1167 | + Utils.FormatSize(_downloaded),Utils.FormatSize(_size), |
1168 | + Math.Floor(100.0 * _downloaded / _size) |
1169 | + ); |
1170 | + |
1171 | + else |
1172 | + return string.Format("Skipped, {0}", Utils.FormatSize(_size)); |
1173 | + } |
1174 | + } |
1175 | + |
1176 | + public override string Icon { |
1177 | + get { return "document"; } |
1178 | + } |
1179 | + |
1180 | + public string Path { |
1181 | + get { return _parent.Path + '/' + _name; } |
1182 | + } |
1183 | + |
1184 | + public string Uri { |
1185 | + get { return "file://" + Path; } |
1186 | + } |
1187 | + } |
1188 | + |
1189 | +} |
1190 | |
1191 | === added file 'Transmission/src/TorrentFileSetPriorityAction.cs' |
1192 | --- Transmission/src/TorrentFileSetPriorityAction.cs 1970-01-01 00:00:00 +0000 |
1193 | +++ Transmission/src/TorrentFileSetPriorityAction.cs 2010-07-26 16:47:47 +0000 |
1194 | @@ -0,0 +1,108 @@ |
1195 | + |
1196 | +using System; |
1197 | +using System.Linq; |
1198 | +using System.Collections.Generic; |
1199 | + |
1200 | +using Mono.Addins; |
1201 | + |
1202 | +using Do.Platform; |
1203 | +using Do.Universe; |
1204 | + |
1205 | +namespace Transmission { |
1206 | + |
1207 | + public class PriorityItem: Item { |
1208 | + private TransmissionAPI.FilePriority _value; |
1209 | + private string _name; |
1210 | + private string _icon; |
1211 | + |
1212 | + public PriorityItem(TransmissionAPI.FilePriority value, string name, string icon) { |
1213 | + _value = value; |
1214 | + _name = name; |
1215 | + _icon = icon; |
1216 | + } |
1217 | + |
1218 | + public override string Name { |
1219 | + get { return _name; } |
1220 | + } |
1221 | + |
1222 | + public override string Description { |
1223 | + get { return ""; } |
1224 | + } |
1225 | + |
1226 | + public override string Icon { |
1227 | + get { return _icon; } |
1228 | + } |
1229 | + |
1230 | + public TransmissionAPI.FilePriority Value { |
1231 | + get { return _value; } |
1232 | + } |
1233 | + } |
1234 | + |
1235 | + public class TorrentFileSetPriorityAction: Act { |
1236 | + |
1237 | + public TorrentFileSetPriorityAction() { |
1238 | + } |
1239 | + |
1240 | + public override string Name { |
1241 | + get { return AddinManager.CurrentLocalizer.GetString ("Set priority"); } |
1242 | + } |
1243 | + |
1244 | + public override string Description { |
1245 | + get { return AddinManager.CurrentLocalizer.GetString ("Set download priority"); } |
1246 | + } |
1247 | + |
1248 | + public override string Icon { |
1249 | + get { return "object-flip-vertical"; } |
1250 | + } |
1251 | + |
1252 | + public override IEnumerable<Type> SupportedItemTypes { |
1253 | + get { |
1254 | + yield return typeof (ITorrentEntry); |
1255 | + } |
1256 | + } |
1257 | + |
1258 | + public override IEnumerable<Type> SupportedModifierItemTypes { |
1259 | + get { |
1260 | + yield return typeof (PriorityItem); |
1261 | + } |
1262 | + } |
1263 | + |
1264 | + public override bool ModifierItemsOptional { |
1265 | + get { return false; } |
1266 | + } |
1267 | + |
1268 | + public override IEnumerable<Item> DynamicModifierItemsForItem(Item item) { |
1269 | + yield return new PriorityItem(TransmissionAPI.FilePriority.Low, "Low", "down"); |
1270 | + yield return new PriorityItem(TransmissionAPI.FilePriority.Normal, "Normal", "forward"); |
1271 | + yield return new PriorityItem(TransmissionAPI.FilePriority.High, "High", "up"); |
1272 | + } |
1273 | + |
1274 | + public override IEnumerable<Item> Perform(IEnumerable<Item> items, IEnumerable<Item> modItems) { |
1275 | + TransmissionAPI.FilePriority priority = (modItems.First() as PriorityItem).Value; |
1276 | + |
1277 | + TransmissionAPI.FileOperation operation = new TransmissionAPI.FileOperation(null, priority); |
1278 | + |
1279 | + // Group torrent entries by torrent. |
1280 | + var files_by_torrent = items |
1281 | + .Cast<ITorrentEntry>() |
1282 | + .GroupBy( |
1283 | + item => item.Torrent, |
1284 | + (torrent, entries) => new { |
1285 | + Torrent = torrent, |
1286 | + Files = entries.SelectMany(entry => entry.GetFiles()) |
1287 | + } |
1288 | + ); |
1289 | + |
1290 | + TransmissionAPI api = TransmissionPlugin.getTransmission(); |
1291 | + |
1292 | + // Expand entries for each torrent into set of torrent file entries. |
1293 | + // Perform action for each torrent separately. |
1294 | + foreach (var group in files_by_torrent) { |
1295 | + var operations = group.Files.ToDictionary(f => f.Index, f => operation); |
1296 | + api.SetTorrent(group.Torrent.HashString, null, null, null, null, null, operations); |
1297 | + } |
1298 | + |
1299 | + yield break; |
1300 | + } |
1301 | + } |
1302 | +} |
1303 | |
1304 | === added file 'Transmission/src/TorrentItem.cs' |
1305 | --- Transmission/src/TorrentItem.cs 1970-01-01 00:00:00 +0000 |
1306 | +++ Transmission/src/TorrentItem.cs 2010-07-26 16:47:47 +0000 |
1307 | @@ -0,0 +1,72 @@ |
1308 | + |
1309 | +using System; |
1310 | +using System.Collections.Generic; |
1311 | + |
1312 | +using Do.Universe; |
1313 | + |
1314 | +namespace Transmission { |
1315 | + |
1316 | + public class TorrentItem: Item { |
1317 | + |
1318 | + private string _name; |
1319 | + private string _comment; |
1320 | + private string _hash_string; |
1321 | + private long _size; |
1322 | + private TransmissionAPI.TorrentStatus _status; |
1323 | + private int _download_speed_limit, _upload_speed_limit; |
1324 | + private TorrentDirectoryItem _root; |
1325 | + |
1326 | + public TorrentItem(TransmissionAPI.TorrentInfo info) { |
1327 | + _hash_string = info.HashString; |
1328 | + _name = info.Name; |
1329 | + _comment = info.Comment; |
1330 | + _status = info.Status; |
1331 | + _size = info.TotalSize; |
1332 | + _download_speed_limit = info.DownloadLimit; |
1333 | + _upload_speed_limit = info.UploadLimit; |
1334 | + _root = new TorrentDirectoryItem(this, null, info.DownloadDir); |
1335 | + } |
1336 | + |
1337 | + public override string Name { |
1338 | + get { return _name; } |
1339 | + } |
1340 | + |
1341 | + public override string Description { |
1342 | + get { |
1343 | + string status_text = ""; |
1344 | + switch (_status) { |
1345 | + case TransmissionAPI.TorrentStatus.CheckWait: status_text = "Waiting for check"; break; |
1346 | + case TransmissionAPI.TorrentStatus.Check: status_text = "Checking"; break; |
1347 | + case TransmissionAPI.TorrentStatus.Download: status_text = "Downloading"; break; |
1348 | + case TransmissionAPI.TorrentStatus.Seed: status_text = "Seeding"; break; |
1349 | + case TransmissionAPI.TorrentStatus.Stopped: status_text = "Stopped"; break; |
1350 | + } |
1351 | + |
1352 | + return string.Format("{0}, {1}", Utils.FormatSize(_size), status_text); |
1353 | + } |
1354 | + } |
1355 | + |
1356 | + public override string Icon { |
1357 | + get { return "transmission"; } |
1358 | + } |
1359 | + |
1360 | + public string HashString { |
1361 | + get { return _hash_string; } |
1362 | + } |
1363 | + |
1364 | + public TorrentDirectoryItem Root { |
1365 | + get { return _root; } |
1366 | + } |
1367 | + |
1368 | + public int DownloadSpeedLimit { |
1369 | + get { return _download_speed_limit; } |
1370 | + set { _download_speed_limit = value; } |
1371 | + } |
1372 | + |
1373 | + public int UploadSpeedLimit { |
1374 | + get { return _upload_speed_limit; } |
1375 | + set { _upload_speed_limit = value; } |
1376 | + } |
1377 | + } |
1378 | + |
1379 | +} |
1380 | |
1381 | === added file 'Transmission/src/TorrentItemSource.cs' |
1382 | --- Transmission/src/TorrentItemSource.cs 1970-01-01 00:00:00 +0000 |
1383 | +++ Transmission/src/TorrentItemSource.cs 2010-07-26 16:47:47 +0000 |
1384 | @@ -0,0 +1,130 @@ |
1385 | + |
1386 | +using System; |
1387 | +using System.Collections.Generic; |
1388 | + |
1389 | +using Mono.Addins; |
1390 | + |
1391 | +using Do.Universe; |
1392 | +using Do.Platform; |
1393 | +using Do.Platform.Linux; |
1394 | + |
1395 | +namespace Transmission { |
1396 | + |
1397 | + public class TorrentItemSource: ItemSource, IConfigurable { |
1398 | + |
1399 | + private List<Item> _torrents = new List<Item>(); |
1400 | + |
1401 | + public TorrentItemSource() { |
1402 | + } |
1403 | + |
1404 | + public override string Name { |
1405 | + get { return "Torrents"; } |
1406 | + } |
1407 | + |
1408 | + public override string Description { |
1409 | + get { return "Transmission torrent client downloads"; } |
1410 | + } |
1411 | + |
1412 | + public override string Icon { |
1413 | + get { return "transmission"; } |
1414 | + } |
1415 | + |
1416 | + public override void UpdateItems () { |
1417 | + Log<TorrentItemSource>.Debug("Updating torrents list"); |
1418 | + |
1419 | + // Clear current torrents list. |
1420 | + _torrents.Clear(); |
1421 | + |
1422 | + TransmissionAPI api = TransmissionPlugin.getTransmission(); |
1423 | + |
1424 | + foreach (TransmissionAPI.TorrentInfo t in api.GetAllTorrents()) { |
1425 | + Log<TorrentItemSource>.Debug("Torrent: {0}", t.Name); |
1426 | + |
1427 | + TorrentItem torrent = new TorrentItem(t); |
1428 | + |
1429 | + // Transmission returns files as flat list with full names, this map |
1430 | + // is used to organize files into hierarchy. |
1431 | + // It maps directory path to directory item. |
1432 | + Dictionary<string, TorrentDirectoryItem> dirs = new Dictionary<string, TorrentDirectoryItem>(); |
1433 | + dirs.Add("", torrent.Root); |
1434 | + |
1435 | + int index = 0; // File index within list. |
1436 | + foreach (TransmissionAPI.TorrentFileInfo f in t.files) { |
1437 | + // Split path and name. |
1438 | + int sep_pos = f.Name.LastIndexOf('/'); |
1439 | + |
1440 | + string name = f.Name.Substring(sep_pos+1); |
1441 | + string path = f.Name.Substring(0, sep_pos == -1 ? 0 : sep_pos); |
1442 | + Log<TorrentItemSource>.Debug("File {0} in dir {1}", name, path); |
1443 | + TorrentDirectoryItem dir = FindOrCreateDirectory(path, dirs); |
1444 | + |
1445 | + dir.Files.Add(new TorrentFileItem(torrent, index, dir, name, f)); |
1446 | + |
1447 | + ++index; |
1448 | + } |
1449 | + |
1450 | + _torrents.Add(torrent); |
1451 | + } |
1452 | + } |
1453 | + |
1454 | + private TorrentDirectoryItem FindOrCreateDirectory( |
1455 | + string path, |
1456 | + Dictionary<string, TorrentDirectoryItem> dirs |
1457 | + ) { |
1458 | + TorrentDirectoryItem dir; |
1459 | + dirs.TryGetValue(path, out dir); |
1460 | + |
1461 | + if (dir != null) { |
1462 | + // Found already added directory. |
1463 | + return dir; |
1464 | + |
1465 | + } else { |
1466 | + // Directory doesn't exist, find or add parent one, then add this one. |
1467 | + int sep_pos = path.LastIndexOf('/'); |
1468 | + |
1469 | + string parent_path = path.Substring(0, sep_pos == -1 ? 0 : sep_pos); |
1470 | + TorrentDirectoryItem parent = FindOrCreateDirectory(parent_path, dirs); |
1471 | + |
1472 | + string name = path.Substring(sep_pos+1); |
1473 | + dir = new TorrentDirectoryItem(parent.Torrent, parent, name); |
1474 | + |
1475 | + parent.Files.Add(dir); |
1476 | + dirs.Add(path, dir); |
1477 | + |
1478 | + return dir; |
1479 | + } |
1480 | + } |
1481 | + |
1482 | + public override IEnumerable<Item> Items { |
1483 | + get { return _torrents; } |
1484 | + } |
1485 | + |
1486 | + public override IEnumerable<Item> ChildrenOfItem(Item item) { |
1487 | + if (item is TorrentItem) { |
1488 | + foreach (Item entry in ((TorrentItem)item).Root.Files) |
1489 | + yield return entry; |
1490 | + |
1491 | + } else if (item is TorrentDirectoryItem) { |
1492 | + foreach (Item entry in ((TorrentDirectoryItem)item).Files) |
1493 | + yield return entry; |
1494 | + |
1495 | + } else { |
1496 | + yield break; |
1497 | + |
1498 | + } |
1499 | + } |
1500 | + |
1501 | + public override IEnumerable<Type> SupportedItemTypes { |
1502 | + get { |
1503 | + yield return typeof(TorrentItem); |
1504 | + yield return typeof(TorrentDirectoryItem); |
1505 | + yield return typeof(TorrentFileItem); |
1506 | + } |
1507 | + } |
1508 | + |
1509 | + public Gtk.Bin GetConfiguration() { |
1510 | + return new TransmissionConfig(); |
1511 | + } |
1512 | + |
1513 | + } |
1514 | +} |
1515 | |
1516 | === added file 'Transmission/src/TorrentLimitDownloadSpeedAction.cs' |
1517 | --- Transmission/src/TorrentLimitDownloadSpeedAction.cs 1970-01-01 00:00:00 +0000 |
1518 | +++ Transmission/src/TorrentLimitDownloadSpeedAction.cs 2010-07-26 16:47:47 +0000 |
1519 | @@ -0,0 +1,47 @@ |
1520 | + |
1521 | +using System; |
1522 | +using System.Linq; |
1523 | +using System.Collections.Generic; |
1524 | +using System.Text.RegularExpressions; |
1525 | + |
1526 | +using Mono.Addins; |
1527 | + |
1528 | +using Do.Platform; |
1529 | +using Do.Universe; |
1530 | + |
1531 | +namespace Transmission { |
1532 | + |
1533 | + public class TorrentLimitDownloadSpeedAction: TorrentAbstractLimitSpeedAction { |
1534 | + |
1535 | + public override string Name { |
1536 | + get { return AddinManager.CurrentLocalizer.GetString("Limit download speed"); } |
1537 | + } |
1538 | + |
1539 | + public override string Description { |
1540 | + get { return AddinManager.CurrentLocalizer.GetString("Set download speed limit"); } |
1541 | + } |
1542 | + |
1543 | + public override string Icon { |
1544 | + get { return "top"; } |
1545 | + } |
1546 | + |
1547 | + protected override PredefinedSpeed GetCurrentSpeedItem(TorrentItem torrent) { |
1548 | + int currentSpeed = torrent.DownloadSpeedLimit; |
1549 | + return new PredefinedSpeed( |
1550 | + currentSpeed, |
1551 | + string.Format("Saved: {0}", Utils.FormatSpeed(currentSpeed)), |
1552 | + "Use limit from torrent settings" |
1553 | + ); |
1554 | + } |
1555 | + |
1556 | + protected override void SetSpeedLimit(TransmissionAPI api, IEnumerable<TorrentItem> torrents, int speed) { |
1557 | + bool limit_speed = (speed != 0); |
1558 | + int? limit = (speed == 0 ? (int?)null : speed); |
1559 | + api.SetTorrents(torrents.Select(t => t.HashString), null, limit_speed, limit, null, null); |
1560 | + |
1561 | + foreach (TorrentItem torrent in torrents) |
1562 | + torrent.DownloadSpeedLimit = speed; |
1563 | + } |
1564 | + |
1565 | + } |
1566 | +} |
1567 | |
1568 | === added file 'Transmission/src/TorrentLimitUploadSpeedAction.cs' |
1569 | --- Transmission/src/TorrentLimitUploadSpeedAction.cs 1970-01-01 00:00:00 +0000 |
1570 | +++ Transmission/src/TorrentLimitUploadSpeedAction.cs 2010-07-26 16:47:47 +0000 |
1571 | @@ -0,0 +1,47 @@ |
1572 | + |
1573 | +using System; |
1574 | +using System.Linq; |
1575 | +using System.Collections.Generic; |
1576 | +using System.Text.RegularExpressions; |
1577 | + |
1578 | +using Mono.Addins; |
1579 | + |
1580 | +using Do.Platform; |
1581 | +using Do.Universe; |
1582 | + |
1583 | +namespace Transmission { |
1584 | + |
1585 | + public class TorrentLimitUploadSpeedAction: TorrentAbstractLimitSpeedAction { |
1586 | + |
1587 | + public override string Name { |
1588 | + get { return AddinManager.CurrentLocalizer.GetString ("Limit upload speed"); } |
1589 | + } |
1590 | + |
1591 | + public override string Description { |
1592 | + get { return AddinManager.CurrentLocalizer.GetString ("Set upload speed limit"); } |
1593 | + } |
1594 | + |
1595 | + public override string Icon { |
1596 | + get { return "top"; } |
1597 | + } |
1598 | + |
1599 | + protected override PredefinedSpeed GetCurrentSpeedItem(TorrentItem torrent) { |
1600 | + int currentSpeed = torrent.UploadSpeedLimit; |
1601 | + return new PredefinedSpeed( |
1602 | + currentSpeed, |
1603 | + string.Format("Saved: {0}", Utils.FormatSpeed(currentSpeed)), |
1604 | + "Use limit from torrent settings" |
1605 | + ); |
1606 | + } |
1607 | + |
1608 | + protected override void SetSpeedLimit(TransmissionAPI api, IEnumerable<TorrentItem> torrents, int speed) { |
1609 | + bool limit_speed = (speed != 0); |
1610 | + int? limit = (speed == 0 ? (int?)null : speed); |
1611 | + api.SetTorrents(torrents.Select(t => t.HashString), null, null, null, limit_speed, limit); |
1612 | + |
1613 | + foreach (TorrentItem torrent in torrents) |
1614 | + torrent.UploadSpeedLimit = speed; |
1615 | + } |
1616 | + |
1617 | + } |
1618 | +} |
1619 | |
1620 | === added file 'Transmission/src/TorrentMarkForDownloadAction.cs' |
1621 | --- Transmission/src/TorrentMarkForDownloadAction.cs 1970-01-01 00:00:00 +0000 |
1622 | +++ Transmission/src/TorrentMarkForDownloadAction.cs 2010-07-26 16:47:47 +0000 |
1623 | @@ -0,0 +1,62 @@ |
1624 | + |
1625 | +using System; |
1626 | +using System.Linq; |
1627 | +using System.Collections.Generic; |
1628 | + |
1629 | +using Mono.Addins; |
1630 | + |
1631 | +using Do.Platform; |
1632 | +using Do.Universe; |
1633 | + |
1634 | +namespace Transmission { |
1635 | + |
1636 | + public class TorrentMarkForDownloadAction: Act { |
1637 | + |
1638 | + public TorrentMarkForDownloadAction() { |
1639 | + } |
1640 | + |
1641 | + public override string Name { |
1642 | + get { return AddinManager.CurrentLocalizer.GetString ("Mark for download"); } |
1643 | + } |
1644 | + |
1645 | + public override string Description { |
1646 | + get { return AddinManager.CurrentLocalizer.GetString ("Mark file as needed to be downloaded"); } |
1647 | + } |
1648 | + |
1649 | + public override string Icon { |
1650 | + get { return "add"; } |
1651 | + } |
1652 | + |
1653 | + public override IEnumerable<Type> SupportedItemTypes { |
1654 | + get { |
1655 | + yield return typeof (ITorrentEntry); |
1656 | + } |
1657 | + } |
1658 | + |
1659 | + public override IEnumerable<Item> Perform(IEnumerable<Item> items, IEnumerable<Item> modItems) { |
1660 | + TransmissionAPI api = TransmissionPlugin.getTransmission(); |
1661 | + |
1662 | + // Operation is common for all files. |
1663 | + TransmissionAPI.FileOperation operation = new TransmissionAPI.FileOperation(true, null); |
1664 | + |
1665 | + // Group selected items by owner torrent. |
1666 | + var files_by_torrent = items |
1667 | + .Cast<ITorrentEntry>() |
1668 | + .GroupBy( |
1669 | + item => item.Torrent, |
1670 | + (torrent, entries) => new { |
1671 | + Torrent = torrent, |
1672 | + Files = entries.SelectMany(entry => entry.GetFiles()) |
1673 | + } |
1674 | + ); |
1675 | + |
1676 | + // Perform action for each torrent separately. |
1677 | + foreach (var group in files_by_torrent) { |
1678 | + var operations = group.Files.ToDictionary(f => f.Index, f => operation); |
1679 | + api.SetTorrent(group.Torrent.HashString, null, null, null, null, null, operations); |
1680 | + } |
1681 | + |
1682 | + yield break; |
1683 | + } |
1684 | + } |
1685 | +} |
1686 | |
1687 | === added file 'Transmission/src/TorrentOperateAction.cs' |
1688 | --- Transmission/src/TorrentOperateAction.cs 1970-01-01 00:00:00 +0000 |
1689 | +++ Transmission/src/TorrentOperateAction.cs 2010-07-26 16:47:47 +0000 |
1690 | @@ -0,0 +1,37 @@ |
1691 | +using System; |
1692 | +using System.Linq; |
1693 | +using System.Collections.Generic; |
1694 | + |
1695 | +using Mono.Addins; |
1696 | + |
1697 | +using Do.Universe; |
1698 | +using Do.Platform; |
1699 | + |
1700 | +namespace Transmission { |
1701 | + |
1702 | + public class TorrentOperateAction: Act { |
1703 | + |
1704 | + public override string Name { |
1705 | + get { return AddinManager.CurrentLocalizer.GetString ("Operate on files"); } |
1706 | + } |
1707 | + |
1708 | + public override string Description { |
1709 | + get { return AddinManager.CurrentLocalizer.GetString ("Operate on downloaded file"); } |
1710 | + } |
1711 | + |
1712 | + public override string Icon { |
1713 | + get { return "file"; } |
1714 | + } |
1715 | + |
1716 | + public override IEnumerable<Type> SupportedItemTypes { |
1717 | + get { yield return typeof (ITorrentEntry); } |
1718 | + } |
1719 | + |
1720 | + public override IEnumerable<Item> Perform(IEnumerable<Item> items, IEnumerable<Item> modItems) { |
1721 | + foreach (Item item in items) { |
1722 | + ITorrentEntry entry = (ITorrentEntry)item; |
1723 | + yield return Services.UniverseFactory.NewFileItem(entry.Path) as Item; |
1724 | + } |
1725 | + } |
1726 | + } |
1727 | +} |
1728 | |
1729 | === added file 'Transmission/src/TorrentStartAction.cs' |
1730 | --- Transmission/src/TorrentStartAction.cs 1970-01-01 00:00:00 +0000 |
1731 | +++ Transmission/src/TorrentStartAction.cs 2010-07-26 16:47:47 +0000 |
1732 | @@ -0,0 +1,42 @@ |
1733 | + |
1734 | +using System; |
1735 | +using System.Linq; |
1736 | +using System.Collections.Generic; |
1737 | + |
1738 | +using Mono.Addins; |
1739 | + |
1740 | +using Do.Universe; |
1741 | + |
1742 | +namespace Transmission { |
1743 | + |
1744 | + public class TorrentStartAction: Act { |
1745 | + |
1746 | + public TorrentStartAction() { |
1747 | + } |
1748 | + |
1749 | + public override string Name { |
1750 | + get { return AddinManager.CurrentLocalizer.GetString ("Start"); } |
1751 | + } |
1752 | + |
1753 | + public override string Description { |
1754 | + get { return AddinManager.CurrentLocalizer.GetString ("Start downloading torrent"); } |
1755 | + } |
1756 | + |
1757 | + public override string Icon { |
1758 | + get { return "gtk-media-play"; } |
1759 | + } |
1760 | + |
1761 | + public override IEnumerable<Type> SupportedItemTypes { |
1762 | + get { yield return typeof (TorrentItem); } |
1763 | + } |
1764 | + |
1765 | + public override IEnumerable<Item> Perform(IEnumerable<Item> items, IEnumerable<Item> modItems) { |
1766 | + TransmissionAPI api = TransmissionPlugin.getTransmission(); |
1767 | + |
1768 | + var hashes = items.Cast<TorrentItem>().Select(t => t.HashString); |
1769 | + api.StartTorrents(hashes); |
1770 | + |
1771 | + return null; |
1772 | + } |
1773 | + } |
1774 | +} |
1775 | |
1776 | === added file 'Transmission/src/TorrentStopAction.cs' |
1777 | --- Transmission/src/TorrentStopAction.cs 1970-01-01 00:00:00 +0000 |
1778 | +++ Transmission/src/TorrentStopAction.cs 2010-07-26 16:47:47 +0000 |
1779 | @@ -0,0 +1,42 @@ |
1780 | + |
1781 | +using System; |
1782 | +using System.Linq; |
1783 | +using System.Collections.Generic; |
1784 | + |
1785 | +using Mono.Addins; |
1786 | + |
1787 | +using Do.Universe; |
1788 | + |
1789 | +namespace Transmission { |
1790 | + |
1791 | + public class TorrentStopAction: Act { |
1792 | + |
1793 | + public TorrentStopAction() { |
1794 | + } |
1795 | + |
1796 | + public override string Name { |
1797 | + get { return AddinManager.CurrentLocalizer.GetString ("Stop"); } |
1798 | + } |
1799 | + |
1800 | + public override string Description { |
1801 | + get { return AddinManager.CurrentLocalizer.GetString ("Stop downloading torrent"); } |
1802 | + } |
1803 | + |
1804 | + public override string Icon { |
1805 | + get { return "gtk-media-pause"; } |
1806 | + } |
1807 | + |
1808 | + public override IEnumerable<Type> SupportedItemTypes { |
1809 | + get { yield return typeof (TorrentItem); } |
1810 | + } |
1811 | + |
1812 | + public override IEnumerable<Item> Perform(IEnumerable<Item> items, IEnumerable<Item> modItems) { |
1813 | + TransmissionAPI api = TransmissionPlugin.getTransmission(); |
1814 | + |
1815 | + var hashes = items.Cast<TorrentItem>().Select(t => t.HashString); |
1816 | + api.StopTorrents(hashes); |
1817 | + |
1818 | + return null; |
1819 | + } |
1820 | + } |
1821 | +} |
1822 | |
1823 | === added file 'Transmission/src/TorrentUnmarkForDownloadAction.cs' |
1824 | --- Transmission/src/TorrentUnmarkForDownloadAction.cs 1970-01-01 00:00:00 +0000 |
1825 | +++ Transmission/src/TorrentUnmarkForDownloadAction.cs 2010-07-26 16:47:47 +0000 |
1826 | @@ -0,0 +1,62 @@ |
1827 | + |
1828 | +using System; |
1829 | +using System.Linq; |
1830 | +using System.Collections.Generic; |
1831 | + |
1832 | +using Mono.Addins; |
1833 | + |
1834 | +using Do.Platform; |
1835 | +using Do.Universe; |
1836 | + |
1837 | +namespace Transmission { |
1838 | + |
1839 | + public class TorrentUnmarkForDownloadAction: Act { |
1840 | + |
1841 | + public TorrentUnmarkForDownloadAction() { |
1842 | + } |
1843 | + |
1844 | + public override string Name { |
1845 | + get { return AddinManager.CurrentLocalizer.GetString ("Unmark for download"); } |
1846 | + } |
1847 | + |
1848 | + public override string Description { |
1849 | + get { return AddinManager.CurrentLocalizer.GetString ("Unmark file as needed to be downloaded"); } |
1850 | + } |
1851 | + |
1852 | + public override string Icon { |
1853 | + get { return "remove"; } |
1854 | + } |
1855 | + |
1856 | + public override IEnumerable<Type> SupportedItemTypes { |
1857 | + get { |
1858 | + yield return typeof (ITorrentEntry); |
1859 | + } |
1860 | + } |
1861 | + |
1862 | + public override IEnumerable<Item> Perform(IEnumerable<Item> items, IEnumerable<Item> modItems) { |
1863 | + TransmissionAPI api = TransmissionPlugin.getTransmission(); |
1864 | + |
1865 | + // Operation is common for all files. |
1866 | + TransmissionAPI.FileOperation operation = new TransmissionAPI.FileOperation(false, null); |
1867 | + |
1868 | + // Group selected items by owner torrent. |
1869 | + var files_by_torrent = items |
1870 | + .Cast<ITorrentEntry>() |
1871 | + .GroupBy( |
1872 | + item => item.Torrent, |
1873 | + (torrent, entries) => new { |
1874 | + Torrent = torrent, |
1875 | + Files = entries.SelectMany(entry => entry.GetFiles()) |
1876 | + } |
1877 | + ); |
1878 | + |
1879 | + // Perform action for each torrent separately. |
1880 | + foreach (var group in files_by_torrent) { |
1881 | + var operations = group.Files.ToDictionary(f => f.Index, f => operation); |
1882 | + api.SetTorrent(group.Torrent.HashString, null, null, null, null, null, operations); |
1883 | + } |
1884 | + |
1885 | + yield break; |
1886 | + } |
1887 | + } |
1888 | +} |
1889 | |
1890 | === added file 'Transmission/src/TorrentVerifyAction.cs' |
1891 | --- Transmission/src/TorrentVerifyAction.cs 1970-01-01 00:00:00 +0000 |
1892 | +++ Transmission/src/TorrentVerifyAction.cs 2010-07-26 16:47:47 +0000 |
1893 | @@ -0,0 +1,42 @@ |
1894 | + |
1895 | +using System; |
1896 | +using System.Linq; |
1897 | +using System.Collections.Generic; |
1898 | + |
1899 | +using Mono.Addins; |
1900 | + |
1901 | +using Do.Universe; |
1902 | + |
1903 | +namespace Transmission { |
1904 | + |
1905 | + public class TorrentVerifyAction: Act { |
1906 | + |
1907 | + public TorrentVerifyAction() { |
1908 | + } |
1909 | + |
1910 | + public override string Name { |
1911 | + get { return AddinManager.CurrentLocalizer.GetString ("Verify"); } |
1912 | + } |
1913 | + |
1914 | + public override string Description { |
1915 | + get { return AddinManager.CurrentLocalizer.GetString ("Verify torrent"); } |
1916 | + } |
1917 | + |
1918 | + public override string Icon { |
1919 | + get { return "dialog-question"; } |
1920 | + } |
1921 | + |
1922 | + public override IEnumerable<Type> SupportedItemTypes { |
1923 | + get { yield return typeof (TorrentItem); } |
1924 | + } |
1925 | + |
1926 | + public override IEnumerable<Item> Perform(IEnumerable<Item> items, IEnumerable<Item> modItems) { |
1927 | + TransmissionAPI api = TransmissionPlugin.getTransmission(); |
1928 | + |
1929 | + var hashes = items.Cast<TorrentItem>().Select(t => t.HashString); |
1930 | + api.VerifyTorrents(hashes); |
1931 | + |
1932 | + return null; |
1933 | + } |
1934 | + } |
1935 | +} |
1936 | |
1937 | === added file 'Transmission/src/TransmissionAPI.cs' |
1938 | --- Transmission/src/TransmissionAPI.cs 1970-01-01 00:00:00 +0000 |
1939 | +++ Transmission/src/TransmissionAPI.cs 2010-07-26 16:47:47 +0000 |
1940 | @@ -0,0 +1,575 @@ |
1941 | + |
1942 | +using System; |
1943 | +using System.IO; |
1944 | +using System.Collections; |
1945 | +using System.Collections.Generic; |
1946 | +using System.Net; |
1947 | +using System.Text; |
1948 | +using Jayrock.Json; |
1949 | + |
1950 | +namespace Transmission { |
1951 | + |
1952 | + /// <summary> |
1953 | + /// Transmission API client. |
1954 | + /// Compatible with RPC version 5 to 10 (release version 1.60 to 2.10). |
1955 | + /// </summary> |
1956 | + public class TransmissionAPI { |
1957 | + |
1958 | + /// <summary> |
1959 | + /// File loading priority. |
1960 | + /// </summary> |
1961 | + public enum FilePriority { |
1962 | + Low, Normal, High |
1963 | + }; |
1964 | + |
1965 | + /// <summary> |
1966 | + /// Operation on individual file from torrent. |
1967 | + /// </summary> |
1968 | + /// <remarks> |
1969 | + /// All fields are nullable, <c>null</c> means "don't change current value". |
1970 | + /// </remarks> |
1971 | + public struct FileOperation { |
1972 | + public FileOperation(bool? download, FilePriority? priority) { |
1973 | + this.download = download; |
1974 | + this.priority = priority; |
1975 | + } |
1976 | + |
1977 | + /// <summary>Whether it is needed to download this file</summary> |
1978 | + public bool? download; |
1979 | + |
1980 | + /// <summary>Priority relative to other files of the same torrent</summary> |
1981 | + public FilePriority? priority; |
1982 | + }; |
1983 | + |
1984 | + /// <summary> |
1985 | + /// Error communicating to Transmission. |
1986 | + /// </summary> |
1987 | + public class TransmissionAPIError: Exception { |
1988 | + public TransmissionAPIError(string message): base(message) {} |
1989 | + public TransmissionAPIError(string message, Exception reason): base(message, reason) {} |
1990 | + }; |
1991 | + |
1992 | + /// <summary> |
1993 | + /// Error returned by Transmission. |
1994 | + /// </summary> |
1995 | + public class TransmissionError: Exception { |
1996 | + public TransmissionError(string message): base(message) { |
1997 | + } |
1998 | + }; |
1999 | + |
2000 | + public const int DEFAULT_PORT = 9091; |
2001 | + public const string DEFAULT_PATH = "/transmission/rpc"; |
2002 | + public const string SESSION_HEADER = "X-Transmission-Session-Id"; |
2003 | + |
2004 | + private string _url, _username, _password; |
2005 | + private string _session_id = ""; |
2006 | + |
2007 | + private delegate void ResultReader(JsonReader json); |
2008 | + |
2009 | + /// <summary>Response handler which does nothing</summary> |
2010 | + /// <remarks>Prefer using <see cref="Call(string, IDictionary<string, object>)"/> instead</remarks> |
2011 | + private void NullHandler(JsonReader json) {} |
2012 | + |
2013 | + /// <summary> |
2014 | + /// Create API client. |
2015 | + /// </summary> |
2016 | + /// <param name="url">Transmission API-RPC URL</param> |
2017 | + /// <param name="username">Username for authentication</param> |
2018 | + /// <param name="password">Password for authentication</param> |
2019 | + /// <remarks>Pass <c>null</c> for both <paramref="username"/> and <paramref="username"/> is |
2020 | + /// authentication isn't needed.</remarks> |
2021 | + public TransmissionAPI(string url, string username, string password) { |
2022 | + _url = url; |
2023 | + _username = username; |
2024 | + _password = password; |
2025 | + } |
2026 | + |
2027 | + /// <summary>Compose request JSON string</summary> |
2028 | + protected string ComposeRequest(string method, IDictionary<string, object> arguments) { |
2029 | + StringWriter sw = new StringWriter(); |
2030 | + |
2031 | + using (JsonWriter json = new JsonTextWriter(sw)) { |
2032 | + json.WriteStartObject(); |
2033 | + |
2034 | + json.WriteMember("method"); |
2035 | + json.WriteString(method); |
2036 | + |
2037 | + json.WriteMember("arguments"); |
2038 | + json.WriteStartObject(); |
2039 | + foreach (KeyValuePair<string, object> pair in arguments) { |
2040 | + string name = pair.Key; |
2041 | + object value = pair.Value; |
2042 | + |
2043 | + json.WriteMember(name); |
2044 | + Jayrock.Json.Conversion.JsonConvert.Export(value, json); |
2045 | + } |
2046 | + json.WriteEndObject(); |
2047 | + |
2048 | + json.WriteEndObject(); |
2049 | + } |
2050 | + |
2051 | + return sw.ToString(); |
2052 | + } |
2053 | + |
2054 | + /// <summary></summary> |
2055 | + /// <param name="payload">HTTP POST request content</param> |
2056 | + /// <returns>HTTP response content</returns> |
2057 | + /// <exception cref="System.Net.WebException"/> |
2058 | + protected string PerformRequest(byte[] payload) { |
2059 | + // Prepare request. |
2060 | + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_url); |
2061 | + request.Method = "POST"; |
2062 | + request.ContentType = "application/x-www-form-urlencoded"; |
2063 | + request.Headers[SESSION_HEADER] = _session_id; |
2064 | + request.ContentLength = payload.Length; |
2065 | + |
2066 | + // Authenticate if credentials are given. |
2067 | + if (_username != null && _password != null) { |
2068 | + string auth = Convert.ToBase64String(Encoding.Default.GetBytes(_username + ":" + _password)); |
2069 | + request.Headers["Authorization"] = "Basic " + auth; |
2070 | + } |
2071 | + |
2072 | + // Perform request. |
2073 | + using (Stream stream = request.GetRequestStream()) { |
2074 | + stream.Write(payload, 0, payload.Length); |
2075 | + } |
2076 | + |
2077 | + // Get response. |
2078 | + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); |
2079 | + return new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8).ReadToEnd(); |
2080 | + } |
2081 | + |
2082 | + /// <summary> |
2083 | + /// Call Transmission API method. |
2084 | + /// </summary> |
2085 | + /// <param name="method">API method name</param> |
2086 | + /// <param name="arguments">Arguments passed to API method</param> |
2087 | + /// <param name="handler">Function called with value returned by method</param> |
2088 | + /// <exception cref="TransmissionError" /> |
2089 | + /// <exception cref="TransmissionAPIError" /> |
2090 | + private void Call(string method, IDictionary<string, object> arguments, ResultReader handler) { |
2091 | + // Compose request and encode it to UTF-8. |
2092 | + string req = ComposeRequest(method, arguments); |
2093 | + byte[] reqb = System.Text.Encoding.UTF8.GetBytes(req); |
2094 | + |
2095 | + try { |
2096 | + |
2097 | + string resp = null; |
2098 | + try { |
2099 | + resp = PerformRequest(reqb); |
2100 | + |
2101 | + } catch (System.Net.WebException err) { |
2102 | + HttpWebResponse response = (HttpWebResponse)err.Response; |
2103 | + |
2104 | + // Transmission 1.53 and 1.6 introduced X-Transmission-Session-Id header |
2105 | + // in order to protect from CSRF attacks. If you make request without |
2106 | + // this header (or your session expire) you'll get 409 response with |
2107 | + // this header set. Just copy header to your request and try again. |
2108 | + if ( |
2109 | + err.Status == WebExceptionStatus.ProtocolError && |
2110 | + response.StatusCode == HttpStatusCode.Conflict |
2111 | + ) { |
2112 | + _session_id = response.Headers[SESSION_HEADER]; |
2113 | + resp = PerformRequest(reqb); |
2114 | + |
2115 | + } else { |
2116 | + throw; |
2117 | + } |
2118 | + } |
2119 | + |
2120 | + JsonReader json_reader = new JsonTextReader(new StringReader(resp)); |
2121 | + |
2122 | + json_reader.ReadToken(JsonTokenClass.Object); |
2123 | + while (json_reader.TokenClass == JsonTokenClass.Member) { |
2124 | + switch (json_reader.ReadMember()) { |
2125 | + case "result": |
2126 | + string result = json_reader.ReadString(); |
2127 | + if (result != "success") |
2128 | + throw new TransmissionError(result); |
2129 | + break; |
2130 | + case "tag": |
2131 | + json_reader.ReadNumber(); |
2132 | + break; |
2133 | + case "arguments": |
2134 | + json_reader.ReadToken(JsonTokenClass.Object); |
2135 | + handler(json_reader); |
2136 | + json_reader.ReadToken(JsonTokenClass.EndObject); |
2137 | + break; |
2138 | + default: |
2139 | + json_reader.Skip(); |
2140 | + break; |
2141 | + } |
2142 | + } |
2143 | + json_reader.ReadToken(JsonTokenClass.EndObject); |
2144 | + json_reader.ReadToken(JsonTokenClass.EOF); |
2145 | + |
2146 | + } catch (System.Net.WebException err) { |
2147 | + throw new TransmissionAPIError("Cannot access Transmission RPC service", err); |
2148 | + } |
2149 | + } |
2150 | + |
2151 | + /// <summary>Call API method and ignore return value</summary> |
2152 | + /// <remarks>This is equivalent to <c>Call(method, arguments, NullHandler)</c>.</remarks> |
2153 | + private void Call(string method, IDictionary<string, object> arguments) { |
2154 | + Call(method, arguments, NullHandler); |
2155 | + } |
2156 | + |
2157 | + /// <summary> |
2158 | + /// Start torrents. |
2159 | + /// </summary> |
2160 | + /// <param name="torrent_hashes">Sequence of torrent's hashes</param> |
2161 | + /// <exception cref="TransmissionAPIError" /> |
2162 | + /// <exception cref="TransmissionError" /> |
2163 | + public void StartTorrents(IEnumerable<string> torrent_hashes) { |
2164 | + Dictionary<string, object> arguments = new Dictionary<string, object>(); |
2165 | + arguments.Add("ids", torrent_hashes); |
2166 | + Call("torrent-start", arguments); |
2167 | + } |
2168 | + |
2169 | + /// <summary> |
2170 | + /// Start all torrents. |
2171 | + /// </summary> |
2172 | + /// <exception cref="TransmissionAPIError" /> |
2173 | + /// <exception cref="TransmissionError" /> |
2174 | + public void StartAllTorrents() { |
2175 | + Call("torrent-start", new Dictionary<string, object>()); |
2176 | + } |
2177 | + |
2178 | + /// <summary> |
2179 | + /// Stop torrents. |
2180 | + /// </summary> |
2181 | + /// <param name="torrent_hashes">Sequence of torrent's hashes</param> |
2182 | + /// <exception cref="TransmissionAPIError" /> |
2183 | + /// <exception cref="TransmissionError" /> |
2184 | + public void StopTorrents(IEnumerable<string> torrent_hashes) { |
2185 | + Dictionary<string, object> arguments = new Dictionary<string, object>(); |
2186 | + arguments.Add("ids", torrent_hashes); |
2187 | + Call("torrent-stop", arguments); |
2188 | + } |
2189 | + |
2190 | + /// <summary> |
2191 | + /// Stop all torrents. |
2192 | + /// </summary> |
2193 | + /// <exception cref="TransmissionAPIError" /> |
2194 | + /// <exception cref="TransmissionError" /> |
2195 | + public void StopAllTorrents() { |
2196 | + Call("torrent-stop", new Dictionary<string, object>()); |
2197 | + } |
2198 | + |
2199 | + /// <summary> |
2200 | + /// Start torrents verification. |
2201 | + /// </summary> |
2202 | + /// <param name="torrent_hashes">Sequence of torrent's hashes to verify</param> |
2203 | + /// <exception cref="TransmissionAPIError" /> |
2204 | + /// <exception cref="TransmissionError" /> |
2205 | + public void VerifyTorrents(IEnumerable<string> torrent_hashes) { |
2206 | + Dictionary<string, object> arguments = new Dictionary<string, object>(); |
2207 | + arguments.Add("ids", torrent_hashes); |
2208 | + Call("torrent-verify", arguments); |
2209 | + } |
2210 | + |
2211 | + /// <summary> |
2212 | + /// Start torrents verification for all torrents. |
2213 | + /// </summary> |
2214 | + /// <exception cref="TransmissionAPIError" /> |
2215 | + /// <exception cref="TransmissionError" /> |
2216 | + public void VerifyAllTorrents() { |
2217 | + Call("torrent-verify", new Dictionary<string, object>()); |
2218 | + } |
2219 | + |
2220 | + /// <summary> |
2221 | + /// Set torrents' properties. |
2222 | + /// |
2223 | + /// Not all torrent properties can be changed using this method, because some of them |
2224 | + /// are meaningless for torrent group, e.g. file priorities. Use <c>SetTorrent</c> method |
2225 | + /// to set such properties. |
2226 | + /// </summary> |
2227 | + /// <param name="torrent_hashes">Sequence of torrents hashed to modify</param> |
2228 | + /// <param name="peer_limit">Maximum number of used peers, if it is <c>null</c> then value won't be changed.</param> |
2229 | + /// <param name="limit_download"> |
2230 | + /// Downloading speed limit switch, if it is <c>true</c>, downloading speed will be limited, |
2231 | + /// if it is <c>false</c>, downloading speed isn't limited, if it is <c>null</c>, limit switch won't be changed. |
2232 | + /// A <see cref="System.Nullable"/> |
2233 | + /// </param> |
2234 | + /// <param name="download_speed_limit"> |
2235 | + /// A <see cref="System.Nullable"/> |
2236 | + /// </param> |
2237 | + /// <param name="limit_upload"> |
2238 | + /// A <see cref="System.Nullable"/> |
2239 | + /// </param> |
2240 | + /// <param name="upload_speed_limit"> |
2241 | + /// A <see cref="System.Nullable"/> |
2242 | + /// </param> |
2243 | + public void SetTorrents(IEnumerable<string> torrent_hashes, int? peer_limit, bool? limit_download, int? download_speed_limit, bool? limit_upload, int? upload_speed_limit) { |
2244 | + Dictionary<string, object> arguments = new Dictionary<string, object>(); |
2245 | + |
2246 | + arguments.Add("ids", torrent_hashes); |
2247 | + |
2248 | + if (peer_limit != null) |
2249 | + arguments.Add("peer-limit", peer_limit); |
2250 | + |
2251 | + if (limit_download.HasValue) { |
2252 | + if (limit_download.Value) { |
2253 | + arguments.Add("downloadLimited", true); |
2254 | + if (download_speed_limit.HasValue) |
2255 | + arguments.Add("downloadLimit", download_speed_limit.Value); |
2256 | + } else { |
2257 | + arguments.Add("downloadLimited", false); |
2258 | + } |
2259 | + } |
2260 | + |
2261 | + if (limit_upload.HasValue) { |
2262 | + if (limit_upload.Value) { |
2263 | + arguments.Add("uploadLimited", true); |
2264 | + if (upload_speed_limit.HasValue) |
2265 | + arguments.Add("uploadLimit", upload_speed_limit.Value); |
2266 | + } else { |
2267 | + arguments.Add("uploadLimited", false); |
2268 | + } |
2269 | + } |
2270 | + |
2271 | + Call("torrent-set", arguments); |
2272 | + } |
2273 | + |
2274 | + public void SetTorrent(string torrent_hash, int? peer_limit, bool? limit_download, int? download_speed_limit, bool? limit_upload, int? upload_speed_limit, IDictionary<int, FileOperation> files) { |
2275 | + Dictionary<string, object> arguments = new Dictionary<string, object>(); |
2276 | + |
2277 | + arguments.Add("ids", new string[] { torrent_hash }); |
2278 | + |
2279 | + if (peer_limit != null) |
2280 | + arguments.Add("peer-limit", peer_limit); |
2281 | + |
2282 | + if (limit_download.HasValue) { |
2283 | + if (limit_download.Value) { |
2284 | + arguments.Add("downloadLimited", true); |
2285 | + if (download_speed_limit.HasValue) |
2286 | + arguments.Add("downloadLimit", download_speed_limit.Value); |
2287 | + } else { |
2288 | + arguments.Add("downloadLimited", false); |
2289 | + } |
2290 | + } |
2291 | + |
2292 | + if (limit_upload.HasValue) { |
2293 | + if (limit_upload.Value) { |
2294 | + arguments.Add("uploadLimited", true); |
2295 | + if (upload_speed_limit.HasValue) |
2296 | + arguments.Add("uploadLimit", upload_speed_limit.Value); |
2297 | + } else { |
2298 | + arguments.Add("uploadLimited", false); |
2299 | + } |
2300 | + } |
2301 | + |
2302 | + List<int> wanted_files = new List<int>(); |
2303 | + List<int> unwanted_files = new List<int>(); |
2304 | + List<int> low_priority_files = new List<int>(); |
2305 | + List<int> normal_priority_files = new List<int>(); |
2306 | + List<int> high_priority_files = new List<int>(); |
2307 | + foreach (KeyValuePair<int, FileOperation> op in files) { |
2308 | + int index = op.Key; |
2309 | + FileOperation file = op.Value; |
2310 | + |
2311 | + if (file.download.HasValue) { |
2312 | + if (file.download.Value) wanted_files.Add(index); |
2313 | + else unwanted_files.Add(index); |
2314 | + } |
2315 | + |
2316 | + if (file.priority.HasValue) { |
2317 | + switch (file.priority.Value) { |
2318 | + case FilePriority.Low: low_priority_files.Add(index); break; |
2319 | + case FilePriority.Normal: normal_priority_files.Add(index); break; |
2320 | + case FilePriority.High: high_priority_files.Add(index); break; |
2321 | + } |
2322 | + } |
2323 | + } |
2324 | + if (wanted_files.Count > 0) arguments.Add("files-wanted", wanted_files); |
2325 | + if (unwanted_files.Count > 0) arguments.Add("files-unwanted", unwanted_files); |
2326 | + if (low_priority_files.Count > 0) arguments.Add("priority-low", low_priority_files); |
2327 | + if (normal_priority_files.Count > 0) arguments.Add("priority-normal", normal_priority_files); |
2328 | + if (high_priority_files.Count > 0) arguments.Add("priority-high", high_priority_files); |
2329 | + |
2330 | + Call("torrent-set", arguments); |
2331 | + } |
2332 | + |
2333 | + /// <summary> |
2334 | + /// Torrent status. |
2335 | + /// </summary> |
2336 | + public enum TorrentStatus { |
2337 | + CheckWait = 1, Check = 2, Download = 4, Seed = 8, Stopped = 16 |
2338 | + }; |
2339 | + |
2340 | + public class TorrentInfo { |
2341 | + public int Id; // Torrent's unique ID within Transmission. |
2342 | + public string Comment; |
2343 | + public string HashString; |
2344 | + public string Name; |
2345 | + public string DownloadDir; |
2346 | + public IList<TorrentFileInfo> files; |
2347 | + public TorrentStatus Status; |
2348 | + public long TotalSize; |
2349 | + |
2350 | + public int DownloadLimit; |
2351 | + public bool DownloadLimited; |
2352 | + public int UploadLimit; |
2353 | + public bool UploadLimited; |
2354 | + }; |
2355 | + |
2356 | + public class TorrentFileInfo { |
2357 | + public string Name; |
2358 | + public long Length; |
2359 | + public long BytesCompleted; |
2360 | + public bool Wanted; |
2361 | + public FilePriority Priority; |
2362 | + }; |
2363 | + |
2364 | + /// <summary>Get information about all torrents.</summary> |
2365 | + /// <remarks>This is equivalent to <c>GetTorrents(null)</c>.</remarks> |
2366 | + public IEnumerable<TorrentInfo> GetAllTorrents() { |
2367 | + return GetTorrents(null); |
2368 | + } |
2369 | + |
2370 | + public IEnumerable<TorrentInfo> GetTorrents(IEnumerable<string> torrent_hashes) { |
2371 | + Dictionary<string, object> arguments = new Dictionary<string, object>(); |
2372 | + if (torrent_hashes != null) arguments.Add("ids", torrent_hashes); |
2373 | + arguments.Add("fields", new string[] {"comment", "downloadDir", "files", "hashString", "id", "name", "priorities", "status", "totalSize", "wanted", "downloadLimited", "downloadLimit", "uploadLimited", "uploadLimit"}); |
2374 | + |
2375 | + List<TorrentInfo> torrents = new List<TorrentInfo>(); |
2376 | + |
2377 | + Jayrock.Json.Conversion.ImportContext jsonctx = new Jayrock.Json.Conversion.ImportContext(); |
2378 | + jsonctx.Register(new ListImporter<int>()); |
2379 | + jsonctx.Register(new ListImporter<TorrentFileInfo>()); |
2380 | + |
2381 | + Call("torrent-get", arguments, delegate(JsonReader json) { |
2382 | + while (json.TokenClass == JsonTokenClass.Member) { |
2383 | + switch (json.ReadMember()) { |
2384 | + case "torrents": |
2385 | + json.ReadToken(JsonTokenClass.Array); |
2386 | + while (json.TokenClass != JsonTokenClass.EndArray) { |
2387 | + |
2388 | + json.ReadToken(JsonTokenClass.Object); |
2389 | + |
2390 | + TorrentInfo torrent = new TorrentInfo(); |
2391 | + IList<TorrentFileInfo> files = null; |
2392 | + IList<int> wanted = null; |
2393 | + IList<int> priorities = null; |
2394 | + |
2395 | + while (json.TokenClass == JsonTokenClass.Member) { |
2396 | + switch (json.ReadMember()) { |
2397 | + case "comment": torrent.Comment = json.ReadString(); break; |
2398 | + case "hashString": torrent.HashString = json.ReadString(); break; |
2399 | + case "name": torrent.Name = json.ReadString(); break; |
2400 | + case "id": torrent.Id = json.ReadNumber().ToInt32(); break; |
2401 | + case "downloadDir": torrent.DownloadDir = json.ReadString(); break; |
2402 | + case "status": torrent.Status = (TorrentStatus)json.ReadNumber().ToInt32(); break; |
2403 | + case "totalSize": torrent.TotalSize = json.ReadNumber().ToInt64(); break; |
2404 | + case "wanted": wanted = (IList<int>)jsonctx.Import(typeof(List<int>), json); break; |
2405 | + case "priorities": priorities = (IList<int>)jsonctx.Import(typeof(List<int>), json); break; |
2406 | + case "files": files = jsonctx.Import(typeof(List<TorrentFileInfo>), json) as IList<TorrentFileInfo>; break; |
2407 | + case "downloadLimited": torrent.DownloadLimited = json.ReadBoolean(); break; |
2408 | + case "downloadLimit": torrent.DownloadLimit = json.ReadNumber().ToInt32(); break; |
2409 | + case "uploadLimited": torrent.UploadLimited = json.ReadBoolean(); break; |
2410 | + case "uploadLimit": torrent.UploadLimit = json.ReadNumber().ToInt32(); break; |
2411 | + } |
2412 | + } |
2413 | + |
2414 | + for (int i = 0; i < files.Count; ++i) { |
2415 | + files[i].Wanted = wanted[i] == 1; |
2416 | + |
2417 | + int prio = priorities[i]; |
2418 | + if (prio < -1 || prio > 1) |
2419 | + throw new TransmissionAPIError(string.Format("Invalid priority value: {0}", prio)); |
2420 | + files[i].Priority = (FilePriority)(prio+1); |
2421 | + } |
2422 | + torrent.files = files; |
2423 | + torrents.Add(torrent); |
2424 | + |
2425 | + json.ReadToken(JsonTokenClass.EndObject); |
2426 | + } |
2427 | + json.ReadToken(JsonTokenClass.EndArray); |
2428 | + break; |
2429 | + default: |
2430 | + json.Skip(); |
2431 | + break; |
2432 | + } |
2433 | + } |
2434 | + }); |
2435 | + |
2436 | + return torrents; |
2437 | + } |
2438 | + |
2439 | + // Transmission RPC allows to use .torrent file content instead of it's filename, but |
2440 | + // this isn't supported. |
2441 | + public void AddTorrent(string filename, string download_to, bool paused, int? peer_limit) { |
2442 | + Dictionary<string, object> arguments = new Dictionary<string, object>(); |
2443 | + arguments.Add("filename", filename); |
2444 | + arguments.Add("download-dir", download_to); |
2445 | + arguments.Add("paused", paused); |
2446 | + if (peer_limit.HasValue) arguments.Add("peer-limit", peer_limit.Value); |
2447 | + Call("torrent-add", arguments); |
2448 | + } |
2449 | + |
2450 | + /// <summary> |
2451 | + /// Remove torrents. |
2452 | + /// </summary> |
2453 | + /// <param name="hashes">Sequence of torrent hashes to remove.</param> |
2454 | + /// <param name="delete_files">Whether downloaded files should be deleted or not.</param> |
2455 | + public void RemoveTorrent(IEnumerable<string> hashes, bool delete_files) { |
2456 | + Dictionary<string, object> arguments = new Dictionary<string, object>(); |
2457 | + arguments.Add("ids", hashes); |
2458 | + arguments.Add("delete-load-data", delete_files); |
2459 | + Call("torrent-remove", arguments); |
2460 | + } |
2461 | + |
2462 | + /// <summary> |
2463 | + /// Set session parameters. |
2464 | + /// </summary> |
2465 | + /// <param name="download_dir"> |
2466 | + /// Path to directory to download torrent contents to. |
2467 | + /// Pass <c>null</c> to keep old value. |
2468 | + /// </param> |
2469 | + /// <param name="peer_limit"> |
2470 | + /// Global limit on number of connected peers. Pass <c>null</c> to keep old value. |
2471 | + /// </param> |
2472 | + /// <param name="limit_download"> |
2473 | + /// Global limit on number of connected peers. Pass <c>null</c> to keep old value. |
2474 | + /// </param> |
2475 | + public void SetSession( |
2476 | + string download_dir, int? peer_limit, |
2477 | + bool? limit_download, int? download_speed_limit, bool? limit_upload, int? upload_speed_limit |
2478 | + ) { |
2479 | + Dictionary<string, object> arguments = new Dictionary<string, object>(); |
2480 | + |
2481 | + if (download_dir != null) |
2482 | + arguments.Add("download-dir", download_dir); |
2483 | + |
2484 | + if (peer_limit.HasValue) |
2485 | + arguments.Add("peer-limit", peer_limit.Value); |
2486 | + |
2487 | + if (limit_download.HasValue) { |
2488 | + if (limit_download.Value) { |
2489 | + arguments.Add("downloadLimited", true); |
2490 | + if (download_speed_limit.HasValue) |
2491 | + arguments.Add("downloadLimit", download_speed_limit.Value); |
2492 | + } else { |
2493 | + arguments.Add("downloadLimited", false); |
2494 | + } |
2495 | + } |
2496 | + |
2497 | + if (limit_upload.HasValue) { |
2498 | + if (limit_upload.Value) { |
2499 | + arguments.Add("uploadLimited", true); |
2500 | + if (upload_speed_limit.HasValue) |
2501 | + arguments.Add("uploadLimit", upload_speed_limit.Value); |
2502 | + } else { |
2503 | + arguments.Add("uploadLimited", false); |
2504 | + } |
2505 | + } |
2506 | + |
2507 | + Call("session-set", arguments); |
2508 | + } |
2509 | + |
2510 | + public void GetSession() { |
2511 | + Call("session-get", new Dictionary<string, object>()); |
2512 | + } |
2513 | + |
2514 | + } |
2515 | +} |
2516 | |
2517 | === added file 'Transmission/src/TransmissionPlugin.cs' |
2518 | --- Transmission/src/TransmissionPlugin.cs 1970-01-01 00:00:00 +0000 |
2519 | +++ Transmission/src/TransmissionPlugin.cs 2010-07-26 16:47:47 +0000 |
2520 | @@ -0,0 +1,50 @@ |
2521 | +using System; |
2522 | +using System.Collections.Generic; |
2523 | + |
2524 | +using Do.Platform; |
2525 | + |
2526 | +namespace Transmission { |
2527 | + |
2528 | + public class ConnectionParameters { |
2529 | + public ConnectionParameters(string url, string username, string password) { |
2530 | + this.url = url; |
2531 | + this.username = username; |
2532 | + this.password = password; |
2533 | + } |
2534 | + |
2535 | + public string url; |
2536 | + public string username; |
2537 | + public string password; |
2538 | + }; |
2539 | + |
2540 | + public class TransmissionPlugin { |
2541 | + private static TransmissionAPI transmission; |
2542 | + |
2543 | + public static TransmissionAPI getTransmission() { |
2544 | + if (transmission == null) { |
2545 | + ConnectionParameters p = getTransmissionConnectionParameters(); |
2546 | + Log<TransmissionPlugin>.Info("Using Transmission on {0}", p.url); |
2547 | + Log<TransmissionPlugin>.Debug("Using name, password: {0}:{1}", p.username, p.password); |
2548 | + transmission = new TransmissionAPI(p.url, p.username, p.password); |
2549 | + } |
2550 | + return transmission; |
2551 | + } |
2552 | + |
2553 | + public static void ResetConnection() { |
2554 | + transmission = null; |
2555 | + } |
2556 | + |
2557 | + public static ConnectionParameters getTransmissionConnectionParameters() { |
2558 | + string host = TransmissionConfig.Address; |
2559 | + int port = TransmissionConfig.Port; |
2560 | + string username = TransmissionConfig.UserName; |
2561 | + string password = TransmissionConfig.Password; |
2562 | + |
2563 | + string url = string.Format("http://{0}:{1}/transmission/rpc", host, port); |
2564 | + return new ConnectionParameters(url, username, password); |
2565 | + } |
2566 | + |
2567 | + }; |
2568 | + |
2569 | +} |
2570 | + |
2571 | |
2572 | === added file 'Transmission/src/Utils.cs' |
2573 | --- Transmission/src/Utils.cs 1970-01-01 00:00:00 +0000 |
2574 | +++ Transmission/src/Utils.cs 2010-07-26 16:47:47 +0000 |
2575 | @@ -0,0 +1,111 @@ |
2576 | + |
2577 | +using System; |
2578 | +using System.Linq; |
2579 | +using System.Collections.Generic; |
2580 | +using System.Text.RegularExpressions; |
2581 | + |
2582 | +using Do.Platform; |
2583 | +using Do.Universe; |
2584 | + |
2585 | +namespace Transmission { |
2586 | + |
2587 | + class Utils { |
2588 | + |
2589 | + public static int ParseSpeed(string speed) { |
2590 | + Regex regex = new Regex( |
2591 | + @"^(\d+)\s*(b|[km]i?b?)$", |
2592 | + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace |
2593 | + ); |
2594 | + Match match = regex.Match(speed); |
2595 | + |
2596 | + if (match.Success) { |
2597 | + int number = int.Parse(match.Groups[1].Value); |
2598 | + string unit = match.Groups[2].Value.ToLower(); |
2599 | + int scale = 1; |
2600 | + |
2601 | + if (unit == "" || unit[0] == 'k') scale = 1; |
2602 | + else if (unit[0] == 'm') scale = 1024; |
2603 | + |
2604 | + return number * scale; |
2605 | + |
2606 | + } else { |
2607 | + throw new ArgumentException("Invalid speed string"); |
2608 | + } |
2609 | + } |
2610 | + |
2611 | + public static string FormatAmount(float amount, string baseFormat, float[] scales, string[] formats) { |
2612 | + if (scales.Length != formats.Length) |
2613 | + throw new ArgumentException("'scales' and 'formats' arguments must have equal length"); |
2614 | + |
2615 | + // The typical scales count is three to five, so don't use binary search, |
2616 | + // but just plain reverse loop. |
2617 | + for (int i = scales.Length-1; i >= 0; --i) { |
2618 | + if (amount >= scales[i]) |
2619 | + return string.Format(formats[i], amount / scales[i]); |
2620 | + } |
2621 | + |
2622 | + return string.Format(baseFormat, amount); |
2623 | + } |
2624 | + |
2625 | + // Format speed in KiB/sec into human-readable representation. |
2626 | + public static string FormatSpeed(int speed_kbytes_sec) { |
2627 | + return FormatAmount(speed_kbytes_sec, "{0} KiB/sec", |
2628 | + new float[] { 1024, 1024*1024}, |
2629 | + new string[] {"{0:#.#} MiB/sec", "{0:#.#} GiB/sec"} |
2630 | + ); |
2631 | + } |
2632 | + |
2633 | + // Format size in bytes into human-readable representation. |
2634 | + public static string FormatSize(long size_bytes) { |
2635 | + return FormatAmount(size_bytes, "{0} B", |
2636 | + new float[] { 1024, 1024*1024, 1024*1024*1024}, |
2637 | + new string[] {"{0:#.#} KiB", "{0:#.#} MiB", "{0:#.##} GiB"} |
2638 | + ); |
2639 | + } |
2640 | + |
2641 | + public readonly static IEnumerable<PredefinedSpeed> PredefinedSpeedItems = new List<PredefinedSpeed>() { |
2642 | + new PredefinedSpeed( 10, "10 KiB/sec", ""), |
2643 | + new PredefinedSpeed( 20, "20 KiB/sec", ""), |
2644 | + new PredefinedSpeed( 50, "50 KiB/sec", ""), |
2645 | + new PredefinedSpeed( 100, "100 KiB/sec", ""), |
2646 | + new PredefinedSpeed( 200, "200 KiB/sec", ""), |
2647 | + new PredefinedSpeed( 500, "500 KiB/sec", ""), |
2648 | + new PredefinedSpeed( 1 * 1024, "1 MiB/sec", ""), |
2649 | + new PredefinedSpeed( 2 * 1024, "2 MiB/sec", ""), |
2650 | + new PredefinedSpeed( 5 * 1024, "5 MiB/sec", ""), |
2651 | + new PredefinedSpeed( 10 * 1024, "10 MiB/sec", ""), |
2652 | + new PredefinedSpeed( 20 * 1024, "20 MiB/sec", ""), |
2653 | + new PredefinedSpeed( 50 * 1024, "50 MiB/sec", ""), |
2654 | + new PredefinedSpeed(100 * 1024, "100 MiB/sec", ""), |
2655 | + }; |
2656 | + |
2657 | + } |
2658 | + |
2659 | + public class PredefinedSpeed: Item { |
2660 | + private string _name, _desc; |
2661 | + private int _value; |
2662 | + |
2663 | + public PredefinedSpeed(int value, string name, string desc) { |
2664 | + _value = value; |
2665 | + _name = name; |
2666 | + _desc = desc; |
2667 | + } |
2668 | + |
2669 | + public override string Name { |
2670 | + get { return _name; } |
2671 | + } |
2672 | + |
2673 | + public override string Description { |
2674 | + get { return _desc; } |
2675 | + } |
2676 | + |
2677 | + public override string Icon { |
2678 | + get { return "top"; } |
2679 | + } |
2680 | + |
2681 | + public int Value { |
2682 | + get { return _value; } |
2683 | + } |
2684 | + } |
2685 | + |
2686 | +} |
2687 | |
2688 | === modified file 'configure.ac' |
2689 | --- configure.ac 2010-03-08 02:43:56 +0000 |
2690 | +++ configure.ac 2010-07-26 16:47:47 +0000 |
2691 | @@ -383,6 +383,8 @@ |
2692 | Tracker/Resources/TrackerSearch.addin.xml |
2693 | Translate/Makefile |
2694 | Translate/Resources/Translate.addin.xml |
2695 | +Transmission/Makefile |
2696 | +Transmission/Resources/Transmission.addin.xml |
2697 | Tomboy/Makefile |
2698 | Tomboy/Resources/Tomboy.addin.xml |
2699 | Vinagre/Makefile |
Oh, wow. Sorry for missing this for so long!
This looks good. I've only got two minor niggles, and one larger one. The two minor ones are: you should have copyright headers on the files you've created, and I'd generally use a lot more automatic properties rather than explicit private _foo variables.
The major one is that it bundles a binary copy of Jayrock.Json. We generally try to minimise the binaries we bundle in the source tree; most distributions will not accept packages with binaries bundled like this.
Given the terrible length of time that this has been waiting for a review, I'm happy to make these changes myself if you don't want to. I would like your email address, though, so that I can credit you in the Authors file properly.