1
# Miro - an RSS based video player application
2
# Copyright (C) 2009-2010 Participatory Culture Foundation
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.
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.
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
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
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.
29
"""``miro.commandline`` -- This modules handles the parsing of
30
files/URLs passed to Miro on the command line.
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.
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.
41
from miro.gtcache import gettext as _
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
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
61
_command_line_args = []
63
_command_line_videos = None
64
_command_line_view = None
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):
75
def add_video(path, manual_feed=None):
76
path = os.path.abspath(path)
77
item_for_path = _item_exists_for_path(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)
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(),
88
if _command_line_videos is not None:
89
_command_line_videos.add(file_item)
91
def add_videos(paths):
92
manual_feed = feed.Feed.get_manual_feed()
93
app.bulk_sql_manager.start()
96
add_video(path, manual_feed=manual_feed)
98
app.bulk_sql_manager.finish()
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",
107
if i.downloader.get_state() in ('paused', 'stopped'):
110
new_item = item.Item(item.fp_values_for_file(path),
111
feed_id=manual_feed.get_id())
114
def _complain_about_subscription_url(message_text):
115
title = _("Subscription error")
116
dialogs.MessageBoxDialog(title, message_text).run()
118
def add_subscription_url(prefix, expected_content_type, url):
119
real_url = url[len(prefix):]
121
if info.get('content-type') == expected_content_type:
122
subscription_list = autodiscover.parse_content(info['body'])
123
if subscription_list is None:
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),
130
_complain_about_subscription_url(text)
132
subscription.Subscriber().add_subscriptions(
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),
141
_complain_about_subscription_url(text)
145
"Could not download the %(appname)s feed file: %(url)s",
146
{"appname": config.get(prefs.SHORT_APP_NAME),
149
_complain_about_subscription_url(text)
151
httpclient.grabURL(real_url, callback, errback)
153
def set_command_line_args(args):
154
_command_line_args.extend(args)
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()
163
def parse_command_line_args(args):
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.
169
_command_line_args.extend(args)
171
reset_command_line_view()
174
added_downloads = False
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'):
192
torrent_infohash = get_torrent_info_hash(arg)
194
title = _("Invalid Torrent")
196
"The torrent file %(filename)s appears to be corrupt "
197
"and cannot be opened.",
198
{"filename": os.path.basename(arg)}
200
dialogs.MessageBoxDialog(title, msg).run()
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)
212
logging.warning("parse_command_line_args: %s doesn't exist", arg)
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.
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()
225
# FIXME - switch to downloads tab?
229
global _command_line_args
232
parse_command_line_args(_command_line_args)
233
_command_line_args = []