Vimeo: Support for selecting file format (bug 1954)
This commit is contained in:
parent
5693551766
commit
e215a5d5a3
|
@ -52,7 +52,7 @@
|
|||
<object class="GtkTable" id="table_players">
|
||||
<property name="column_spacing">6</property>
|
||||
<property name="n_columns">3</property>
|
||||
<property name="n_rows">3</property>
|
||||
<property name="n_rows">4</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="visible">True</property>
|
||||
<child>
|
||||
|
@ -136,11 +136,11 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_preferred_video_format">
|
||||
<object class="GtkLabel" id="label_preferred_youtube_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Preferred video format:</property>
|
||||
<property name="label" translatable="yes">Preferred YouTube format:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">2</property>
|
||||
|
@ -149,10 +149,10 @@
|
|||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_preferred_video_format">
|
||||
<object class="GtkComboBox" id="combobox_preferred_youtube_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<signal name="changed" handler="on_combobox_preferred_video_format_changed" swapped="no"/>
|
||||
<signal name="changed" handler="on_combobox_preferred_youtube_format_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
|
@ -161,6 +161,32 @@
|
|||
<property name="bottom_attach">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_preferred_vimeo_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="label" translatable="yes">Preferred Vimeo format:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="x_options">fill</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkComboBox" id="combobox_preferred_vimeo_format">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<signal name="changed" handler="on_combobox_preferred_vimeo_format_changed" swapped="no"/>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
|
|
|
@ -193,6 +193,10 @@ defaults = {
|
|||
'preferred_fmt_ids': [], # for advanced uses (custom fallback sequence)
|
||||
},
|
||||
|
||||
'vimeo': {
|
||||
'fileformat': 'hd', # preferred file format (hd, sd, mobile)
|
||||
},
|
||||
|
||||
'extensions': {
|
||||
'enabled': [],
|
||||
},
|
||||
|
|
|
@ -751,7 +751,7 @@ class DownloadTask(object):
|
|||
# Resolve URL and start downloading the episode
|
||||
fmt_ids = youtube.get_fmt_ids(self._config.youtube)
|
||||
url = youtube.get_real_download_url(self.__episode.url, fmt_ids)
|
||||
url = vimeo.get_real_download_url(url)
|
||||
url = vimeo.get_real_download_url(url, self._config.vimeo.fileformat)
|
||||
url = escapist_videos.get_real_download_url(url)
|
||||
|
||||
downloader = DownloadURLOpener(self.__episode.channel)
|
||||
|
|
|
@ -32,6 +32,7 @@ N_ = gpodder.ngettext
|
|||
|
||||
from gpodder import util
|
||||
from gpodder import youtube
|
||||
from gpodder import vimeo
|
||||
|
||||
from gpodder.gtkui.interface.common import BuilderWidget
|
||||
from gpodder.gtkui.interface.common import TreeViewHelper
|
||||
|
@ -139,23 +140,28 @@ class gPodderFlattrSignIn(BuilderWidget):
|
|||
def on_btn_close_clicked(self, widget):
|
||||
util.idle_add(self.main_window.destroy)
|
||||
|
||||
class VideoFormatList(gtk.ListStore):
|
||||
|
||||
class YouTubeVideoFormatListModel(gtk.ListStore):
|
||||
C_CAPTION, C_ID = range(2)
|
||||
|
||||
def __init__(self, config):
|
||||
gtk.ListStore.__init__(self, str, int)
|
||||
self._config = config
|
||||
self.custom_fmt_ids = self._config.youtube.preferred_fmt_ids
|
||||
|
||||
if self._config.youtube.preferred_fmt_ids:
|
||||
caption = _('Custom (%(format_ids)s)') % {
|
||||
'format_ids': ', '.join(self.custom_format_ids),
|
||||
'format_ids': ', '.join(str(x) for x in self.custom_fmt_ids),
|
||||
}
|
||||
self.append((caption, -1))
|
||||
else:
|
||||
for id, (fmt_id, path, description) in youtube.formats:
|
||||
self.append((description, id))
|
||||
|
||||
for id, (fmt_id, path, description) in youtube.formats:
|
||||
self.append((description, id))
|
||||
|
||||
def get_index(self):
|
||||
if self._config.youtube.preferred_fmt_ids:
|
||||
return 0
|
||||
|
||||
for index, row in enumerate(self):
|
||||
if self._config.youtube.preferred_fmt_id == row[self.C_ID]:
|
||||
return index
|
||||
|
@ -165,6 +171,36 @@ class VideoFormatList(gtk.ListStore):
|
|||
value = self[index][self.C_ID]
|
||||
if value > 0:
|
||||
self._config.youtube.preferred_fmt_id = value
|
||||
# If we set a value, we need to unset the custom one, so that
|
||||
# the single value (preferred_fmt_id) gets used instead
|
||||
self._config.youtube.preferred_fmt_ids = []
|
||||
else:
|
||||
# If the user selects the -1 value, it's our custom one, and
|
||||
# we need to restore the value for preferred_fmt_ids
|
||||
self._config.youtube.preferred_fmt_ids = self.custom_fmt_ids
|
||||
|
||||
|
||||
class VimeoVideoFormatListModel(gtk.ListStore):
|
||||
C_CAPTION, C_ID = range(2)
|
||||
|
||||
def __init__(self, config):
|
||||
gtk.ListStore.__init__(self, str, str)
|
||||
self._config = config
|
||||
|
||||
for fileformat, description in vimeo.FORMATS:
|
||||
self.append((description, fileformat))
|
||||
|
||||
def get_index(self):
|
||||
for index, row in enumerate(self):
|
||||
if self._config.vimeo.fileformat == row[self.C_ID]:
|
||||
return index
|
||||
return 0
|
||||
|
||||
def set_index(self, index):
|
||||
value = self[index][self.C_ID]
|
||||
if value > 0:
|
||||
self._config.vimeo.fileformat = value
|
||||
|
||||
|
||||
class gPodderPreferences(BuilderWidget):
|
||||
C_TOGGLE, C_LABEL, C_EXTENSION, C_SHOW_TOGGLE = range(4)
|
||||
|
@ -190,12 +226,19 @@ class gPodderPreferences(BuilderWidget):
|
|||
index = self.video_player_model.get_index(self._config.videoplayer)
|
||||
self.combo_video_player_app.set_active(index)
|
||||
|
||||
self.preferred_video_format_model = VideoFormatList(self._config)
|
||||
self.combobox_preferred_video_format.set_model(self.preferred_video_format_model)
|
||||
self.preferred_youtube_format_model = YouTubeVideoFormatListModel(self._config)
|
||||
self.combobox_preferred_youtube_format.set_model(self.preferred_youtube_format_model)
|
||||
cellrenderer = gtk.CellRendererText()
|
||||
self.combobox_preferred_video_format.pack_start(cellrenderer, True)
|
||||
self.combobox_preferred_video_format.add_attribute(cellrenderer, 'text', self.preferred_video_format_model.C_CAPTION)
|
||||
self.combobox_preferred_video_format.set_active(self.preferred_video_format_model.get_index())
|
||||
self.combobox_preferred_youtube_format.pack_start(cellrenderer, True)
|
||||
self.combobox_preferred_youtube_format.add_attribute(cellrenderer, 'text', self.preferred_youtube_format_model.C_CAPTION)
|
||||
self.combobox_preferred_youtube_format.set_active(self.preferred_youtube_format_model.get_index())
|
||||
|
||||
self.preferred_vimeo_format_model = VimeoVideoFormatListModel(self._config)
|
||||
self.combobox_preferred_vimeo_format.set_model(self.preferred_vimeo_format_model)
|
||||
cellrenderer = gtk.CellRendererText()
|
||||
self.combobox_preferred_vimeo_format.pack_start(cellrenderer, True)
|
||||
self.combobox_preferred_vimeo_format.add_attribute(cellrenderer, 'text', self.preferred_vimeo_format_model.C_CAPTION)
|
||||
self.combobox_preferred_vimeo_format.set_active(self.preferred_vimeo_format_model.get_index())
|
||||
|
||||
self._config.connect_gtk_togglebutton('podcast_list_view_all',
|
||||
self.checkbutton_show_all_episodes)
|
||||
|
@ -482,9 +525,13 @@ class gPodderPreferences(BuilderWidget):
|
|||
index = self.combo_video_player_app.get_active()
|
||||
self._config.videoplayer = self.video_player_model.get_command(index)
|
||||
|
||||
def on_combobox_preferred_video_format_changed(self, widget):
|
||||
index = self.combobox_preferred_video_format.get_active()
|
||||
self.preferred_video_format_model.set_index(index)
|
||||
def on_combobox_preferred_youtube_format_changed(self, widget):
|
||||
index = self.combobox_preferred_youtube_format.get_active()
|
||||
self.preferred_youtube_format_model.set_index(index)
|
||||
|
||||
def on_combobox_preferred_vimeo_format_changed(self, widget):
|
||||
index = self.combobox_preferred_vimeo_format.get_active()
|
||||
self.preferred_vimeo_format_model.set_index(index)
|
||||
|
||||
def on_button_audio_player_clicked(self, widget):
|
||||
result = self.show_text_edit_dialog(_('Configure audio player'), \
|
||||
|
|
|
@ -1873,9 +1873,10 @@ class gPodder(BuilderWidget, dbus.service.Object):
|
|||
self.mygpo_client.on_playback([episode])
|
||||
|
||||
fmt_ids = youtube.get_fmt_ids(self.config.youtube)
|
||||
vimeo_fmt = self.config.vimeo.fileformat
|
||||
|
||||
allow_partial = (player != 'default')
|
||||
filename = episode.get_playback_url(fmt_ids, allow_partial)
|
||||
filename = episode.get_playback_url(fmt_ids, vimeo_fmt, allow_partial)
|
||||
|
||||
# Determine the playback resume position - if the file
|
||||
# was played 100%, we simply start from the beginning
|
||||
|
|
|
@ -466,7 +466,7 @@ class PodcastEpisode(PodcastModelObject):
|
|||
|
||||
self.set_state(gpodder.STATE_DELETED)
|
||||
|
||||
def get_playback_url(self, fmt_ids=None, allow_partial=False):
|
||||
def get_playback_url(self, fmt_ids=None, vimeo_fmt=None, allow_partial=False):
|
||||
"""Local (or remote) playback/streaming filename/URL
|
||||
|
||||
Returns either the local filename or a streaming URL that
|
||||
|
@ -484,7 +484,7 @@ class PodcastEpisode(PodcastModelObject):
|
|||
if url is None or not os.path.exists(url):
|
||||
url = self.url
|
||||
url = youtube.get_real_download_url(url, fmt_ids)
|
||||
url = vimeo.get_real_download_url(url)
|
||||
url = vimeo.get_real_download_url(url, vimeo_fmt)
|
||||
url = escapist_videos.get_real_download_url(url)
|
||||
|
||||
return url
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
|
||||
import gpodder
|
||||
|
||||
_ = gpodder.gettext
|
||||
|
||||
from gpodder import util
|
||||
|
||||
import logging
|
||||
|
@ -44,13 +46,19 @@ MOOGALOOP_RE = re.compile(r'http://vimeo\.com/moogaloop\.swf\?clip_id=(\d+)$', r
|
|||
SIGNATURE_RE = re.compile(r'"timestamp":(\d+),"signature":"([^"]+)"')
|
||||
DATA_CONFIG_RE = re.compile(r'data-config-url="([^"]+)"')
|
||||
|
||||
# List of qualities, from lowest to highest
|
||||
FILEFORMAT_RANKING = ['mobile', 'sd', 'hd']
|
||||
|
||||
FORMATS = (
|
||||
('mobile', _('Mobile')),
|
||||
('sd', _('SD')),
|
||||
('hd', _('HD')),
|
||||
)
|
||||
|
||||
|
||||
class VimeoError(BaseException): pass
|
||||
|
||||
def get_real_download_url(url):
|
||||
quality = 'sd'
|
||||
codecs = 'H264,VP8,VP6'
|
||||
|
||||
def get_real_download_url(url, preferred_fileformat=None):
|
||||
video_id = get_vimeo_id(url)
|
||||
|
||||
if video_id is None:
|
||||
|
@ -78,8 +86,21 @@ def get_real_download_url(url):
|
|||
|
||||
yield (fileformat, keys['url'])
|
||||
|
||||
for quality, url in get_urls(data_config_url):
|
||||
return url
|
||||
fileformat_to_url = dict(get_urls(data_config_url))
|
||||
|
||||
if preferred_fileformat is not None and preferred_fileformat in fileformat_to_url:
|
||||
logger.debug('Picking preferred format: %s', preferred_fileformat)
|
||||
return fileformat_to_url[preferred_fileformat]
|
||||
|
||||
def fileformat_sort_key_func(fileformat):
|
||||
if fileformat in FILEFORMAT_RANKING:
|
||||
return FILEFORMAT_RANKING.index(fileformat)
|
||||
|
||||
return 0
|
||||
|
||||
for fileformat in sorted(fileformat_to_url, key=fileformat_sort_key_func, reverse=True):
|
||||
logger.debug('Picking best format: %s', fileformat)
|
||||
return fileformat_to_url[fileformat]
|
||||
|
||||
def get_vimeo_id(url):
|
||||
result = MOOGALOOP_RE.match(url)
|
||||
|
|
Loading…
Reference in New Issue