Merge lp:~dobey/rhythmbox-ubuntuone/update-from-trunk into lp:rhythmbox-ubuntuone/stable-3-0

Proposed by dobey on 2012-01-18
Status: Merged
Approved by: dobey on 2012-01-19
Approved revision: no longer in the source branch.
Merged at revision: 106
Proposed branch: lp:~dobey/rhythmbox-ubuntuone/update-from-trunk
Merge into: lp:rhythmbox-ubuntuone/stable-3-0
Diff against target: 2092 lines (+957/-890)
14 files modified
COPYING (+668/-159)
COPYING.LIB (+165/-0)
MANIFEST.in (+3/-4)
po/POTFILES.in (+3/-4)
rb.py (+0/-39)
rhythmdb.py (+0/-12)
run-tests (+1/-1)
setup.cfg (+1/-1)
setup.py (+11/-12)
ubuntuone/MusicStoreWidget.py (+52/-123)
ubuntuone/ubuntuone.plugin.in (+7/-6)
ubuntuone/ubuntuone.py (+46/-41)
umusicstore/U1MSLinks.py (+0/-380)
umusicstore/u1msurl.glade (+0/-108)
To merge this branch: bzr merge lp:~dobey/rhythmbox-ubuntuone/update-from-trunk
Reviewer Review Type Date Requested Status
Brian Curtin (community) Approve on 2012-01-18
Roberto Alsina (community) 2012-01-18 Approve on 2012-01-18
Review via email: mp+89126@code.launchpad.net

Commit Message

Update the plug-in to load in Rhythmbox 3.x, with a minimal set of functionality
Remove the U1MSLinks code and UI, as it's not the best way to implement the feature, and is more complex now

To post a comment you must log in.
Roberto Alsina (ralsina) wrote :

+1

review: Approve
Brian Curtin (brian.curtin) wrote :

Looks fine.

review: Approve
106. By dobey on 2012-01-19

Update the plug-in to load in Rhythmbox 3.x, with a minimal set of functionality
Remove the U1MSLinks code and UI, as it's not the best way to implement the feature, and is more complex now

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'COPYING'
2--- COPYING 2010-01-06 15:26:32 +0000
3+++ COPYING 2012-01-19 20:21:35 +0000
4@@ -1,165 +1,674 @@
5- GNU LESSER GENERAL PUBLIC LICENSE
6+ GNU GENERAL PUBLIC LICENSE
7 Version 3, 29 June 2007
8
9 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
10 Everyone is permitted to copy and distribute verbatim copies
11 of this license document, but changing it is not allowed.
12
13-
14- This version of the GNU Lesser General Public License incorporates
15-the terms and conditions of version 3 of the GNU General Public
16-License, supplemented by the additional permissions listed below.
17-
18- 0. Additional Definitions.
19-
20- As used herein, "this License" refers to version 3 of the GNU Lesser
21-General Public License, and the "GNU GPL" refers to version 3 of the GNU
22-General Public License.
23-
24- "The Library" refers to a covered work governed by this License,
25-other than an Application or a Combined Work as defined below.
26-
27- An "Application" is any work that makes use of an interface provided
28-by the Library, but which is not otherwise based on the Library.
29-Defining a subclass of a class defined by the Library is deemed a mode
30-of using an interface provided by the Library.
31-
32- A "Combined Work" is a work produced by combining or linking an
33-Application with the Library. The particular version of the Library
34-with which the Combined Work was made is also called the "Linked
35-Version".
36-
37- The "Minimal Corresponding Source" for a Combined Work means the
38-Corresponding Source for the Combined Work, excluding any source code
39-for portions of the Combined Work that, considered in isolation, are
40-based on the Application, and not on the Linked Version.
41-
42- The "Corresponding Application Code" for a Combined Work means the
43-object code and/or source code for the Application, including any data
44-and utility programs needed for reproducing the Combined Work from the
45-Application, but excluding the System Libraries of the Combined Work.
46-
47- 1. Exception to Section 3 of the GNU GPL.
48-
49- You may convey a covered work under sections 3 and 4 of this License
50-without being bound by section 3 of the GNU GPL.
51-
52- 2. Conveying Modified Versions.
53-
54- If you modify a copy of the Library, and, in your modifications, a
55-facility refers to a function or data to be supplied by an Application
56-that uses the facility (other than as an argument passed when the
57-facility is invoked), then you may convey a copy of the modified
58-version:
59-
60- a) under this License, provided that you make a good faith effort to
61- ensure that, in the event an Application does not supply the
62- function or data, the facility still operates, and performs
63- whatever part of its purpose remains meaningful, or
64-
65- b) under the GNU GPL, with none of the additional permissions of
66- this License applicable to that copy.
67-
68- 3. Object Code Incorporating Material from Library Header Files.
69-
70- The object code form of an Application may incorporate material from
71-a header file that is part of the Library. You may convey such object
72-code under terms of your choice, provided that, if the incorporated
73-material is not limited to numerical parameters, data structure
74-layouts and accessors, or small macros, inline functions and templates
75-(ten or fewer lines in length), you do both of the following:
76-
77- a) Give prominent notice with each copy of the object code that the
78- Library is used in it and that the Library and its use are
79- covered by this License.
80-
81- b) Accompany the object code with a copy of the GNU GPL and this license
82- document.
83-
84- 4. Combined Works.
85-
86- You may convey a Combined Work under terms of your choice that,
87-taken together, effectively do not restrict modification of the
88-portions of the Library contained in the Combined Work and reverse
89-engineering for debugging such modifications, if you also do each of
90-the following:
91-
92- a) Give prominent notice with each copy of the Combined Work that
93- the Library is used in it and that the Library and its use are
94- covered by this License.
95-
96- b) Accompany the Combined Work with a copy of the GNU GPL and this license
97- document.
98-
99- c) For a Combined Work that displays copyright notices during
100- execution, include the copyright notice for the Library among
101- these notices, as well as a reference directing the user to the
102- copies of the GNU GPL and this license document.
103-
104- d) Do one of the following:
105-
106- 0) Convey the Minimal Corresponding Source under the terms of this
107- License, and the Corresponding Application Code in a form
108- suitable for, and under terms that permit, the user to
109- recombine or relink the Application with a modified version of
110- the Linked Version to produce a modified Combined Work, in the
111- manner specified by section 6 of the GNU GPL for conveying
112- Corresponding Source.
113-
114- 1) Use a suitable shared library mechanism for linking with the
115- Library. A suitable mechanism is one that (a) uses at run time
116- a copy of the Library already present on the user's computer
117- system, and (b) will operate properly with a modified version
118- of the Library that is interface-compatible with the Linked
119- Version.
120-
121- e) Provide Installation Information, but only if you would otherwise
122- be required to provide such information under section 6 of the
123- GNU GPL, and only to the extent that such information is
124- necessary to install and execute a modified version of the
125- Combined Work produced by recombining or relinking the
126- Application with a modified version of the Linked Version. (If
127- you use option 4d0, the Installation Information must accompany
128- the Minimal Corresponding Source and Corresponding Application
129- Code. If you use option 4d1, you must provide the Installation
130- Information in the manner specified by section 6 of the GNU GPL
131- for conveying Corresponding Source.)
132-
133- 5. Combined Libraries.
134-
135- You may place library facilities that are a work based on the
136-Library side by side in a single library together with other library
137-facilities that are not Applications and are not covered by this
138-License, and convey such a combined library under terms of your
139-choice, if you do both of the following:
140-
141- a) Accompany the combined library with a copy of the same work based
142- on the Library, uncombined with any other library facilities,
143- conveyed under the terms of this License.
144-
145- b) Give prominent notice with the combined library that part of it
146- is a work based on the Library, and explaining where to find the
147- accompanying uncombined form of the same work.
148-
149- 6. Revised Versions of the GNU Lesser General Public License.
150-
151- The Free Software Foundation may publish revised and/or new versions
152-of the GNU Lesser General Public License from time to time. Such new
153-versions will be similar in spirit to the present version, but may
154-differ in detail to address new problems or concerns.
155-
156- Each version is given a distinguishing version number. If the
157-Library as you received it specifies that a certain numbered version
158-of the GNU Lesser General Public License "or any later version"
159-applies to it, you have the option of following the terms and
160-conditions either of that published version or of any later version
161-published by the Free Software Foundation. If the Library as you
162-received it does not specify a version number of the GNU Lesser
163-General Public License, you may choose any version of the GNU Lesser
164-General Public License ever published by the Free Software Foundation.
165-
166- If the Library as you received it specifies that a proxy can decide
167-whether future versions of the GNU Lesser General Public License shall
168-apply, that proxy's public statement of acceptance of any version is
169-permanent authorization for you to choose that version for the
170-Library.
171+ Preamble
172+
173+ The GNU General Public License is a free, copyleft license for
174+software and other kinds of works.
175+
176+ The licenses for most software and other practical works are designed
177+to take away your freedom to share and change the works. By contrast,
178+the GNU General Public License is intended to guarantee your freedom to
179+share and change all versions of a program--to make sure it remains free
180+software for all its users. We, the Free Software Foundation, use the
181+GNU General Public License for most of our software; it applies also to
182+any other work released this way by its authors. You can apply it to
183+your programs, too.
184+
185+ When we speak of free software, we are referring to freedom, not
186+price. Our General Public Licenses are designed to make sure that you
187+have the freedom to distribute copies of free software (and charge for
188+them if you wish), that you receive source code or can get it if you
189+want it, that you can change the software or use pieces of it in new
190+free programs, and that you know you can do these things.
191+
192+ To protect your rights, we need to prevent others from denying you
193+these rights or asking you to surrender the rights. Therefore, you have
194+certain responsibilities if you distribute copies of the software, or if
195+you modify it: responsibilities to respect the freedom of others.
196+
197+ For example, if you distribute copies of such a program, whether
198+gratis or for a fee, you must pass on to the recipients the same
199+freedoms that you received. You must make sure that they, too, receive
200+or can get the source code. And you must show them these terms so they
201+know their rights.
202+
203+ Developers that use the GNU GPL protect your rights with two steps:
204+(1) assert copyright on the software, and (2) offer you this License
205+giving you legal permission to copy, distribute and/or modify it.
206+
207+ For the developers' and authors' protection, the GPL clearly explains
208+that there is no warranty for this free software. For both users' and
209+authors' sake, the GPL requires that modified versions be marked as
210+changed, so that their problems will not be attributed erroneously to
211+authors of previous versions.
212+
213+ Some devices are designed to deny users access to install or run
214+modified versions of the software inside them, although the manufacturer
215+can do so. This is fundamentally incompatible with the aim of
216+protecting users' freedom to change the software. The systematic
217+pattern of such abuse occurs in the area of products for individuals to
218+use, which is precisely where it is most unacceptable. Therefore, we
219+have designed this version of the GPL to prohibit the practice for those
220+products. If such problems arise substantially in other domains, we
221+stand ready to extend this provision to those domains in future versions
222+of the GPL, as needed to protect the freedom of users.
223+
224+ Finally, every program is threatened constantly by software patents.
225+States should not allow patents to restrict development and use of
226+software on general-purpose computers, but in those that do, we wish to
227+avoid the special danger that patents applied to a free program could
228+make it effectively proprietary. To prevent this, the GPL assures that
229+patents cannot be used to render the program non-free.
230+
231+ The precise terms and conditions for copying, distribution and
232+modification follow.
233+
234+ TERMS AND CONDITIONS
235+
236+ 0. Definitions.
237+
238+ "This License" refers to version 3 of the GNU General Public License.
239+
240+ "Copyright" also means copyright-like laws that apply to other kinds of
241+works, such as semiconductor masks.
242+
243+ "The Program" refers to any copyrightable work licensed under this
244+License. Each licensee is addressed as "you". "Licensees" and
245+"recipients" may be individuals or organizations.
246+
247+ To "modify" a work means to copy from or adapt all or part of the work
248+in a fashion requiring copyright permission, other than the making of an
249+exact copy. The resulting work is called a "modified version" of the
250+earlier work or a work "based on" the earlier work.
251+
252+ A "covered work" means either the unmodified Program or a work based
253+on the Program.
254+
255+ To "propagate" a work means to do anything with it that, without
256+permission, would make you directly or secondarily liable for
257+infringement under applicable copyright law, except executing it on a
258+computer or modifying a private copy. Propagation includes copying,
259+distribution (with or without modification), making available to the
260+public, and in some countries other activities as well.
261+
262+ To "convey" a work means any kind of propagation that enables other
263+parties to make or receive copies. Mere interaction with a user through
264+a computer network, with no transfer of a copy, is not conveying.
265+
266+ An interactive user interface displays "Appropriate Legal Notices"
267+to the extent that it includes a convenient and prominently visible
268+feature that (1) displays an appropriate copyright notice, and (2)
269+tells the user that there is no warranty for the work (except to the
270+extent that warranties are provided), that licensees may convey the
271+work under this License, and how to view a copy of this License. If
272+the interface presents a list of user commands or options, such as a
273+menu, a prominent item in the list meets this criterion.
274+
275+ 1. Source Code.
276+
277+ The "source code" for a work means the preferred form of the work
278+for making modifications to it. "Object code" means any non-source
279+form of a work.
280+
281+ A "Standard Interface" means an interface that either is an official
282+standard defined by a recognized standards body, or, in the case of
283+interfaces specified for a particular programming language, one that
284+is widely used among developers working in that language.
285+
286+ The "System Libraries" of an executable work include anything, other
287+than the work as a whole, that (a) is included in the normal form of
288+packaging a Major Component, but which is not part of that Major
289+Component, and (b) serves only to enable use of the work with that
290+Major Component, or to implement a Standard Interface for which an
291+implementation is available to the public in source code form. A
292+"Major Component", in this context, means a major essential component
293+(kernel, window system, and so on) of the specific operating system
294+(if any) on which the executable work runs, or a compiler used to
295+produce the work, or an object code interpreter used to run it.
296+
297+ The "Corresponding Source" for a work in object code form means all
298+the source code needed to generate, install, and (for an executable
299+work) run the object code and to modify the work, including scripts to
300+control those activities. However, it does not include the work's
301+System Libraries, or general-purpose tools or generally available free
302+programs which are used unmodified in performing those activities but
303+which are not part of the work. For example, Corresponding Source
304+includes interface definition files associated with source files for
305+the work, and the source code for shared libraries and dynamically
306+linked subprograms that the work is specifically designed to require,
307+such as by intimate data communication or control flow between those
308+subprograms and other parts of the work.
309+
310+ The Corresponding Source need not include anything that users
311+can regenerate automatically from other parts of the Corresponding
312+Source.
313+
314+ The Corresponding Source for a work in source code form is that
315+same work.
316+
317+ 2. Basic Permissions.
318+
319+ All rights granted under this License are granted for the term of
320+copyright on the Program, and are irrevocable provided the stated
321+conditions are met. This License explicitly affirms your unlimited
322+permission to run the unmodified Program. The output from running a
323+covered work is covered by this License only if the output, given its
324+content, constitutes a covered work. This License acknowledges your
325+rights of fair use or other equivalent, as provided by copyright law.
326+
327+ You may make, run and propagate covered works that you do not
328+convey, without conditions so long as your license otherwise remains
329+in force. You may convey covered works to others for the sole purpose
330+of having them make modifications exclusively for you, or provide you
331+with facilities for running those works, provided that you comply with
332+the terms of this License in conveying all material for which you do
333+not control copyright. Those thus making or running the covered works
334+for you must do so exclusively on your behalf, under your direction
335+and control, on terms that prohibit them from making any copies of
336+your copyrighted material outside their relationship with you.
337+
338+ Conveying under any other circumstances is permitted solely under
339+the conditions stated below. Sublicensing is not allowed; section 10
340+makes it unnecessary.
341+
342+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
343+
344+ No covered work shall be deemed part of an effective technological
345+measure under any applicable law fulfilling obligations under article
346+11 of the WIPO copyright treaty adopted on 20 December 1996, or
347+similar laws prohibiting or restricting circumvention of such
348+measures.
349+
350+ When you convey a covered work, you waive any legal power to forbid
351+circumvention of technological measures to the extent such circumvention
352+is effected by exercising rights under this License with respect to
353+the covered work, and you disclaim any intention to limit operation or
354+modification of the work as a means of enforcing, against the work's
355+users, your or third parties' legal rights to forbid circumvention of
356+technological measures.
357+
358+ 4. Conveying Verbatim Copies.
359+
360+ You may convey verbatim copies of the Program's source code as you
361+receive it, in any medium, provided that you conspicuously and
362+appropriately publish on each copy an appropriate copyright notice;
363+keep intact all notices stating that this License and any
364+non-permissive terms added in accord with section 7 apply to the code;
365+keep intact all notices of the absence of any warranty; and give all
366+recipients a copy of this License along with the Program.
367+
368+ You may charge any price or no price for each copy that you convey,
369+and you may offer support or warranty protection for a fee.
370+
371+ 5. Conveying Modified Source Versions.
372+
373+ You may convey a work based on the Program, or the modifications to
374+produce it from the Program, in the form of source code under the
375+terms of section 4, provided that you also meet all of these conditions:
376+
377+ a) The work must carry prominent notices stating that you modified
378+ it, and giving a relevant date.
379+
380+ b) The work must carry prominent notices stating that it is
381+ released under this License and any conditions added under section
382+ 7. This requirement modifies the requirement in section 4 to
383+ "keep intact all notices".
384+
385+ c) You must license the entire work, as a whole, under this
386+ License to anyone who comes into possession of a copy. This
387+ License will therefore apply, along with any applicable section 7
388+ additional terms, to the whole of the work, and all its parts,
389+ regardless of how they are packaged. This License gives no
390+ permission to license the work in any other way, but it does not
391+ invalidate such permission if you have separately received it.
392+
393+ d) If the work has interactive user interfaces, each must display
394+ Appropriate Legal Notices; however, if the Program has interactive
395+ interfaces that do not display Appropriate Legal Notices, your
396+ work need not make them do so.
397+
398+ A compilation of a covered work with other separate and independent
399+works, which are not by their nature extensions of the covered work,
400+and which are not combined with it such as to form a larger program,
401+in or on a volume of a storage or distribution medium, is called an
402+"aggregate" if the compilation and its resulting copyright are not
403+used to limit the access or legal rights of the compilation's users
404+beyond what the individual works permit. Inclusion of a covered work
405+in an aggregate does not cause this License to apply to the other
406+parts of the aggregate.
407+
408+ 6. Conveying Non-Source Forms.
409+
410+ You may convey a covered work in object code form under the terms
411+of sections 4 and 5, provided that you also convey the
412+machine-readable Corresponding Source under the terms of this License,
413+in one of these ways:
414+
415+ a) Convey the object code in, or embodied in, a physical product
416+ (including a physical distribution medium), accompanied by the
417+ Corresponding Source fixed on a durable physical medium
418+ customarily used for software interchange.
419+
420+ b) Convey the object code in, or embodied in, a physical product
421+ (including a physical distribution medium), accompanied by a
422+ written offer, valid for at least three years and valid for as
423+ long as you offer spare parts or customer support for that product
424+ model, to give anyone who possesses the object code either (1) a
425+ copy of the Corresponding Source for all the software in the
426+ product that is covered by this License, on a durable physical
427+ medium customarily used for software interchange, for a price no
428+ more than your reasonable cost of physically performing this
429+ conveying of source, or (2) access to copy the
430+ Corresponding Source from a network server at no charge.
431+
432+ c) Convey individual copies of the object code with a copy of the
433+ written offer to provide the Corresponding Source. This
434+ alternative is allowed only occasionally and noncommercially, and
435+ only if you received the object code with such an offer, in accord
436+ with subsection 6b.
437+
438+ d) Convey the object code by offering access from a designated
439+ place (gratis or for a charge), and offer equivalent access to the
440+ Corresponding Source in the same way through the same place at no
441+ further charge. You need not require recipients to copy the
442+ Corresponding Source along with the object code. If the place to
443+ copy the object code is a network server, the Corresponding Source
444+ may be on a different server (operated by you or a third party)
445+ that supports equivalent copying facilities, provided you maintain
446+ clear directions next to the object code saying where to find the
447+ Corresponding Source. Regardless of what server hosts the
448+ Corresponding Source, you remain obligated to ensure that it is
449+ available for as long as needed to satisfy these requirements.
450+
451+ e) Convey the object code using peer-to-peer transmission, provided
452+ you inform other peers where the object code and Corresponding
453+ Source of the work are being offered to the general public at no
454+ charge under subsection 6d.
455+
456+ A separable portion of the object code, whose source code is excluded
457+from the Corresponding Source as a System Library, need not be
458+included in conveying the object code work.
459+
460+ A "User Product" is either (1) a "consumer product", which means any
461+tangible personal property which is normally used for personal, family,
462+or household purposes, or (2) anything designed or sold for incorporation
463+into a dwelling. In determining whether a product is a consumer product,
464+doubtful cases shall be resolved in favor of coverage. For a particular
465+product received by a particular user, "normally used" refers to a
466+typical or common use of that class of product, regardless of the status
467+of the particular user or of the way in which the particular user
468+actually uses, or expects or is expected to use, the product. A product
469+is a consumer product regardless of whether the product has substantial
470+commercial, industrial or non-consumer uses, unless such uses represent
471+the only significant mode of use of the product.
472+
473+ "Installation Information" for a User Product means any methods,
474+procedures, authorization keys, or other information required to install
475+and execute modified versions of a covered work in that User Product from
476+a modified version of its Corresponding Source. The information must
477+suffice to ensure that the continued functioning of the modified object
478+code is in no case prevented or interfered with solely because
479+modification has been made.
480+
481+ If you convey an object code work under this section in, or with, or
482+specifically for use in, a User Product, and the conveying occurs as
483+part of a transaction in which the right of possession and use of the
484+User Product is transferred to the recipient in perpetuity or for a
485+fixed term (regardless of how the transaction is characterized), the
486+Corresponding Source conveyed under this section must be accompanied
487+by the Installation Information. But this requirement does not apply
488+if neither you nor any third party retains the ability to install
489+modified object code on the User Product (for example, the work has
490+been installed in ROM).
491+
492+ The requirement to provide Installation Information does not include a
493+requirement to continue to provide support service, warranty, or updates
494+for a work that has been modified or installed by the recipient, or for
495+the User Product in which it has been modified or installed. Access to a
496+network may be denied when the modification itself materially and
497+adversely affects the operation of the network or violates the rules and
498+protocols for communication across the network.
499+
500+ Corresponding Source conveyed, and Installation Information provided,
501+in accord with this section must be in a format that is publicly
502+documented (and with an implementation available to the public in
503+source code form), and must require no special password or key for
504+unpacking, reading or copying.
505+
506+ 7. Additional Terms.
507+
508+ "Additional permissions" are terms that supplement the terms of this
509+License by making exceptions from one or more of its conditions.
510+Additional permissions that are applicable to the entire Program shall
511+be treated as though they were included in this License, to the extent
512+that they are valid under applicable law. If additional permissions
513+apply only to part of the Program, that part may be used separately
514+under those permissions, but the entire Program remains governed by
515+this License without regard to the additional permissions.
516+
517+ When you convey a copy of a covered work, you may at your option
518+remove any additional permissions from that copy, or from any part of
519+it. (Additional permissions may be written to require their own
520+removal in certain cases when you modify the work.) You may place
521+additional permissions on material, added by you to a covered work,
522+for which you have or can give appropriate copyright permission.
523+
524+ Notwithstanding any other provision of this License, for material you
525+add to a covered work, you may (if authorized by the copyright holders of
526+that material) supplement the terms of this License with terms:
527+
528+ a) Disclaiming warranty or limiting liability differently from the
529+ terms of sections 15 and 16 of this License; or
530+
531+ b) Requiring preservation of specified reasonable legal notices or
532+ author attributions in that material or in the Appropriate Legal
533+ Notices displayed by works containing it; or
534+
535+ c) Prohibiting misrepresentation of the origin of that material, or
536+ requiring that modified versions of such material be marked in
537+ reasonable ways as different from the original version; or
538+
539+ d) Limiting the use for publicity purposes of names of licensors or
540+ authors of the material; or
541+
542+ e) Declining to grant rights under trademark law for use of some
543+ trade names, trademarks, or service marks; or
544+
545+ f) Requiring indemnification of licensors and authors of that
546+ material by anyone who conveys the material (or modified versions of
547+ it) with contractual assumptions of liability to the recipient, for
548+ any liability that these contractual assumptions directly impose on
549+ those licensors and authors.
550+
551+ All other non-permissive additional terms are considered "further
552+restrictions" within the meaning of section 10. If the Program as you
553+received it, or any part of it, contains a notice stating that it is
554+governed by this License along with a term that is a further
555+restriction, you may remove that term. If a license document contains
556+a further restriction but permits relicensing or conveying under this
557+License, you may add to a covered work material governed by the terms
558+of that license document, provided that the further restriction does
559+not survive such relicensing or conveying.
560+
561+ If you add terms to a covered work in accord with this section, you
562+must place, in the relevant source files, a statement of the
563+additional terms that apply to those files, or a notice indicating
564+where to find the applicable terms.
565+
566+ Additional terms, permissive or non-permissive, may be stated in the
567+form of a separately written license, or stated as exceptions;
568+the above requirements apply either way.
569+
570+ 8. Termination.
571+
572+ You may not propagate or modify a covered work except as expressly
573+provided under this License. Any attempt otherwise to propagate or
574+modify it is void, and will automatically terminate your rights under
575+this License (including any patent licenses granted under the third
576+paragraph of section 11).
577+
578+ However, if you cease all violation of this License, then your
579+license from a particular copyright holder is reinstated (a)
580+provisionally, unless and until the copyright holder explicitly and
581+finally terminates your license, and (b) permanently, if the copyright
582+holder fails to notify you of the violation by some reasonable means
583+prior to 60 days after the cessation.
584+
585+ Moreover, your license from a particular copyright holder is
586+reinstated permanently if the copyright holder notifies you of the
587+violation by some reasonable means, this is the first time you have
588+received notice of violation of this License (for any work) from that
589+copyright holder, and you cure the violation prior to 30 days after
590+your receipt of the notice.
591+
592+ Termination of your rights under this section does not terminate the
593+licenses of parties who have received copies or rights from you under
594+this License. If your rights have been terminated and not permanently
595+reinstated, you do not qualify to receive new licenses for the same
596+material under section 10.
597+
598+ 9. Acceptance Not Required for Having Copies.
599+
600+ You are not required to accept this License in order to receive or
601+run a copy of the Program. Ancillary propagation of a covered work
602+occurring solely as a consequence of using peer-to-peer transmission
603+to receive a copy likewise does not require acceptance. However,
604+nothing other than this License grants you permission to propagate or
605+modify any covered work. These actions infringe copyright if you do
606+not accept this License. Therefore, by modifying or propagating a
607+covered work, you indicate your acceptance of this License to do so.
608+
609+ 10. Automatic Licensing of Downstream Recipients.
610+
611+ Each time you convey a covered work, the recipient automatically
612+receives a license from the original licensors, to run, modify and
613+propagate that work, subject to this License. You are not responsible
614+for enforcing compliance by third parties with this License.
615+
616+ An "entity transaction" is a transaction transferring control of an
617+organization, or substantially all assets of one, or subdividing an
618+organization, or merging organizations. If propagation of a covered
619+work results from an entity transaction, each party to that
620+transaction who receives a copy of the work also receives whatever
621+licenses to the work the party's predecessor in interest had or could
622+give under the previous paragraph, plus a right to possession of the
623+Corresponding Source of the work from the predecessor in interest, if
624+the predecessor has it or can get it with reasonable efforts.
625+
626+ You may not impose any further restrictions on the exercise of the
627+rights granted or affirmed under this License. For example, you may
628+not impose a license fee, royalty, or other charge for exercise of
629+rights granted under this License, and you may not initiate litigation
630+(including a cross-claim or counterclaim in a lawsuit) alleging that
631+any patent claim is infringed by making, using, selling, offering for
632+sale, or importing the Program or any portion of it.
633+
634+ 11. Patents.
635+
636+ A "contributor" is a copyright holder who authorizes use under this
637+License of the Program or a work on which the Program is based. The
638+work thus licensed is called the contributor's "contributor version".
639+
640+ A contributor's "essential patent claims" are all patent claims
641+owned or controlled by the contributor, whether already acquired or
642+hereafter acquired, that would be infringed by some manner, permitted
643+by this License, of making, using, or selling its contributor version,
644+but do not include claims that would be infringed only as a
645+consequence of further modification of the contributor version. For
646+purposes of this definition, "control" includes the right to grant
647+patent sublicenses in a manner consistent with the requirements of
648+this License.
649+
650+ Each contributor grants you a non-exclusive, worldwide, royalty-free
651+patent license under the contributor's essential patent claims, to
652+make, use, sell, offer for sale, import and otherwise run, modify and
653+propagate the contents of its contributor version.
654+
655+ In the following three paragraphs, a "patent license" is any express
656+agreement or commitment, however denominated, not to enforce a patent
657+(such as an express permission to practice a patent or covenant not to
658+sue for patent infringement). To "grant" such a patent license to a
659+party means to make such an agreement or commitment not to enforce a
660+patent against the party.
661+
662+ If you convey a covered work, knowingly relying on a patent license,
663+and the Corresponding Source of the work is not available for anyone
664+to copy, free of charge and under the terms of this License, through a
665+publicly available network server or other readily accessible means,
666+then you must either (1) cause the Corresponding Source to be so
667+available, or (2) arrange to deprive yourself of the benefit of the
668+patent license for this particular work, or (3) arrange, in a manner
669+consistent with the requirements of this License, to extend the patent
670+license to downstream recipients. "Knowingly relying" means you have
671+actual knowledge that, but for the patent license, your conveying the
672+covered work in a country, or your recipient's use of the covered work
673+in a country, would infringe one or more identifiable patents in that
674+country that you have reason to believe are valid.
675+
676+ If, pursuant to or in connection with a single transaction or
677+arrangement, you convey, or propagate by procuring conveyance of, a
678+covered work, and grant a patent license to some of the parties
679+receiving the covered work authorizing them to use, propagate, modify
680+or convey a specific copy of the covered work, then the patent license
681+you grant is automatically extended to all recipients of the covered
682+work and works based on it.
683+
684+ A patent license is "discriminatory" if it does not include within
685+the scope of its coverage, prohibits the exercise of, or is
686+conditioned on the non-exercise of one or more of the rights that are
687+specifically granted under this License. You may not convey a covered
688+work if you are a party to an arrangement with a third party that is
689+in the business of distributing software, under which you make payment
690+to the third party based on the extent of your activity of conveying
691+the work, and under which the third party grants, to any of the
692+parties who would receive the covered work from you, a discriminatory
693+patent license (a) in connection with copies of the covered work
694+conveyed by you (or copies made from those copies), or (b) primarily
695+for and in connection with specific products or compilations that
696+contain the covered work, unless you entered into that arrangement,
697+or that patent license was granted, prior to 28 March 2007.
698+
699+ Nothing in this License shall be construed as excluding or limiting
700+any implied license or other defenses to infringement that may
701+otherwise be available to you under applicable patent law.
702+
703+ 12. No Surrender of Others' Freedom.
704+
705+ If conditions are imposed on you (whether by court order, agreement or
706+otherwise) that contradict the conditions of this License, they do not
707+excuse you from the conditions of this License. If you cannot convey a
708+covered work so as to satisfy simultaneously your obligations under this
709+License and any other pertinent obligations, then as a consequence you may
710+not convey it at all. For example, if you agree to terms that obligate you
711+to collect a royalty for further conveying from those to whom you convey
712+the Program, the only way you could satisfy both those terms and this
713+License would be to refrain entirely from conveying the Program.
714+
715+ 13. Use with the GNU Affero General Public License.
716+
717+ Notwithstanding any other provision of this License, you have
718+permission to link or combine any covered work with a work licensed
719+under version 3 of the GNU Affero General Public License into a single
720+combined work, and to convey the resulting work. The terms of this
721+License will continue to apply to the part which is the covered work,
722+but the special requirements of the GNU Affero General Public License,
723+section 13, concerning interaction through a network will apply to the
724+combination as such.
725+
726+ 14. Revised Versions of this License.
727+
728+ The Free Software Foundation may publish revised and/or new versions of
729+the GNU General Public License from time to time. Such new versions will
730+be similar in spirit to the present version, but may differ in detail to
731+address new problems or concerns.
732+
733+ Each version is given a distinguishing version number. If the
734+Program specifies that a certain numbered version of the GNU General
735+Public License "or any later version" applies to it, you have the
736+option of following the terms and conditions either of that numbered
737+version or of any later version published by the Free Software
738+Foundation. If the Program does not specify a version number of the
739+GNU General Public License, you may choose any version ever published
740+by the Free Software Foundation.
741+
742+ If the Program specifies that a proxy can decide which future
743+versions of the GNU General Public License can be used, that proxy's
744+public statement of acceptance of a version permanently authorizes you
745+to choose that version for the Program.
746+
747+ Later license versions may give you additional or different
748+permissions. However, no additional obligations are imposed on any
749+author or copyright holder as a result of your choosing to follow a
750+later version.
751+
752+ 15. Disclaimer of Warranty.
753+
754+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
755+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
756+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
757+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
758+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
759+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
760+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
761+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
762+
763+ 16. Limitation of Liability.
764+
765+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
766+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
767+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
768+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
769+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
770+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
771+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
772+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
773+SUCH DAMAGES.
774+
775+ 17. Interpretation of Sections 15 and 16.
776+
777+ If the disclaimer of warranty and limitation of liability provided
778+above cannot be given local legal effect according to their terms,
779+reviewing courts shall apply local law that most closely approximates
780+an absolute waiver of all civil liability in connection with the
781+Program, unless a warranty or assumption of liability accompanies a
782+copy of the Program in return for a fee.
783+
784+ END OF TERMS AND CONDITIONS
785+
786+ How to Apply These Terms to Your New Programs
787+
788+ If you develop a new program, and you want it to be of the greatest
789+possible use to the public, the best way to achieve this is to make it
790+free software which everyone can redistribute and change under these terms.
791+
792+ To do so, attach the following notices to the program. It is safest
793+to attach them to the start of each source file to most effectively
794+state the exclusion of warranty; and each file should have at least
795+the "copyright" line and a pointer to where the full notice is found.
796+
797+ <one line to give the program's name and a brief idea of what it does.>
798+ Copyright (C) <year> <name of author>
799+
800+ This program is free software: you can redistribute it and/or modify
801+ it under the terms of the GNU General Public License as published by
802+ the Free Software Foundation, either version 3 of the License, or
803+ (at your option) any later version.
804+
805+ This program is distributed in the hope that it will be useful,
806+ but WITHOUT ANY WARRANTY; without even the implied warranty of
807+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
808+ GNU General Public License for more details.
809+
810+ You should have received a copy of the GNU General Public License
811+ along with this program. If not, see <http://www.gnu.org/licenses/>.
812+
813+Also add information on how to contact you by electronic and paper mail.
814+
815+ If the program does terminal interaction, make it output a short
816+notice like this when it starts in an interactive mode:
817+
818+ <program> Copyright (C) <year> <name of author>
819+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
820+ This is free software, and you are welcome to redistribute it
821+ under certain conditions; type `show c' for details.
822+
823+The hypothetical commands `show w' and `show c' should show the appropriate
824+parts of the General Public License. Of course, your program's commands
825+might be different; for a GUI interface, you would use an "about box".
826+
827+ You should also get your employer (if you work as a programmer) or school,
828+if any, to sign a "copyright disclaimer" for the program, if necessary.
829+For more information on this, and how to apply and follow the GNU GPL, see
830+<http://www.gnu.org/licenses/>.
831+
832+ The GNU General Public License does not permit incorporating your program
833+into proprietary programs. If your program is a subroutine library, you
834+may consider it more useful to permit linking proprietary applications with
835+the library. If this is what you want to do, use the GNU Lesser General
836+Public License instead of this License. But first, please read
837+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
838
839=== added file 'COPYING.LIB'
840--- COPYING.LIB 1970-01-01 00:00:00 +0000
841+++ COPYING.LIB 2012-01-19 20:21:35 +0000
842@@ -0,0 +1,165 @@
843+ GNU LESSER GENERAL PUBLIC LICENSE
844+ Version 3, 29 June 2007
845+
846+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
847+ Everyone is permitted to copy and distribute verbatim copies
848+ of this license document, but changing it is not allowed.
849+
850+
851+ This version of the GNU Lesser General Public License incorporates
852+the terms and conditions of version 3 of the GNU General Public
853+License, supplemented by the additional permissions listed below.
854+
855+ 0. Additional Definitions.
856+
857+ As used herein, "this License" refers to version 3 of the GNU Lesser
858+General Public License, and the "GNU GPL" refers to version 3 of the GNU
859+General Public License.
860+
861+ "The Library" refers to a covered work governed by this License,
862+other than an Application or a Combined Work as defined below.
863+
864+ An "Application" is any work that makes use of an interface provided
865+by the Library, but which is not otherwise based on the Library.
866+Defining a subclass of a class defined by the Library is deemed a mode
867+of using an interface provided by the Library.
868+
869+ A "Combined Work" is a work produced by combining or linking an
870+Application with the Library. The particular version of the Library
871+with which the Combined Work was made is also called the "Linked
872+Version".
873+
874+ The "Minimal Corresponding Source" for a Combined Work means the
875+Corresponding Source for the Combined Work, excluding any source code
876+for portions of the Combined Work that, considered in isolation, are
877+based on the Application, and not on the Linked Version.
878+
879+ The "Corresponding Application Code" for a Combined Work means the
880+object code and/or source code for the Application, including any data
881+and utility programs needed for reproducing the Combined Work from the
882+Application, but excluding the System Libraries of the Combined Work.
883+
884+ 1. Exception to Section 3 of the GNU GPL.
885+
886+ You may convey a covered work under sections 3 and 4 of this License
887+without being bound by section 3 of the GNU GPL.
888+
889+ 2. Conveying Modified Versions.
890+
891+ If you modify a copy of the Library, and, in your modifications, a
892+facility refers to a function or data to be supplied by an Application
893+that uses the facility (other than as an argument passed when the
894+facility is invoked), then you may convey a copy of the modified
895+version:
896+
897+ a) under this License, provided that you make a good faith effort to
898+ ensure that, in the event an Application does not supply the
899+ function or data, the facility still operates, and performs
900+ whatever part of its purpose remains meaningful, or
901+
902+ b) under the GNU GPL, with none of the additional permissions of
903+ this License applicable to that copy.
904+
905+ 3. Object Code Incorporating Material from Library Header Files.
906+
907+ The object code form of an Application may incorporate material from
908+a header file that is part of the Library. You may convey such object
909+code under terms of your choice, provided that, if the incorporated
910+material is not limited to numerical parameters, data structure
911+layouts and accessors, or small macros, inline functions and templates
912+(ten or fewer lines in length), you do both of the following:
913+
914+ a) Give prominent notice with each copy of the object code that the
915+ Library is used in it and that the Library and its use are
916+ covered by this License.
917+
918+ b) Accompany the object code with a copy of the GNU GPL and this license
919+ document.
920+
921+ 4. Combined Works.
922+
923+ You may convey a Combined Work under terms of your choice that,
924+taken together, effectively do not restrict modification of the
925+portions of the Library contained in the Combined Work and reverse
926+engineering for debugging such modifications, if you also do each of
927+the following:
928+
929+ a) Give prominent notice with each copy of the Combined Work that
930+ the Library is used in it and that the Library and its use are
931+ covered by this License.
932+
933+ b) Accompany the Combined Work with a copy of the GNU GPL and this license
934+ document.
935+
936+ c) For a Combined Work that displays copyright notices during
937+ execution, include the copyright notice for the Library among
938+ these notices, as well as a reference directing the user to the
939+ copies of the GNU GPL and this license document.
940+
941+ d) Do one of the following:
942+
943+ 0) Convey the Minimal Corresponding Source under the terms of this
944+ License, and the Corresponding Application Code in a form
945+ suitable for, and under terms that permit, the user to
946+ recombine or relink the Application with a modified version of
947+ the Linked Version to produce a modified Combined Work, in the
948+ manner specified by section 6 of the GNU GPL for conveying
949+ Corresponding Source.
950+
951+ 1) Use a suitable shared library mechanism for linking with the
952+ Library. A suitable mechanism is one that (a) uses at run time
953+ a copy of the Library already present on the user's computer
954+ system, and (b) will operate properly with a modified version
955+ of the Library that is interface-compatible with the Linked
956+ Version.
957+
958+ e) Provide Installation Information, but only if you would otherwise
959+ be required to provide such information under section 6 of the
960+ GNU GPL, and only to the extent that such information is
961+ necessary to install and execute a modified version of the
962+ Combined Work produced by recombining or relinking the
963+ Application with a modified version of the Linked Version. (If
964+ you use option 4d0, the Installation Information must accompany
965+ the Minimal Corresponding Source and Corresponding Application
966+ Code. If you use option 4d1, you must provide the Installation
967+ Information in the manner specified by section 6 of the GNU GPL
968+ for conveying Corresponding Source.)
969+
970+ 5. Combined Libraries.
971+
972+ You may place library facilities that are a work based on the
973+Library side by side in a single library together with other library
974+facilities that are not Applications and are not covered by this
975+License, and convey such a combined library under terms of your
976+choice, if you do both of the following:
977+
978+ a) Accompany the combined library with a copy of the same work based
979+ on the Library, uncombined with any other library facilities,
980+ conveyed under the terms of this License.
981+
982+ b) Give prominent notice with the combined library that part of it
983+ is a work based on the Library, and explaining where to find the
984+ accompanying uncombined form of the same work.
985+
986+ 6. Revised Versions of the GNU Lesser General Public License.
987+
988+ The Free Software Foundation may publish revised and/or new versions
989+of the GNU Lesser General Public License from time to time. Such new
990+versions will be similar in spirit to the present version, but may
991+differ in detail to address new problems or concerns.
992+
993+ Each version is given a distinguishing version number. If the
994+Library as you received it specifies that a certain numbered version
995+of the GNU Lesser General Public License "or any later version"
996+applies to it, you have the option of following the terms and
997+conditions either of that published version or of any later version
998+published by the Free Software Foundation. If the Library as you
999+received it does not specify a version number of the GNU Lesser
1000+General Public License, you may choose any version of the GNU Lesser
1001+General Public License ever published by the Free Software Foundation.
1002+
1003+ If the Library as you received it specifies that a proxy can decide
1004+whether future versions of the GNU Lesser General Public License shall
1005+apply, that proxy's public statement of acceptance of any version is
1006+permanent authorization for you to choose that version for the
1007+Library.
1008
1009=== modified file 'MANIFEST.in'
1010--- MANIFEST.in 2010-11-02 15:50:32 +0000
1011+++ MANIFEST.in 2012-01-19 20:21:35 +0000
1012@@ -1,5 +1,4 @@
1013-include COPYING MANIFEST.in README
1014-include run-tests rb.py rhythmdb.py
1015-recursive-include gst *.py
1016+include COPYING COPYING.LIB MANIFEST.in README
1017+include run-tests
1018 recursive-include po *.po POTFILES.in
1019-recursive-include umusicstore *.py *.glade *.mp3 *.rb-plugin.in
1020+recursive-include ubuntuone *.py *.glade *.mp3 *.rb-plugin.in
1021
1022=== modified file 'po/POTFILES.in'
1023--- po/POTFILES.in 2010-09-13 03:43:27 +0000
1024+++ po/POTFILES.in 2012-01-19 20:21:35 +0000
1025@@ -1,5 +1,4 @@
1026-umusicstore/__init__.py
1027-umusicstore/MusicStoreWidget.py
1028-umusicstore/U1MSLinks.py
1029-[type: gettext/ini]umusicstore/umusicstore.rb-plugin.in
1030+ubuntuone/ubuntuone.py
1031+ubuntuone/MusicStoreWidget.py
1032+[type: gettext/ini]ubuntuone/ubuntuone.plugin.in
1033
1034
1035=== removed file 'rb.py'
1036--- rb.py 2011-04-05 21:31:48 +0000
1037+++ rb.py 1970-01-01 00:00:00 +0000
1038@@ -1,39 +0,0 @@
1039-"""Fake rb.py for use in testing."""
1040-
1041-SOURCE_GROUP_CATEGORY_FIXED = 0
1042-
1043-
1044-class Plugin(object):
1045- """Fake Plugin class for testing."""
1046-
1047- def __init__(self, *args, **kwargs):
1048- super(Plugin, self).__init__()
1049-
1050- def find_file(self, *args, **kwargs):
1051- """Fake find_file method."""
1052- pass
1053-
1054-
1055-class Source(object):
1056- """Fake Source class for testing."""
1057-
1058- add = __fake_it
1059- remove = __fake_it
1060- show_all = __fake_it
1061- do_impl_activate = __fake_it
1062-
1063- def __fake_it(self, *args, **kwargs):
1064- """Fake method."""
1065-
1066-
1067-def rb_source_group_get_by_name(*args, **kwargs):
1068- """Fake method."""
1069- return
1070-
1071-def rb_display_page_group_get_by_id(*args, **kwargs):
1072- """Fake method."""
1073- return
1074-
1075-def rb_source_group_register(*args, **kwargs):
1076- """Fake method."""
1077- return
1078
1079=== removed file 'rhythmdb.py'
1080--- rhythmdb.py 2010-11-02 15:50:32 +0000
1081+++ rhythmdb.py 1970-01-01 00:00:00 +0000
1082@@ -1,12 +0,0 @@
1083-"""Fake rhythmdb.py for use in testing."""
1084-
1085-PROP_ARTIST = 0
1086-PROP_TITLE = 1
1087-PROP_ALBUM = 2
1088-
1089-
1090-class EntryType(object):
1091- """Fake EntryType object."""
1092-
1093- def __init__(self, *args, **kwargs):
1094- super(EntryType, self).__init__()
1095
1096=== modified file 'run-tests'
1097--- run-tests 2010-11-02 15:50:32 +0000
1098+++ run-tests 2012-01-19 20:21:35 +0000
1099@@ -14,7 +14,7 @@
1100 #
1101 # You should have received a copy of the GNU General Public License along
1102 # with this program. If not, see <http://www.gnu.org/licenses/>.
1103-export PYTHONPATH=umusicstore
1104+export PYTHONPATH=ubuntuone
1105 u1lint .
1106 if [ -x `which pep8` ]; then
1107 pep8 --repeat .
1108
1109=== modified file 'setup.cfg'
1110--- setup.cfg 2010-04-14 21:37:08 +0000
1111+++ setup.cfg 2012-01-19 20:21:35 +0000
1112@@ -1,2 +1,2 @@
1113 [build_i18n]
1114-desktop_files=[("lib/rhythmbox/plugins/umusicstore", ("umusicstore/umusicstore.rb-plugin.in",))]
1115+desktop_files=[("lib/rhythmbox/plugins/ubuntuone", ("ubuntuone/ubuntuone.plugin.in",))]
1116
1117=== modified file 'setup.py'
1118--- setup.py 2011-12-01 19:20:35 +0000
1119+++ setup.py 2012-01-19 20:21:35 +0000
1120@@ -3,20 +3,19 @@
1121
1122 import DistUtilsExtra.auto
1123
1124+
1125 DistUtilsExtra.auto.setup(
1126- name='rhythmbox-ubuntuone-music-store',
1127+ name='rhythmbox-ubuntuone',
1128 version='2.99',
1129 license='LGPL v3',
1130- author='Stuart Langridge',
1131- author_email='stuart.langridge@canonical.com',
1132- description='Ubuntu One Music Store Rhythmbox plug-in',
1133- long_description=('A plug-in to access the Ubuntu One Music Store '
1134- 'in Rhythmbox.'),
1135- url='https://launchpad.net/rhythmbox-ubuntuone-music-store',
1136- data_files=[('/usr/lib/rhythmbox/plugins/umusicstore',
1137- ['umusicstore/__init__.py',
1138- 'umusicstore/MusicStoreWidget.py',
1139- 'umusicstore/U1MSLinks.py',
1140- 'umusicstore/u1msurl.glade'])],
1141+ author='Ubuntu One Developers',
1142+ author_email='ubuntuone-users@lists.launchpad.net',
1143+ description='Ubuntu One Rhythmbox plug-in',
1144+ long_description=('A plug-in to integrate Ubuntu One in Rhythmbox.'),
1145+ url='https://launchpad.net/rhythmbox-ubuntuone',
1146+ data_files=[('lib/rhythmbox/plugins/ubuntuone',
1147+ ['ubuntuone/ubuntuone.py',
1148+ 'ubuntuone/MusicStoreWidget.py',
1149+ ])],
1150 )
1151
1152
1153=== renamed directory 'umusicstore' => 'ubuntuone'
1154=== modified file 'ubuntuone/MusicStoreWidget.py'
1155--- umusicstore/MusicStoreWidget.py 2011-04-05 21:31:48 +0000
1156+++ ubuntuone/MusicStoreWidget.py 2012-01-19 20:21:35 +0000
1157@@ -1,5 +1,4 @@
1158-"""The Ubuntu One Music Store Rhythmbox plugin."""
1159-# Copyright (C) 2009 Canonical, Ltd.
1160+# Copyright (C) 2009-2012 Canonical, Ltd.
1161 #
1162 # This library is free software; you can redistribute it and/or modify
1163 # it under the terms of the GNU Lesser General Public License
1164@@ -13,35 +12,25 @@
1165 # You should have received a copy of the GNU Lesser General Public
1166 # License along with this library. If not, see
1167 # <http://www.gnu.org/licenses/>.
1168-#
1169-# Authored by Stuart Langridge <stuart.langridge@canonical.com>
1170-
1171-# pylint: disable=W0201
1172-
1173-# Import these here as gtk/gio import ordering seems to matter
1174-import gobject
1175-import gtk
1176-import gio
1177-
1178-import gconf
1179+"""The Ubuntu One Rhythmbox plugin."""
1180+
1181 import gettext
1182 import os
1183-# pylint: disable=F0401
1184-import rb as RB
1185-import rhythmdb
1186-# pylint: enable=F0401
1187 import stat
1188-import urllib
1189 import urlparse
1190-import xdg.BaseDirectory
1191-
1192+
1193+# pylint: disable=E0611
1194+from gi.repository import Gio, GObject, Gtk, RB
1195+# pylint: enable=E0611
1196+
1197+from dirspec import basedir
1198 from gettext import lgettext as _
1199-from ubuntuone.gtkwidgets import MusicStore as U1MusicStore
1200+#from ubuntuone.gtkwidgets import MusicStore as U1MusicStore
1201
1202 gettext.bindtextdomain("rhythmbox-ubuntuone-music-store", "/usr/share/locale")
1203 gettext.textdomain("rhythmbox-ubuntuone-music-store")
1204
1205-MUSIC_STORE_WIDGET = U1MusicStore() # keep this around for later
1206+MUSIC_STORE_WIDGET = Gtk.EventBox() # keep this around for later
1207 U1LIBRARYPATH = MUSIC_STORE_WIDGET.get_library_location()
1208 RB_LIBRARY_LOCATIONS = "/apps/rhythmbox/library_locations"
1209 PARTNER_LIST = "canonical-partner-maverick.list"
1210@@ -49,11 +38,11 @@
1211 PLUGIN_PACKAGENAME = "gstreamer0.10-fluendo-plugins-mp3-partner"
1212
1213
1214-class U1EntryType(rhythmdb.EntryType):
1215+class U1EntryType(RB.RhythmDBEntryType):
1216 """Entry type for the Ubuntu One Music Store source."""
1217
1218 def __init__(self):
1219- rhythmdb.EntryType.__init__(self, name='ubuntuone')
1220+ RB.RhythmDBEntryType.__init__(self, name='ubuntuone')
1221
1222 def do_can_sync_metadata(self, entry):
1223 """Not a real source, so we can't sync metadata."""
1224@@ -68,6 +57,10 @@
1225 """The Ubuntu One Music Store."""
1226 def __init__(self, plugin):
1227 self.plugin = plugin
1228+ self.db = None
1229+ self.shell = None
1230+ self.source = None
1231+ self.u1_library_symlink = None
1232 self.entry_type = U1EntryType()
1233
1234 def activate(self, shell):
1235@@ -75,12 +68,12 @@
1236 self.db = shell.get_property("db")
1237 group = RB.rb_display_page_group_get_by_id("stores")
1238
1239- icon = gtk.IconTheme().load_icon(
1240- "ubuntuone", gtk.icon_size_lookup(gtk.ICON_SIZE_MENU)[0], 0)
1241+ icon = Gtk.IconTheme.get_default().load_icon(
1242+ "ubuntuone", Gtk.IconSize.lookup(Gtk.IconSize.MENU)[0], 0)
1243
1244 self.db.register_entry_type(self.entry_type)
1245
1246- self.source = gobject.new(U1Source,
1247+ self.source = GObject.new(U1Source,
1248 shell=shell,
1249 entry_type=self.entry_type,
1250 pixbuf=icon,
1251@@ -101,22 +94,6 @@
1252 """Plugin shutdown."""
1253 # remove source
1254 self.source.delete_thyself()
1255- # remove the library, if it's empty
1256- try:
1257- filecount = len(os.listdir(self.u1_library_symlink))
1258- except OSError:
1259- # symlink is dangling
1260- # so they never downloaded anything
1261- filecount = 0
1262- if filecount == 0:
1263- client = gconf.client_get_default()
1264- libraries = client.get_list(RB_LIBRARY_LOCATIONS,
1265- gconf.VALUE_STRING)
1266- if self.u1_library_path_url in libraries:
1267- client.notify_remove(self.library_adder)
1268- libraries.remove(self.u1_library_path_url)
1269- client.set_list(RB_LIBRARY_LOCATIONS,
1270- gconf.VALUE_STRING, libraries)
1271 # delete held references
1272 del self.db
1273 del self.source
1274@@ -145,7 +122,7 @@
1275 library_path = os.path.join(self.u1_library_symlink, subpath)
1276 # convert path to URI. Don't use urllib for this; Python and
1277 # glib escape URLs differently. gio does it the glib way.
1278- library_uri = gio.File(library_path).get_uri()
1279+ library_uri = Gio.File(library_path).get_uri()
1280 return library_uri
1281
1282 def download_finished(self, source, path):
1283@@ -165,8 +142,10 @@
1284 libsrc = self.shell.props.library_source
1285 artist_view, album_view = libsrc.get_property_views()[0:2]
1286 song_view = libsrc.get_entry_view()
1287- artist = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ARTIST)
1288- album = self.shell.props.db.entry_get(entry, rhythmdb.PROP_ALBUM)
1289+ artist = self.shell.props.db.entry_get(entry,
1290+ RB.RhythmDBPropType.ARTIST)
1291+ album = self.shell.props.db.entry_get(entry,
1292+ RB.RhythmDBPropType.ALBUM)
1293 self.shell.props.display_page_tree.select(libsrc)
1294 artist_view.set_selection([artist])
1295 album_view.set_selection([album])
1296@@ -181,7 +160,7 @@
1297 entry = self.shell.props.db.entry_lookup_by_location(url)
1298 if entry is None:
1299 entry = self.shell.props.db.entry_new(self.entry_type, url)
1300- self.shell.props.db.set(entry, rhythmdb.PROP_TITLE, title)
1301+ self.shell.props.db.set(entry, RB.RhythmDBPropType.TITLE, title)
1302 player = self.shell.get_player()
1303 player.stop()
1304 player.play_entry(entry, self.source)
1305@@ -189,7 +168,7 @@
1306
1307 def add_u1_library(self):
1308 """Add the U1 library if not listed in RB and re-add if changed."""
1309- u1_library_path_folder = xdg.BaseDirectory.save_data_path("ubuntuone")
1310+ u1_library_path_folder = basedir.save_data_path("ubuntuone")
1311 # Ensure that we can write to the folder, because syncdaemon creates it
1312 # with no write permissions
1313 os.chmod(u1_library_path_folder,
1314@@ -212,90 +191,35 @@
1315 "you know what you're doing. If this is a problem, then "
1316 "delete or rename %s.") % (u1_library_path, U1LIBRARYPATH,
1317 u1_library_path)
1318- self.u1_library_path_url = "file://%s" % urllib.quote(u1_library_path)
1319 self.u1_library_symlink = u1_library_path
1320- client = gconf.client_get_default()
1321- self._add_u1_library_if_not_present(client)
1322- self._remove_old_u1_library_if_present(client)
1323- # Watch for changes to the gconf key and re-add the library
1324- self.library_adder = client.notify_add(
1325- RB_LIBRARY_LOCATIONS,
1326- self._add_u1_library_if_not_present)
1327-
1328- def _add_u1_library_if_not_present(self, client, *args, **kwargs):
1329- """Check for the U1 library and add to libraries list."""
1330- libraries = client.get_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING)
1331- if self.u1_library_path_url not in libraries:
1332- libraries.append(self.u1_library_path_url)
1333- client.set_list(RB_LIBRARY_LOCATIONS,
1334- gconf.VALUE_STRING, libraries)
1335-
1336- def _remove_old_u1_library_if_present(self, client, *args, **kwargs):
1337- """Check for the old U1 library and remove it from libraries list."""
1338- libraries = client.get_list(RB_LIBRARY_LOCATIONS, gconf.VALUE_STRING)
1339- removed = False
1340- # originally, this was the library path. Someone might have this.
1341- old_path = "file://%s" % os.path.expanduser("~/.ubuntuone/musicstore")
1342- if old_path in libraries:
1343- libraries.remove(old_path)
1344- removed = True
1345- # Then, this was the library path, which we put into gconf unescaped
1346- actual_udf_path_unescaped = "file://%s" % U1LIBRARYPATH
1347- if actual_udf_path_unescaped in libraries:
1348- libraries.remove(actual_udf_path_unescaped)
1349- removed = True
1350- # In theory, no-one should have the escaped path, but let's check
1351- actual_udf_path_escaped = "file://%s" % U1LIBRARYPATH
1352- if actual_udf_path_escaped in libraries:
1353- libraries.remove(actual_udf_path_escaped)
1354- removed = True
1355- # Also, remove any library which is in .local/share and *isn't*
1356- # the current library. This caters for people who got the library
1357- # created under one name (say, English) and then had it created
1358- # under another (say, after a translation to Dutch)
1359- u1_library_path_folder = xdg.BaseDirectory.save_data_path("ubuntuone")
1360- u1_library_path_folder_url = "file://%s" % urllib.quote(
1361- u1_library_path_folder)
1362- symlink_url = "file://" + urllib.quote(self.u1_library_symlink)
1363- for lib in libraries:
1364- if lib.startswith(u1_library_path_folder_url) and \
1365- lib != symlink_url:
1366- libraries.remove(lib)
1367- # and delete the symlink itself
1368- symlink_to_remove = urllib.unquote(lib[7:])
1369- os.unlink(symlink_to_remove)
1370- removed = True
1371- if removed:
1372- client.set_list(RB_LIBRARY_LOCATIONS,
1373- gconf.VALUE_STRING, libraries)
1374-
1375-
1376-class U1Source(RB.Source, gobject.GObject):
1377+
1378+
1379+class U1Source(RB.Source):
1380 """A Rhythmbox source widget for the U1 Music Store."""
1381 # gproperties required so that rb.Source is instantiable
1382 __gproperties__ = {
1383 'plugin': (RB.Plugin, 'plugin', 'plugin',
1384- gobject.PARAM_WRITABLE | gobject.PARAM_CONSTRUCT_ONLY),
1385+ GObject.PARAM_WRITABLE | GObject.PARAM_CONSTRUCT_ONLY),
1386 }
1387 # we have the preview-mp3 signal; we receive it from the widget, and
1388 # re-emit it so that the plugin gets it, because the plugin actually
1389 # plays the mp3
1390 __gsignals__ = {
1391- "preview-mp3": (gobject.SIGNAL_RUN_FIRST,
1392- gobject.TYPE_NONE, (str, str)),
1393- "play-library": (gobject.SIGNAL_RUN_FIRST,
1394- gobject.TYPE_NONE, (str,)),
1395- "download-finished": (gobject.SIGNAL_RUN_FIRST,
1396- gobject.TYPE_NONE, (str,)),
1397- "url-loaded": (gobject.SIGNAL_RUN_FIRST,
1398- gobject.TYPE_NONE, (str,)),
1399+ "preview-mp3": (GObject.SIGNAL_RUN_FIRST,
1400+ GObject.TYPE_NONE, (str, str)),
1401+ "play-library": (GObject.SIGNAL_RUN_FIRST,
1402+ GObject.TYPE_NONE, (str,)),
1403+ "download-finished": (GObject.SIGNAL_RUN_FIRST,
1404+ GObject.TYPE_NONE, (str,)),
1405+ "url-loaded": (GObject.SIGNAL_RUN_FIRST,
1406+ GObject.TYPE_NONE, (str,)),
1407 }
1408
1409 def __init__(self):
1410 RB.Source.__init__(self, name=_("Ubuntu One"))
1411- gobject.GObject.__init__(self)
1412 self.browser = MUSIC_STORE_WIDGET
1413 self.__activated = False
1414+ self.__plugin = None
1415 self.add_music_store_widget()
1416
1417 def do_impl_activate(self):
1418@@ -317,6 +241,7 @@
1419 return False
1420 uri_to_use = uri.replace("u1ms://", "http://")
1421 print "Calling u1musicstore plugin with %s" % uri_to_use
1422+ # pylint: disable=E1101
1423 shell = self.get_property("shell")
1424 shell.props.display_page_tree.select(self)
1425 self.browser.load_store_link(uri_to_use)
1426@@ -324,6 +249,7 @@
1427
1428 def add_music_store_widget(self):
1429 """Display the music store widget in Rhythmbox."""
1430+ # pylint: disable=E1101
1431 self.add(self.browser)
1432 self.browser.show()
1433 self.show()
1434@@ -343,25 +269,28 @@
1435 return True # so we can pause, else we segfault
1436
1437 def re_emit_preview(self, widget, url, title):
1438- """Handle the preview-mp3 signal and re-emit it to rb.Plugin."""
1439+ """Handle the preview-mp3 signal and re-emit it."""
1440+ # pylint: disable=E1101
1441 self.emit("preview-mp3", url, title)
1442
1443 def re_emit_playlibrary(self, widget, path):
1444- """Handle the play-library signal and re-emit it to rb.Plugin."""
1445+ """Handle the play-library signal and re-emit it."""
1446+ # pylint: disable=E1101
1447 self.emit("play-library", path)
1448
1449 def re_emit_downloadfinished(self, widget, path):
1450- """Handle the download-finished signal and re-emit it to rb.Plugin."""
1451+ """Handle the download-finished signal and re-emit it."""
1452+ # pylint: disable=E1101
1453 self.emit("download-finished", path)
1454
1455 def re_emit_urlloaded(self, widget, url):
1456- """Handle the url-loaded signal and re-emit it to rb.Plugin."""
1457- self.emit("url-loaded", url)
1458+ """Handle the url-loaded signal and re-emit it."""
1459+ # pylint: disable=E1101
1460+ self.signal_emit_by_name("url-loaded", url)
1461
1462 def do_set_property(self, prop, value):
1463- """Allow property settings to handle the plugin call."""
1464+ """Allow property settings to handle the plug-in call."""
1465 if prop.name == 'plugin':
1466 self.__plugin = value
1467 else:
1468 raise AttributeError('unknown property %s' % prop.name)
1469-
1470
1471=== renamed file 'umusicstore/umusicstore.rb-plugin.in' => 'ubuntuone/ubuntuone.plugin.in'
1472--- umusicstore/umusicstore.rb-plugin.in 2010-03-25 08:13:45 +0000
1473+++ ubuntuone/ubuntuone.plugin.in 2012-01-19 20:21:35 +0000
1474@@ -1,10 +1,11 @@
1475-[RB Plugin]
1476+[Plugin]
1477 Loader=python
1478-Module=umusicstore
1479+Module=ubuntuone
1480 IAge=1
1481-_Name=Ubuntu One Music Store
1482-_Description=The Ubuntu One Music Store
1483-Authors=Stuart Langridge <stuart.langridge@canonical.com>, Rodrigo Moya <rodrigo.moya@canonical.com>
1484-Copyright=Copyright © 2009 Canonical
1485+Depends=rb
1486+Name=Ubuntu One
1487+_Description=Integration of Ubuntu One for Rhythmbox.
1488+Authors=Ubuntu One Developers <ubuntuone-users@lists.launchpad.net>
1489+Copyright=Copyright © 2009-2012 Canonical
1490 Website=http://one.ubuntu.com/
1491
1492
1493=== renamed file 'umusicstore/__init__.py' => 'ubuntuone/ubuntuone.py'
1494--- umusicstore/__init__.py 2011-04-05 21:31:48 +0000
1495+++ ubuntuone/ubuntuone.py 2012-01-19 20:21:35 +0000
1496@@ -1,5 +1,4 @@
1497-"""The Ubuntu One Music Store Rhythmbox plugin."""
1498-# Copyright (C) 2009 Canonical, Ltd.
1499+# Copyright (C) 2009-2012 Canonical, Ltd.
1500 #
1501 # This library is free software; you can redistribute it and/or modify
1502 # it under the terms of the GNU Lesser General Public License
1503@@ -13,46 +12,52 @@
1504 # You should have received a copy of the GNU Lesser General Public
1505 # License along with this library. If not, see
1506 # <http://www.gnu.org/licenses/>.
1507-#
1508-# Authored by Stuart Langridge <stuart.langridge@canonical.com>
1509-
1510-import gconf
1511-import rb as RB
1512-
1513-from .MusicStoreWidget import U1MusicStoreWidget
1514-from .U1MSLinks import U1MSLinkProvider
1515-
1516-U1_FIRST_TIME_FLAG_ENTRY = \
1517- "/apps/rhythmbox/plugins/umusicstore/first_time_flag"
1518-
1519-
1520-class U1MusicStorePlugin (RB.Plugin):
1521- """The Ubuntu One Music Store."""
1522+"""The Ubuntu One Rhythmbox plugin."""
1523+
1524+import os
1525+
1526+# pylint: disable=E0611
1527+from gi.repository import Gio, GLib, GObject, Peas
1528+# pylint: enable=E0611
1529+
1530+# We aren't actually providing a music store widget at the moment,
1531+# as libu1 needs to be ported to gtk3 first. We may add it back later.
1532+#from MusicStoreWidget import U1MusicStoreWidget
1533+
1534+
1535+class UbuntuOnePlugin (GObject.GObject, Peas.Activatable):
1536+ """Ubuntu One integration for Rhythmbox."""
1537+ __gtype_name__ = 'UbuntuOnePlugin'
1538+ object = GObject.property(type=GObject.GObject)
1539
1540 def __init__(self):
1541- RB.Plugin.__init__(self)
1542+ GObject.GObject.__init__(self)
1543+
1544+ # The folder where files get stored
1545+ self.u1_library_path_url = 'file://{0}'.format(
1546+ os.path.join(GLib.get_home_dir(),
1547+ '.ubuntuone',
1548+ 'Purchased from Ubuntu One'))
1549+ # RhythmDB settings so we can handle changes
1550+ self.rdbconf = Gio.Settings('org.gnome.rhythmbox.rhythmdb')
1551+ self.rdbconf.connect('changed::locations', self._locations_changed)
1552
1553 # The Music Store itself
1554- self.music_store_widget = U1MusicStoreWidget(plugin=self)
1555-
1556- # The Links button
1557- self.music_store_links_provider = U1MSLinkProvider(
1558- find_file=self.find_file)
1559-
1560- def activate(self, shell):
1561- """Plugin startup."""
1562- self.music_store_widget.activate(shell)
1563- self.music_store_links_provider.activate(shell)
1564-
1565- # Select the source if it's the first time
1566- conf_client = gconf.client_get_default()
1567- if not conf_client.get_bool(U1_FIRST_TIME_FLAG_ENTRY):
1568- shell.props.display_page_tree.select(
1569- self.music_store_widget.source)
1570- conf_client.set_bool(U1_FIRST_TIME_FLAG_ENTRY, True)
1571-
1572- def deactivate(self, shell):
1573- """Plugin shutdown."""
1574- self.music_store_widget.deactivate(shell)
1575- self.music_store_links_provider.deactivate(shell)
1576-
1577+ #self.music_store_widget = U1MusicStoreWidget(plugin=self)
1578+
1579+ def _locations_changed(self, *args, **kwargs):
1580+ """Handle the locations setting being changed."""
1581+ libraries = self.rdbconf.get_strv('locations')
1582+ if self.u1_library_path_url not in libraries:
1583+ libraries.append(self.u1_library_path_url)
1584+ self.rdbconf.set_strv('locations', libraries)
1585+
1586+ def do_activate(self):
1587+ """Plug-in startup."""
1588+ # Add the Ubuntu One purchased music directory if not already added
1589+ self._locations_changed()
1590+ #self.music_store_widget.activate(shell)
1591+
1592+ def do_deactivate(self):
1593+ """Plug-in shutdown."""
1594+ #self.music_store_widget.deactivate(shell)
1595
1596=== removed file 'umusicstore/U1MSLinks.py'
1597--- umusicstore/U1MSLinks.py 2010-12-22 19:16:06 +0000
1598+++ umusicstore/U1MSLinks.py 1970-01-01 00:00:00 +0000
1599@@ -1,380 +0,0 @@
1600-"""The Ubuntu One Music Store Links plugin."""
1601-# Copyright (C) 2010 Canonical, Ltd.
1602-#
1603-# This library is free software; you can redistribute it and/or modify
1604-# it under the terms of the GNU Lesser General Public License
1605-# version 3.0 as published by the Free Software Foundation.
1606-#
1607-# This library is distributed in the hope that it will be useful,
1608-# but WITHOUT ANY WARRANTY; without even the implied warranty of
1609-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1610-# GNU Lesser General Public License version 3.0 for more details.
1611-#
1612-# You should have received a copy of the GNU Lesser General Public
1613-# License along with this library. If not, see
1614-# <http://www.gnu.org/licenses/>.
1615-#
1616-# Authored by Stuart Langridge <stuart.langridge@canonical.com>
1617-
1618-# Import gtk+/gio bits here because order matters for some unknown reason
1619-import glib
1620-import gtk
1621-import gio
1622-
1623-import cgi
1624-import gettext
1625-import locale
1626-import operator
1627-import os
1628-import re
1629-import rhythmdb
1630-import unicodedata
1631-import urllib
1632-import xml.parsers
1633-
1634-from gettext import lgettext as _
1635-from xml.dom import minidom
1636-
1637-try:
1638- import gwibber.lib.gtk.widgets
1639- GWIBBER_AVAILABLE = True
1640-except ImportError:
1641- GWIBBER_AVAILABLE = False
1642-
1643-gettext.bindtextdomain("rhythmbox-ubuntuone-music-store", "/usr/share/locale")
1644-gettext.textdomain("rhythmbox-ubuntuone-music-store")
1645-
1646-UI_STR = \
1647-"""<ui>
1648- <menubar name="MenuBar">
1649- <menu name="ViewMenu" action="View">
1650- <placeholder name="ViewMenuModePlaceholder">
1651- <menuitem name="ViewMenuGetU1MSLink" action="GetU1MSLink"/>
1652- </placeholder>
1653- </menu>
1654- </menubar>
1655- <toolbar name="ToolBar">
1656- <placeholder name="ToolBarPluginPlaceholder">
1657- <toolitem name="U1MSLink" action="GetU1MSLink"/>
1658- </placeholder>
1659- </toolbar>
1660-</ui>"""
1661-
1662-ERRORS = {
1663- "could-not-detect": _("Unable to automatically detect which "
1664- "song is currently playing. Please try searching for "
1665- "the song in the Ubuntu One Music Store."),
1666- "could-not-find": _("Unable to automatically find the song that is "
1667- "currently playing in the Ubuntu One Music Store. "
1668- "Please try searching manually."),
1669- "could-not-connect": _("Unable to look up the song (couldn't connect "
1670- "to Ubuntu One). Please check your internet "
1671- "connection, or try again shortly.")}
1672-
1673-BASE_URL = os.environ.get("U1MSLINK_BASE_URL", "https://one.ubuntu.com")
1674-# getpreferredencoding isn't threadsafe, but we should be OK
1675-PREFERRED_ENCODING = locale.getpreferredencoding()
1676-SCRUBBING_RE = re.compile(r"[\W\s]+", re.UNICODE)
1677-CLEANING_RE = re.compile(r"\s+", re.UNICODE)
1678-
1679-
1680-def normalize(string):
1681- """Normalize the given string, to increase the chances of a match"""
1682- # rule #0 of unicode mangling: first, normalize
1683- na = unicodedata.normalize('NFKD', string)
1684- # then, strip everything that's not alphanumeric
1685- na = re.sub(SCRUBBING_RE, "", na)
1686- # \w leaves _s
1687- na = na.replace("_", " ")
1688- # then, unify spaces
1689- na = re.sub(CLEANING_RE, " ", na).strip()
1690- # finally, lowercase
1691- na = na.lower()
1692- # if there's anything left, go with that, otherwise rollback
1693- return na if na else string
1694-
1695-
1696-def modified_levenshtein(start, end):
1697- """Calculates the Levenshtein distance between start and end,
1698- but counts added characters as worth 0 (thus meaning that 'Foo' will match
1699- 'Foo (Radio Edit)' with a high degree of accuracy.)"""
1700- start = normalize(start)
1701- end = normalize(end)
1702- ls, le = len(start), len(end)
1703- if ls > le:
1704- # Make sure ls <= le, to use O(min(ls, le)) space
1705- start, end = end, start
1706- ls, le = le, ls
1707-
1708- current = range(ls + 1)
1709- for pose in range(1, le + 1):
1710- previous, current = current, [pose] + [0] * ls
1711- for poss in range(1, ls + 1):
1712- delete = current[poss - 1] + 1
1713- change = previous[poss - 1]
1714- if start[poss - 1] != end[pose - 1]:
1715- change = change + 1
1716- # replace add with 10000 to not count adds
1717- current[poss] = min(10000, delete, change)
1718-
1719- return current[ls]
1720-
1721-
1722-class U1MSLinkProvider(object):
1723- """Get a public link for any playing song to buy it in
1724- the Ubuntu One Music Store."""
1725-
1726- def __init__(self, find_file):
1727- self.find_file = find_file
1728- self.track_fetch = None
1729- self.artist_fetch = None
1730- self.win = None
1731- self.button = None
1732- self.action_group = None
1733- self.builder = None
1734- self.pvb = None
1735- self.tweet_button = None
1736- self.message = None
1737- self.ui_id = None
1738- self.image = None
1739-
1740- def activate(self, shell):
1741- """Plugin startup."""
1742- # Add button and menu item
1743- action = gtk.Action("GetU1MSLink", _("Get link to Music Store"),
1744- _("Get a link for the current song to the Ubuntu One Music Store"),
1745- "view-u1mslink")
1746- action.set_icon_name("ubuntuone")
1747- action.connect("activate", self.get_link, shell)
1748- manager = shell.get_player().get_property("ui-manager")
1749- self.action_group = gtk.ActionGroup('U1MSLinkPluginActions')
1750- self.action_group.add_action(action)
1751- manager.insert_action_group(self.action_group, 0)
1752- self.ui_id = manager.add_ui_from_string(UI_STR)
1753- manager.ensure_update()
1754-
1755- def deactivate(self, shell):
1756- """Plugin shutdown."""
1757- manager = shell.get_player().get_property('ui-manager')
1758- manager.remove_ui(self.ui_id)
1759- manager.remove_action_group(self.action_group)
1760- manager.ensure_update()
1761-
1762- def dialog_response_cb(self, dialog, response_id):
1763- """Destroy the window."""
1764- self.win.destroy()
1765- self.win = None
1766-
1767- def get_link(self, action, shell):
1768- """Get the details of the currently playing song from RB."""
1769- self.builder = gtk.Builder()
1770- self.builder.add_from_file(self.find_file("u1msurl.glade"))
1771- self.win = self.builder.get_object("winMain")
1772- self.win.connect("response", self.dialog_response_cb)
1773- self.win.set_transient_for(shell.props.window)
1774- self.image = self.builder.get_object("imgMain")
1775- self.image.set_from_icon_name("ubuntuone", gtk.ICON_SIZE_DIALOG)
1776- self.win.show_all()
1777-
1778- player = shell.get_player()
1779- entry = player.get_playing_entry()
1780- if not entry:
1781- # This shouldn't happen; the button and menu item should
1782- # be disabled when nothing is playing
1783- self.display_error('could-not-detect')
1784- return
1785- artist = shell.props.db.entry_get(entry, rhythmdb.PROP_ARTIST)
1786- if not artist:
1787- # If you're playing something odd, like a radio station, then
1788- # there is a playing entry but it doesn't have an artist.
1789- self.display_error('could-not-detect')
1790- return
1791- title = shell.props.db.entry_get(entry, rhythmdb.PROP_TITLE)
1792- album = shell.props.db.entry_get(entry, rhythmdb.PROP_ALBUM)
1793- # promote them from strings to Unicode
1794- artist = artist.decode(PREFERRED_ENCODING, 'replace')
1795- title = title.decode(PREFERRED_ENCODING, 'replace')
1796- album = album.decode(PREFERRED_ENCODING, 'replace')
1797- self.builder.get_object("lblProgress").set_markup(
1798- _("Looking up <i>%s</i> by <i>%s</i> from <i>%s</i>") % (
1799- cgi.escape(title), cgi.escape(artist), cgi.escape(album)))
1800- self.lookup_artist(title, artist, album)
1801-
1802- def display_error(self, messagename):
1803- """Display error text and a warning icon."""
1804- self.builder.get_object("lblProgress").set_markup(ERRORS[messagename])
1805- self.image.set_from_icon_name("dialog-warning",
1806- gtk.ICON_SIZE_DIALOG)
1807-
1808- def lookup_artist(self, title, artist, album):
1809- """Use the 7digital public API to look up the artist."""
1810- base_url = "http://api.7digital.com/1.2/artist/search"
1811- params = {"q": artist.encode("utf-8", "replace"),
1812- "oauth_consumer_key": "canonical",
1813- "country": "GB"}
1814- url = "%s?%s" % (base_url, urllib.urlencode(params))
1815- self.artist_fetch = gio.File(url)
1816- self.artist_fetch.read_async(
1817- self.artist_fetched,
1818- user_data=(title, artist, album))
1819-
1820- def artist_fetched(self, gdaemonfile, result, user_data):
1821- """Artist query is complete"""
1822- title, artist, album = user_data
1823- try:
1824- data = self.artist_fetch.read_finish(result).read()
1825- except glib.GError:
1826- self.display_error('could-not-connect')
1827- return
1828- try:
1829- dom = minidom.parseString(data)
1830- except xml.parsers.expat.ExpatError:
1831- self.display_error('could-not-connect')
1832- print "Could not parse returned XML:", data
1833- return
1834- artistnodes = dom.getElementsByTagName("artist")
1835- possibles = []
1836- for anode in artistnodes:
1837- names = anode.getElementsByTagName("name")
1838- if not names:
1839- continue
1840- namenode = names[0]
1841- if not namenode.hasChildNodes():
1842- continue
1843- name = namenode.firstChild.nodeValue
1844- possibles.append((
1845- anode.getAttribute("id"),
1846- modified_levenshtein(name, artist),
1847- name))
1848- possibles.sort(key=operator.itemgetter(1))
1849- if not possibles:
1850- self.display_error('could-not-find')
1851- print "Couldn't find artist '%s'" % artist
1852- return
1853- artist_id = possibles[0][0]
1854- print "got artist %s" % possibles[0][2]
1855- self.lookup_track(title, artist, album, artist_id)
1856-
1857- def lookup_track(self, title, artist, album, artist_id):
1858- """Use the 7digital public API to look up the song."""
1859- # There is no way of searching the 7digital API and saying
1860- # I *know* the artist ID, please only return me tracks by that
1861- # artist. So instead we search for the artist name + track name
1862- # combined, and then later we'll walk through the results ourselves.
1863- base_url = "http://api.7digital.com/1.2/track/search"
1864- params = {"q": "%s %s" % (artist.encode("utf-8", "replace"),
1865- title.encode("utf-8", "replace")),
1866- "oauth_consumer_key": "canonical",
1867- "country": "GB", "pagesize": 50}
1868- url = "%s?%s" % (base_url, urllib.urlencode(params))
1869- self.track_fetch = gio.File(url)
1870- self.track_fetch.read_async(self.track_fetched,
1871- user_data=(title, artist, album, artist_id))
1872-
1873- def track_fetched(self, gdaemonfile, result, user_data):
1874- """Track query is complete"""
1875- title, artist, album, artist_id = user_data
1876- try:
1877- data = self.artist_fetch.read_finish(result).read()
1878- except glib.GError:
1879- self.display_error('could-not-connect')
1880- return
1881- try:
1882- dom = minidom.parseString(data)
1883- except xml.parsers.expat.ExpatError:
1884- self.display_error('could-not-connect')
1885- print "Could not parse returned XML:", data
1886- return
1887- print data
1888- tracknodes = dom.getElementsByTagName("track")
1889- possibles = []
1890- for tnode in tracknodes:
1891- anodes = tnode.getElementsByTagName("artist")
1892- if not anodes:
1893- continue
1894- aid = anodes[0].getAttribute("id")
1895- if aid == artist_id:
1896- artist_score = 0
1897- artist_name = artist
1898- else:
1899- atnodes = anodes[0].getElementsByTagName("name")
1900- if not atnodes:
1901- continue
1902- if not atnodes[0].hasChildNodes():
1903- continue
1904- # a +100 penalty for not being the right artist
1905- artist_score = 100 + modified_levenshtein(
1906- atnodes[0].firstChild.nodeValue, artist)
1907- artist_name = atnodes[0].firstChild.nodeValue
1908- nnodes = tnode.getElementsByTagName("title")
1909- if not nnodes:
1910- continue
1911- if not nnodes[0].hasChildNodes():
1912- continue
1913- rnodes = tnode.getElementsByTagName("release")
1914- if not rnodes:
1915- continue
1916- rtnodes = rnodes[0].getElementsByTagName("title")
1917- if not rtnodes:
1918- continue
1919- if not rtnodes[0].hasChildNodes():
1920- continue
1921- track_score = modified_levenshtein(
1922- nnodes[0].firstChild.nodeValue, title)
1923- album_score = modified_levenshtein(
1924- rtnodes[0].firstChild.nodeValue, album)
1925- total_score = track_score + album_score + artist_score
1926- result = {"track": nnodes[0].firstChild.nodeValue,
1927- "album": rtnodes[0].firstChild.nodeValue,
1928- "artist": artist_name,
1929- "track_score": track_score,
1930- "album_score": album_score,
1931- "artist_score": album_score,
1932- "total_score": total_score,
1933- "trackid": tnode.getAttribute("id")}
1934- if total_score < 150:
1935- possibles.append(result)
1936- else:
1937- print "discarding", result
1938- possibles.sort(key=operator.itemgetter('total_score'))
1939- if not possibles:
1940- print "Didn't find any matches at all"
1941- self.display_error('could-not-find')
1942- return
1943- print possibles
1944- match = possibles[0]
1945- print "got a match", match
1946- dest_url = "%s/music/l/%s/%s" % (
1947- BASE_URL, match["trackid"], "0") # this 0 should be userid
1948- self.builder.get_object("lblProgress").set_markup(
1949- _("Found <i>%s</i> by <i>%s</i> from <i>%s</i>") % (
1950- cgi.escape(match["track"]), cgi.escape(match["artist"]),
1951- cgi.escape(match["album"])))
1952- self.builder.get_object("lblURL").set_markup(
1953- "<big><b>%s</b></big>" % dest_url)
1954- clipboard = gtk.Clipboard(
1955- gtk.gdk.display_manager_get().get_default_display(), "CLIPBOARD")
1956- clipboard.set_text(dest_url)
1957-
1958- if GWIBBER_AVAILABLE:
1959- self.tweet_button = gtk.Button("Tweet this link")
1960- self.tweet_button.connect("clicked", self.gwibber, dest_url,
1961- artist, album, title)
1962- self.win.get_content_area().pack_end(self.tweet_button)
1963- self.tweet_button.show()
1964-
1965- def gwibber(self, button, url, artist, album, title):
1966- """Show the Gwibber posting widget."""
1967- self.pvb = gwibber.lib.gtk.widgets.GwibberPosterVBox()
1968- self.message = "Currently listening to %s by %s %s" % (
1969- title, artist, url)
1970- self.pvb.input.connect("expose-event", self.gwibber_input_text)
1971- self.pvb.button_send.connect("clicked",
1972- lambda x: self.builder.get_object("winMain").destroy())
1973- self.pvb.show_all()
1974- self.builder.get_object("vbMain").pack_end(self.pvb)
1975- self.tweet_button.hide()
1976-
1977- def gwibber_input_text(self, *args):
1978- """Set the Gwibber text input."""
1979- self.pvb.input.set_text(self.message)
1980
1981=== removed file 'umusicstore/u1msurl.glade'
1982--- umusicstore/u1msurl.glade 2010-09-20 15:15:15 +0000
1983+++ umusicstore/u1msurl.glade 1970-01-01 00:00:00 +0000
1984@@ -1,108 +0,0 @@
1985-<?xml version="1.0"?>
1986-<interface>
1987- <requires lib="gtk+" version="2.16"/>
1988- <!-- interface-naming-policy project-wide -->
1989- <object class="GtkDialog" id="winMain">
1990- <property name="border_width">5</property>
1991- <property name="type_hint">normal</property>
1992- <property name="has_separator">False</property>
1993- <child internal-child="vbox">
1994- <object class="GtkVBox" id="dialog-vbox1">
1995- <property name="visible">True</property>
1996- <property name="spacing">2</property>
1997- <child>
1998- <object class="GtkHBox" id="hbox1">
1999- <property name="visible">True</property>
2000- <child>
2001- <object class="GtkImage" id="imgMain">
2002- <property name="visible">True</property>
2003- <property name="yalign">0</property>
2004- <property name="xpad">3</property>
2005- <property name="ypad">3</property>
2006- <property name="stock">gtk-info</property>
2007- <property name="icon-size">6</property>
2008- </object>
2009- <packing>
2010- <property name="expand">False</property>
2011- <property name="position">0</property>
2012- </packing>
2013- </child>
2014- <child>
2015- <object class="GtkVBox" id="vbMain">
2016- <property name="visible">True</property>
2017- <property name="spacing">3</property>
2018- <child>
2019- <object class="GtkLabel" id="lblProgress">
2020- <property name="visible">True</property>
2021- <property name="xalign">0</property>
2022- <property name="yalign">0</property>
2023- <property name="wrap">True</property>
2024- </object>
2025- <packing>
2026- <property name="expand">False</property>
2027- <property name="fill">False</property>
2028- <property name="padding">3</property>
2029- <property name="position">0</property>
2030- </packing>
2031- </child>
2032- <child>
2033- <object class="GtkLabel" id="lblURL">
2034- <property name="visible">True</property>
2035- <property name="xalign">0</property>
2036- <property name="yalign">0</property>
2037- <property name="wrap">True</property>
2038- <property name="selectable">True</property>
2039- </object>
2040- <packing>
2041- <property name="expand">False</property>
2042- <property name="fill">False</property>
2043- <property name="padding">3</property>
2044- <property name="position">1</property>
2045- </packing>
2046- </child>
2047- </object>
2048- <packing>
2049- <property name="position">1</property>
2050- </packing>
2051- </child>
2052- </object>
2053- <packing>
2054- <property name="padding">3</property>
2055- <property name="position">1</property>
2056- </packing>
2057- </child>
2058- <child internal-child="action_area">
2059- <object class="GtkHButtonBox" id="dialog-action_area1">
2060- <property name="visible">True</property>
2061- <property name="layout_style">end</property>
2062- <child>
2063- <placeholder/>
2064- </child>
2065- <child>
2066- <object class="GtkButton" id="button1">
2067- <property name="label">gtk-close</property>
2068- <property name="visible">True</property>
2069- <property name="can_focus">True</property>
2070- <property name="receives_default">True</property>
2071- <property name="use_stock">True</property>
2072- </object>
2073- <packing>
2074- <property name="expand">False</property>
2075- <property name="fill">False</property>
2076- <property name="position">1</property>
2077- </packing>
2078- </child>
2079- </object>
2080- <packing>
2081- <property name="expand">False</property>
2082- <property name="pack_type">end</property>
2083- <property name="position">0</property>
2084- </packing>
2085- </child>
2086- </object>
2087- </child>
2088- <action-widgets>
2089- <action-widget response="0">button1</action-widget>
2090- </action-widgets>
2091- </object>
2092-</interface>

Subscribers

People subscribed via source and target branches

to all changes: