Add support for sending files via Bluetooth
git-svn-id: svn://svn.berlios.de/gpodder/trunk@536 b0d088ad-0a06-0410-aad2-9ed5178a7e87
This commit is contained in:
parent
d6807c3a92
commit
a445089fc7
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
|||
Mon, 21 Jan 2008 10:47:49 +0100 <thp@perli.net>
|
||||
Add support for sending files via Bluetooth
|
||||
|
||||
* data/gpodder.glade: Add "Bluetooth" configuration page to
|
||||
preferences dialog
|
||||
* src/gpodder/config.py: Add Bluetooth-related configuration options
|
||||
* src/gpodder/gui.py: Add support for sending (and converting) files
|
||||
for bluetooth file transfer; add glue code for preferences dialog and
|
||||
configuration manager
|
||||
* src/gpodder/libgpodder.py: Add "tempdir" variable to gPodderLibClass
|
||||
that specifies a temporary directory to be used (currently only for
|
||||
converting files for bluetooth transfer, might be migrated to a
|
||||
configuration option later)
|
||||
* src/gpodder/util.py: Add discover_bluetooth_devices() function that
|
||||
searches for nearby devices (either via python-bluez or via hcitool,
|
||||
so one of them has to be installed as a dependency); add
|
||||
bluetooth_send_file() convenience function that starts a file transfer
|
||||
via Bluetooth OBEX - uses gnome-obex-send, which has to be installed
|
||||
for Bluetooth file transfer to work
|
||||
|
||||
Mon, 21 Jan 2008 09:52:09 +0100 <thp@perli.net>
|
||||
Support for different audio/video player selection
|
||||
|
||||
|
|
|
@ -3839,6 +3839,403 @@ Filesystem-based MP3 player</property>
|
|||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTable" id="table13">
|
||||
<property name="border_width">10</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="n_rows">8</property>
|
||||
<property name="n_columns">4</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="row_spacing">6</property>
|
||||
<property name="column_spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="image2929">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon_size">6</property>
|
||||
<property name="icon_name">stock_bluetooth</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="x_padding">6</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options">fill</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label115">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Bluetooth Support</b></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">0</property>
|
||||
<property name="bottom_attach">1</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="bluetooth_enabled">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">Enable Bluetooth support</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">1</property>
|
||||
<property name="bottom_attach">2</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkRadioButton" id="bluetooth_ask_always">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">Ask for device when sending</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">2</property>
|
||||
<property name="bottom_attach">3</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHSeparator" id="hseparator17">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">4</property>
|
||||
<property name="bottom_attach">5</property>
|
||||
<property name="y_padding">3</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkRadioButton" id="bluetooth_ask_never">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">Always send to</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
<property name="group">bluetooth_ask_always</property>
|
||||
</widget>
|
||||
<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>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="bluetooth_device_name">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Nokia N800</b></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">3</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="bluetooth_select_device">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<signal name="clicked" handler="on_bluetooth_select_device_clicked" last_modification_time="Wed, 16 Jan 2008 12:24:17 GMT"/>
|
||||
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment23">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xscale">0</property>
|
||||
<property name="yscale">0</property>
|
||||
<property name="top_padding">0</property>
|
||||
<property name="bottom_padding">0</property>
|
||||
<property name="left_padding">0</property>
|
||||
<property name="right_padding">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox36">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">2</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="image2930">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-find</property>
|
||||
<property name="icon_size">4</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label118">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Select device</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">3</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">3</property>
|
||||
<property name="bottom_attach">4</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label116">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>File Conversion Script</b></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">5</property>
|
||||
<property name="bottom_attach">6</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="bluetooth_use_converter">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">Use converter:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="focus_on_click">True</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="right_attach">2</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkFileChooserButton" id="bluetooth_converter">
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="yes">Select A Converter Script</property>
|
||||
<property name="action">GTK_FILE_CHOOSER_ACTION_OPEN</property>
|
||||
<property name="local_only">True</property>
|
||||
<property name="show_hidden">False</property>
|
||||
<property name="do_overwrite_confirmation">False</property>
|
||||
<property name="width_chars">-1</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">2</property>
|
||||
<property name="right_attach">4</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options"></property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="image2931">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon_size">6</property>
|
||||
<property name="icon_name">text-x-script</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="right_attach">1</property>
|
||||
<property name="top_attach">6</property>
|
||||
<property name="bottom_attach">7</property>
|
||||
<property name="x_options">fill</property>
|
||||
<property name="y_options">fill</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="tab_expand">False</property>
|
||||
<property name="tab_fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox12">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="image2928">
|
||||
<property name="visible">True</property>
|
||||
<property name="icon_size">3</property>
|
||||
<property name="icon_name">stock_bluetooth</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label114">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Bluetooth</property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
|
||||
<property name="width_chars">-1</property>
|
||||
<property name="single_line_mode">False</property>
|
||||
<property name="angle">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="type">tab</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTable" id="table6">
|
||||
<property name="border_width">10</property>
|
||||
|
|
|
@ -72,6 +72,15 @@ gPodderSettings = {
|
|||
'disable_notifications': (bool, False),
|
||||
'on_quit_ask': (bool, True),
|
||||
|
||||
# Bluetooth-related settings
|
||||
'bluetooth_enabled': (bool, False),
|
||||
'bluetooth_ask_always': (bool, True),
|
||||
'bluetooth_ask_never': (bool, False),
|
||||
'bluetooth_device_name': (str, 'No device'),
|
||||
'bluetooth_device_address': (str, '00:00:00:00:00:00'),
|
||||
'bluetooth_use_converter': (bool, False),
|
||||
'bluetooth_converter': (str, ''),
|
||||
|
||||
# Settings that are updated directly in code
|
||||
'ipod_mount': ( str, '/media/ipod' ),
|
||||
'mp3_player_folder': ( str, '/media/usbdisk' ),
|
||||
|
@ -142,12 +151,17 @@ class Config(dict):
|
|||
else:
|
||||
raise ValueError( '%s is not a setting' % name)
|
||||
|
||||
def connect_gtk_filechooser( self, name, filechooser):
|
||||
def connect_gtk_filechooser(self, name, filechooser, is_for_files=False):
|
||||
if name in self.Settings:
|
||||
filechooser.set_current_folder(getattr( self, name))
|
||||
filechooser.connect( 'selection-changed', lambda filechooser: setattr( self, name, filechooser.get_filename()))
|
||||
if is_for_files:
|
||||
# A FileChooser for a single file
|
||||
filechooser.set_filename(getattr(self, name))
|
||||
else:
|
||||
# A FileChooser for a folder
|
||||
filechooser.set_current_folder(getattr(self, name))
|
||||
filechooser.connect('selection-changed', lambda filechooser: setattr(self, name, filechooser.get_filename()))
|
||||
else:
|
||||
raise ValueError( '%s is not a setting' % name)
|
||||
raise ValueError('%s is not a setting'%name)
|
||||
|
||||
def receive_configure_event( self, widget, event, config_prefix):
|
||||
( x, y, width, height ) = map( lambda x: config_prefix + '_' + x, [ 'x', 'y', 'width', 'height' ])
|
||||
|
|
|
@ -25,6 +25,7 @@ import pango
|
|||
import sys
|
||||
import shutil
|
||||
import webbrowser
|
||||
import subprocess
|
||||
|
||||
from xml.sax import saxutils
|
||||
|
||||
|
@ -396,6 +397,43 @@ class gPodder(GladeWidget):
|
|||
|
||||
self.show_copy_dialog( src_filename = episode.local_filename(), dst_filename = episode.sync_filename())
|
||||
|
||||
def copy_episode_bluetooth(self, url, *args):
|
||||
episode = self.active_channel.find_episode(url)
|
||||
filename = episode.local_filename()
|
||||
|
||||
gl = gPodderLib()
|
||||
if gl.config.bluetooth_ask_always:
|
||||
device = None
|
||||
else:
|
||||
device = gl.config.bluetooth_device_address
|
||||
|
||||
if gl.config.bluetooth_use_converter:
|
||||
destfile = os.path.join(gl.tempdir, episode.sync_filename())
|
||||
(base, ext) = os.path.splitext(filename)
|
||||
if not destfile.endswith(ext):
|
||||
destfile += ext
|
||||
|
||||
title = _('Converting file')
|
||||
message = _('Please wait while gPodder converts your media file for bluetooth file transfer.')
|
||||
dlg = gtk.MessageDialog(self.gPodder, gtk.DIALOG_MODAL, gtk.MESSAGE_INFO, gtk.BUTTONS_NONE)
|
||||
dlg.set_title(title)
|
||||
dlg.set_markup('<span weight="bold" size="larger">%s</span>\n\n%s'%(title, message))
|
||||
dlg.show_all()
|
||||
|
||||
def convert_and_send_thread(filename, destfile, device, dialog, notify):
|
||||
p = subprocess.Popen([gl.config.bluetooth_converter, filename, destfile], stdout=sys.stdout, stderr=sys.stderr)
|
||||
result = p.wait()
|
||||
dialog.destroy()
|
||||
if result == 0 or not os.path.exists(destfile):
|
||||
util.bluetooth_send_file(destfile, device)
|
||||
else:
|
||||
notify(_('Error converting file.'), _('Bluetooth file transfer'))
|
||||
util.delete_file(destfile)
|
||||
|
||||
Thread(target=convert_and_send_thread, args=[filename, destfile, device, dlg, self.notification]).start()
|
||||
else:
|
||||
Thread(target=util.bluetooth_send_file, args=[filename, device]).start()
|
||||
|
||||
def treeview_button_pressed( self, treeview, event):
|
||||
if event.button == 3:
|
||||
( x, y ) = ( int(event.x), int(event.y) )
|
||||
|
@ -429,6 +467,7 @@ class gPodder(GladeWidget):
|
|||
first_url = model.get_value( model.get_iter( paths[0]), 0)
|
||||
|
||||
menu = gtk.Menu()
|
||||
gl = gPodderLib()
|
||||
|
||||
( can_play, can_download, can_transfer, can_cancel ) = self.play_or_download()
|
||||
|
||||
|
@ -449,6 +488,15 @@ class gPodder(GladeWidget):
|
|||
item.set_image( gtk.image_new_from_stock( gtk.STOCK_SAVE_AS, gtk.ICON_SIZE_MENU))
|
||||
item.connect( 'activate', lambda w: self.save_episode_as_file( episode_url))
|
||||
menu.append( item)
|
||||
if gl.config.bluetooth_enabled:
|
||||
if gl.config.bluetooth_ask_always:
|
||||
bt_device_name = _('bluetooth device')
|
||||
else:
|
||||
bt_device_name = _('%s via bluetooth')%gl.config.bluetooth_device_name
|
||||
item = gtk.ImageMenuItem(_('Send to %s') % bt_device_name)
|
||||
item.set_image(gtk.image_new_from_icon_name('stock_bluetooth', gtk.ICON_SIZE_MENU))
|
||||
item.connect('activate', lambda w: self.copy_episode_bluetooth(episode_url))
|
||||
menu.append( item)
|
||||
menu.append( gtk.SeparatorMenuItem())
|
||||
else:
|
||||
episode_title = _('%d selected episodes') % len(paths)
|
||||
|
@ -1688,12 +1736,18 @@ class gPodderProperties(GladeWidget):
|
|||
gl.config.connect_gtk_togglebutton('disable_notifications', self.disable_notifications)
|
||||
gl.config.connect_gtk_togglebutton('start_iconified', self.start_iconified)
|
||||
gl.config.connect_gtk_togglebutton('on_quit_ask', self.on_quit_ask)
|
||||
gl.config.connect_gtk_togglebutton('bluetooth_enabled', self.bluetooth_enabled)
|
||||
gl.config.connect_gtk_togglebutton('bluetooth_ask_always', self.bluetooth_ask_always)
|
||||
gl.config.connect_gtk_togglebutton('bluetooth_ask_never', self.bluetooth_ask_never)
|
||||
gl.config.connect_gtk_togglebutton('bluetooth_use_converter', self.bluetooth_use_converter)
|
||||
gl.config.connect_gtk_filechooser( 'bluetooth_converter', self.bluetooth_converter, is_for_files=True)
|
||||
|
||||
self.entryCustomSyncName.set_sensitive( self.cbCustomSyncName.get_active())
|
||||
self.radio_copy_torrents.set_active( not self.radio_gnome_bittorrent.get_active())
|
||||
|
||||
self.iPodMountpoint.set_label( gl.config.ipod_mount)
|
||||
self.filesystemMountpoint.set_label( gl.config.mp3_player_folder)
|
||||
self.bluetooth_device_name.set_markup('<b>%s</b>'%gl.config.bluetooth_device_name)
|
||||
self.chooserDownloadTo.set_current_folder(gl.downloaddir)
|
||||
|
||||
if tagging_supported():
|
||||
|
@ -1732,6 +1786,20 @@ class gPodderProperties(GladeWidget):
|
|||
self.iPodMountpoint.set_label( '')
|
||||
else:
|
||||
self.iPodMountpoint.set_label( ipod.mount_point)
|
||||
|
||||
def on_bluetooth_select_device_clicked(self, widget):
|
||||
gl = gPodderLib()
|
||||
self.bluetooth_select_device.set_sensitive(False)
|
||||
gtk.main_iteration(False)
|
||||
for name, address in util.discover_bluetooth_devices():
|
||||
if self.show_confirmation('Use this device as your bluetooth device?', name):
|
||||
gl.config.bluetooth_device_name = name
|
||||
gl.config.bluetooth_device_address = address
|
||||
self.bluetooth_device_name.set_markup('<b>%s</b>'%gl.config.bluetooth_device_name)
|
||||
self.bluetooth_select_device.set_sensitive(True)
|
||||
return
|
||||
self.show_message('No more devices found', 'Scan finished')
|
||||
self.bluetooth_select_device.set_sensitive(True)
|
||||
|
||||
def set_uar(self, uar):
|
||||
self.comboAudioPlayerApp.set_model(uar.get_applications_as_model())
|
||||
|
|
|
@ -60,6 +60,7 @@ class gPodderLibClass( object):
|
|||
gpodder_dir = os.path.expanduser( '~/.config/gpodder/')
|
||||
util.make_directory( gpodder_dir)
|
||||
|
||||
self.tempdir = gpodder_dir
|
||||
self.feed_cache_file = os.path.join( gpodder_dir, 'feedcache.db')
|
||||
self.channel_settings_file = os.path.join( gpodder_dir, 'channelsettings.db')
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ import glob
|
|||
import stat
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import htmlentitydefs
|
||||
import time
|
||||
import locale
|
||||
|
@ -605,3 +606,62 @@ def idle_add(func, *args):
|
|||
else:
|
||||
func(*args)
|
||||
|
||||
|
||||
def discover_bluetooth_devices():
|
||||
"""
|
||||
This is a generator function that returns
|
||||
(address, name) tuples of all nearby bluetooth
|
||||
devices found.
|
||||
|
||||
If the user has python-bluez installed, it will
|
||||
be used. If not, we're trying to use "hcitool".
|
||||
|
||||
If neither python-bluez or hcitool are available,
|
||||
this function is the empty generator.
|
||||
"""
|
||||
try:
|
||||
# If the user has python-bluez installed
|
||||
import bluetooth
|
||||
log('Using python-bluez to find nearby bluetooth devices')
|
||||
for name, addr in bluetooth.discover_devices(lookup_names=True):
|
||||
yield (name, addr)
|
||||
except:
|
||||
if find_command('hcitool') is not None:
|
||||
log('Using hcitool to find nearby bluetooth devices')
|
||||
# If the user has "hcitool" installed
|
||||
p = subprocess.Popen(['hcitool', 'scan'], stdout=subprocess.PIPE)
|
||||
for line in p.stdout:
|
||||
match = re.match('^\t([^\t]+)\t([^\t]+)\n$', line)
|
||||
if match is not None:
|
||||
(addr, name) = match.groups()
|
||||
yield (name, addr)
|
||||
else:
|
||||
log('Cannot find either python-bluez or hcitool - no bluetooth?')
|
||||
return # <= empty generator
|
||||
|
||||
|
||||
def bluetooth_send_file(filename, device=None, callback_finished=None):
|
||||
"""
|
||||
Sends a file via bluetooth using gnome-obex send.
|
||||
Optional parameter device is the bluetooth address
|
||||
of the device; optional parameter callback_finished
|
||||
is a callback function that will be called when the
|
||||
sending process has finished - it gets one parameter
|
||||
that is either True (when sending succeeded) or False
|
||||
when there was some error.
|
||||
"""
|
||||
if find_command('gnome-obex-send'):
|
||||
command_line = ['gnome-obex-send']
|
||||
if device is not None:
|
||||
command_line += ['--dest', device]
|
||||
command_line.append(filename)
|
||||
result = (subprocess.Popen(command_line).wait() == 0)
|
||||
if callback_finished is not None:
|
||||
callback_finished(result)
|
||||
return result
|
||||
else:
|
||||
log('Cannot send file. Please install "gnome-obex-send".')
|
||||
if callback_finished is not None:
|
||||
callback_finished(False)
|
||||
return False
|
||||
|
||||
|
|
Loading…
Reference in New Issue