~ubuntu-branches/ubuntu/trusty/miro/trusty

« back to all changes in this revision

Viewing changes to portable/commandline.py

  • Committer: Daniel Hahler
  • Date: 2010-04-13 18:51:35 UTC
  • mfrom: (1.2.10 upstream)
  • Revision ID: ubuntu-launchpad@thequod.de-20100413185135-xi24v1diqg8w406x
Merging shared upstream rev into target branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Miro - an RSS based video player application
 
2
# Copyright (C) 2009-2010 Participatory Culture Foundation
 
3
#
 
4
# This program is free software; you can redistribute it and/or modify
 
5
# it under the terms of the GNU General Public License as published by
 
6
# the Free Software Foundation; either version 2 of the License, or
 
7
# (at your option) any later version.
 
8
#
 
9
# This program is distributed in the hope that it will be useful,
 
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
# GNU General Public License for more details.
 
13
#
 
14
# You should have received a copy of the GNU General Public License
 
15
# along with this program; if not, write to the Free Software
 
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
17
#
 
18
# In addition, as a special exception, the copyright holders give
 
19
# permission to link the code of portions of this program with the OpenSSL
 
20
# library.
 
21
#
 
22
# You must obey the GNU General Public License in all respects for all of
 
23
# the code used other than OpenSSL. If you modify file(s) with this
 
24
# exception, you may extend this exception to your version of the file(s),
 
25
# but you are not obligated to do so. If you do not wish to do so, delete
 
26
# this exception statement from your version. If you delete this exception
 
27
# statement from all source files in the program, then also delete it here.
 
28
 
 
29
"""``miro.commandline`` -- This modules handles the parsing of
 
30
files/URLs passed to Miro on the command line.
 
31
 
 
32
Frontends should call ``set_ommand_line_args()`` passing it a list of
 
33
arguments that the users gives.  This should just be suspected
 
34
torrents/videos, not things like ``--help``, ``--version``, etc.
 
35
 
 
36
Frontends should trap when a user opens a torrent/video with Miro
 
37
while Miro is already running.  They should arrange for ``add_video``
 
38
or ``add_torrent`` to be called in the existing Miro process.
 
39
"""
 
40
 
 
41
from miro.gtcache import gettext as _
 
42
 
 
43
import os.path
 
44
import logging
 
45
from miro import app
 
46
from miro import config
 
47
from miro import prefs
 
48
from miro import messages
 
49
from miro import dialogs
 
50
from miro import autodiscover
 
51
from miro import subscription
 
52
from miro import feed
 
53
from miro import item
 
54
from miro import httpclient
 
55
from miro import download_utils
 
56
from miro.util import get_torrent_info_hash
 
57
from miro.plat.utils import samefile, filenameToUnicode
 
58
from miro import singleclick
 
59
from miro import opml
 
60
 
 
61
_command_line_args = []
 
62
_started_up = False
 
63
_command_line_videos = None
 
64
_command_line_view = None
 
65
 
 
66
def _item_exists_for_path(path):
 
67
    # in SQLite, LIKE is case insensitive, so we can use it to only look at
 
68
    # filenames that possibly will match
 
69
    for item_ in item.Item.make_view('filename LIKE ?',
 
70
            (filenameToUnicode(path),)):
 
71
        if samefile(item_.filename, path):
 
72
            return item_
 
73
    return False
 
74
 
 
75
def add_video(path, manual_feed=None):
 
76
    path = os.path.abspath(path)
 
77
    item_for_path = _item_exists_for_path(path)
 
78
    if item_for_path:
 
79
        logging.warn("Not adding duplicate video: %s",
 
80
                     path.decode('ascii', 'ignore'))
 
81
        if _command_line_videos is not None:
 
82
            _command_line_videos.add(item_for_path)
 
83
        return
 
84
    if manual_feed is None:
 
85
        manual_feed = feed.Feed.get_manual_feed()
 
86
    file_item = item.FileItem(path, feed_id=manual_feed.get_id(),
 
87
            mark_seen=True)
 
88
    if _command_line_videos is not None:
 
89
        _command_line_videos.add(file_item)
 
90
 
 
91
def add_videos(paths):
 
92
    manual_feed = feed.Feed.get_manual_feed()
 
93
    app.bulk_sql_manager.start()
 
94
    try:
 
95
        for path in paths:
 
96
            add_video(path, manual_feed=manual_feed)
 
97
    finally:
 
98
        app.bulk_sql_manager.finish()
 
99
 
 
100
def add_torrent(path, torrent_info_hash):
 
101
    manual_feed = feed.Feed.get_manual_feed()
 
102
    for i in manual_feed.items:
 
103
        if ((i.downloader is not None
 
104
             and i.downloader.status.get('infohash') == torrent_info_hash)):
 
105
            logging.info("not downloading %s, it's already a download for %s",
 
106
                         path, i)
 
107
            if i.downloader.get_state() in ('paused', 'stopped'):
 
108
                i.download()
 
109
            return
 
110
    new_item = item.Item(item.fp_values_for_file(path),
 
111
                         feed_id=manual_feed.get_id())
 
112
    new_item.download()
 
113
 
 
114
def _complain_about_subscription_url(message_text):
 
115
    title = _("Subscription error")
 
116
    dialogs.MessageBoxDialog(title, message_text).run()
 
117
 
 
118
def add_subscription_url(prefix, expected_content_type, url):
 
119
    real_url = url[len(prefix):]
 
120
    def callback(info):
 
121
        if info.get('content-type') == expected_content_type:
 
122
            subscription_list = autodiscover.parse_content(info['body'])
 
123
            if subscription_list is None:
 
124
                text = _(
 
125
                    "This %(appname)s feed file has an invalid format: "
 
126
                    "%(url)s.  Please notify the publisher of this file.",
 
127
                    {"appname": config.get(prefs.SHORT_APP_NAME),
 
128
                     "url": real_url}
 
129
                    )
 
130
                _complain_about_subscription_url(text)
 
131
            else:
 
132
                subscription.Subscriber().add_subscriptions(
 
133
                    subscription_list)
 
134
        else:
 
135
            text = _(
 
136
                "This %(appname)s feed file has the wrong content type: "
 
137
                "%(url)s. Please notify the publisher of this file.",
 
138
                {"appname": config.get(prefs.SHORT_APP_NAME),
 
139
                 "url": real_url}
 
140
                )
 
141
            _complain_about_subscription_url(text)
 
142
 
 
143
    def errback(error):
 
144
        text = _(
 
145
            "Could not download the %(appname)s feed file: %(url)s",
 
146
            {"appname": config.get(prefs.SHORT_APP_NAME),
 
147
             "url": real_url}
 
148
            )
 
149
        _complain_about_subscription_url(text)
 
150
 
 
151
    httpclient.grabURL(real_url, callback, errback)
 
152
 
 
153
def set_command_line_args(args):
 
154
    _command_line_args.extend(args)
 
155
 
 
156
def reset_command_line_view():
 
157
    global _command_line_view, _command_line_videos
 
158
    if _command_line_view is not None:
 
159
        _command_line_view.unlink()
 
160
        _command_line_view = None
 
161
    _command_line_videos = set()
 
162
 
 
163
def parse_command_line_args(args):
 
164
    """
 
165
    This goes through a list of files which could be arguments passed
 
166
    in on the command line or a list of files from other source.
 
167
    """
 
168
    if not _started_up:
 
169
        _command_line_args.extend(args)
 
170
        return
 
171
    reset_command_line_view()
 
172
 
 
173
    added_videos = False
 
174
    added_downloads = False
 
175
 
 
176
    for arg in args:
 
177
        if arg.startswith('file://'):
 
178
            arg = download_utils.get_file_url_path(arg)
 
179
        elif arg.startswith('miro:'):
 
180
            add_subscription_url('miro:', 'application/x-miro', arg)
 
181
        elif arg.startswith('democracy:'):
 
182
            add_subscription_url('democracy:', 'application/x-democracy', arg)
 
183
        elif (arg.startswith('http:')
 
184
              or arg.startswith('https:')
 
185
              or arg.startswith('feed:')
 
186
              or arg.startswith('feeds:')):
 
187
            singleclick.add_download(filenameToUnicode(arg))
 
188
        elif os.path.exists(arg):
 
189
            ext = os.path.splitext(arg)[1].lower()
 
190
            if ext in ('.torrent', '.tor'):
 
191
                try:
 
192
                    torrent_infohash = get_torrent_info_hash(arg)
 
193
                except ValueError:
 
194
                    title = _("Invalid Torrent")
 
195
                    msg = _(
 
196
                        "The torrent file %(filename)s appears to be corrupt "
 
197
                        "and cannot be opened.",
 
198
                        {"filename": os.path.basename(arg)}
 
199
                        )
 
200
                    dialogs.MessageBoxDialog(title, msg).run()
 
201
                    continue
 
202
                add_torrent(arg, torrent_infohash)
 
203
                added_downloads = True
 
204
            elif ext in ('.rss', '.rdf', '.atom', '.ato'):
 
205
                feed.add_feed_from_file(arg)
 
206
            elif ext in ('.miro', '.democracy', '.dem', '.opml'):
 
207
                opml.Importer().import_subscriptions(arg, show_summary=False)
 
208
            else:
 
209
                add_video(arg)
 
210
                added_videos = True
 
211
        else:
 
212
            logging.warning("parse_command_line_args: %s doesn't exist", arg)
 
213
 
 
214
    # if the user has Miro set up to play all videos externally, then
 
215
    # we don't want to play videos added by the command line.
 
216
    #
 
217
    # this fixes bug 12362 where if the user has his/her system set up
 
218
    # to use Miro to play videos and Miro goes to play a video
 
219
    # externally, then it causes an infinite loop and dies.
 
220
    if added_videos and config.get(prefs.PLAY_IN_MIRO):
 
221
        item_infos = [messages.ItemInfo(i) for i in _command_line_videos]
 
222
        messages.PlayMovie(item_infos).send_to_frontend()
 
223
 
 
224
    if added_downloads:
 
225
        # FIXME - switch to downloads tab?
 
226
        pass
 
227
 
 
228
def startup():
 
229
    global _command_line_args
 
230
    global _started_up
 
231
    _started_up = True
 
232
    parse_command_line_args(_command_line_args)
 
233
    _command_line_args = []