summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pitt <martinpitt@gnome.org>2013-07-23 08:59:42 +0200
committerMartin Pitt <martinpitt@gnome.org>2013-07-23 08:59:42 +0200
commit66352821de3e5101da4adc925ec88ea151590e32 (patch)
tree3659bfa949d49288d470d289547df2010501c29b
parentd83dd01a0a1df6198ee08954da1c033b88a1004b (diff)
Drop obsolete fdi2mpi.py
hal and hal-fdi haven't been maintained in years, so this script is dead.
-rw-r--r--tools/Makefile.am2
-rwxr-xr-xtools/fdi2mpi.py343
2 files changed, 1 insertions, 344 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am
index a29bd80..d9a0da5 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1 +1 @@
-EXTRA_DIST = COPYING fdi2mpi.py mpi2udev.py mpi2hwdb.py udev-syntax-check.py
+EXTRA_DIST = COPYING mpi2udev.py mpi2hwdb.py udev-syntax-check.py
diff --git a/tools/fdi2mpi.py b/tools/fdi2mpi.py
deleted file mode 100755
index b5de76e..0000000
--- a/tools/fdi2mpi.py
+++ /dev/null
@@ -1,343 +0,0 @@
-#!/usr/bin/python
-# Convert hal's USB music player FDIs into media player information (.mpi)
-# property files.
-#
-# (C) 2009 Canonical Ltd.
-# Author: Martin Pitt <martin.pitt@ubuntu.com>
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software Foundation,
-# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-#
-#
-# Alternatively this script can be distributed under the X11 license:
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is fur-
-# nished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
-# NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
-# NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-import sys, os.path, xml.dom.minidom
-
-# translation of hal match keys to mpi attribute names
-_hal_match2mpi = {
- '@storage.originating_device:usb.vendor_id': 'VendorID',
- '@storage.physical_device:usb.vendor_id': 'VendorID',
- '@storage.originating_device:usb.product_id': 'ProductID',
- '@storage.physical_device:usb.product_id': 'ProductID',
- '@storage.originating_device:@info.parent:usb_device.product': 'USBModel',
- 'storage.vendor': 'USBVendor',
- 'storage.model': 'USBModel',
-
- # if we actually want/need to check for subdevices, we can do:
- #'storage.lun': 'KERNELS=="*:*:*:%s"', # host:bus:target:lun
- # ... but let's ignore it for now:
- 'storage.lun': None,
-
- # the following are globally checked by rule header, ignore them
- '@storage.originating_device:info.subsystem': None,
- 'info.category': None,
-}
-
-_hal_prop2mpi = {
- 'portable_audio_player.access_method.protocols': ('Device', 'AccessProtocol'),
- 'portable_audio_player.access_method': ('Device', 'AccessProtocol'),
- 'portable_audio_player.output_formats': ('Media', 'OutputFormats'),
- 'portable_audio_player.input_formats': ('Media', 'InputFormats'),
- 'portable_audio_player.audio_folders': ('storage', 'AudioFolders'),
- 'portable_audio_player.folder_depth': ('storage', 'FolderDepth'),
- 'portable_audio_player.playlist_path': ('storage', 'PlaylistPath'),
- 'portable_audio_player.playlist_format': ('Playlist', 'Formats'),
- 'portable_audio_player.playlist_formats': ('Playlist', 'Formats'),
- 'storage.requires_eject': ('storage', 'RequiresEject'),
- 'storage.model': ('Device', 'Model'),
- 'storage.vendor': ('Device', 'Vendor'),
- 'storage.drive_type': ('storage', 'DriveType'),
-
- # all of those are "portable audio player"
- 'info.capabilities': (None, None),
-
- # not useful; if we need the device, we should set up a general rule to
- # slam it into the udev db
- 'portable_audio_player.storage_device': (None, None),
-}
-
-def match_op2glob(node):
- '''Convert FDI match operator to a glob.
-
- Return glob
- '''
- if node.attributes.has_key('string'):
- return node.attributes['string'].nodeValue
-
- if node.attributes.has_key('contains'):
- return '*' + node.attributes['contains'].nodeValue + '*'
-
- if node.attributes.has_key('int'):
- v = node.attributes['int'].nodeValue
- if v != '1':
- v = '%04x' % int(v, 0)
- return v
-
- if node.attributes.has_key('int_outof'):
- alternatives = node.attributes['int_outof'].nodeValue.split(';')
- hex_alternatives = []
- for a in alternatives:
- hex_alternatives.append('%04x' % int(a, 0))
- return hex_alternatives
-
- if node.attributes.has_key('contains_ncase'):
- v = node.attributes['contains_ncase'].nodeValue
- nocase_glob = ''.join(['[%s%s]' % (c.lower(), c.upper()) for c in v])
- return '*' + nocase_glob + '*'
-
- if node.attributes.has_key('prefix_ncase'):
- v = node.attributes['prefix_ncase'].nodeValue
- nocase_glob = ''.join(['[%s%s]' % (c.lower(), c.upper()) for c in v])
- return nocase_glob + '*'
-
- raise NotImplementedError, 'unknown string operator ' + str(node.attributes.keys())
-
-def get_node_comment(node):
- '''Return comment before a node.'''
-
- while True:
- node = node.previousSibling
- if not node:
- break
- if node.nodeType == xml.dom.Node.COMMENT_NODE:
- lines = [l.strip() for l in node.nodeValue.splitlines()]
- return ' '.join(lines)
- if node.nodeType != xml.dom.Node.TEXT_NODE:
- break
- return None
-
-def collect_attributes(node, attrs):
- '''Add media player attributes to attrs.'''
-
- for n in node.childNodes:
- if n.nodeType != xml.dom.minidom.Node.ELEMENT_NODE:
- continue
- if n.tagName == 'match':
- continue
- assert n.tagName in ('addset', 'merge', 'append')
-
- (cat, prop) = _hal_prop2mpi[n.attributes['key'].nodeValue]
- if cat is None:
- continue
- content_node = n.childNodes[0]
- assert content_node.nodeType == xml.dom.Node.TEXT_NODE
-
- attrs.setdefault(cat, {}).setdefault(prop, []).append(content_node.nodeValue.strip())
-
-def mkfilename(attrs, current_vendor):
- '''Return an appropriate mpi file name for attributes.'''
-
- v = None
- if 'VendorID' in attrs.get('Device', {}):
- v = attrs['Device']['VendorID']
- if 'USBVendor' in attrs.get('Device', {}):
- v = attrs['Device']['USBVendor']
- if current_vendor:
- v = current_vendor.split()[0].split('/')[0].replace(',', '').lower().strip()
- assert v
-
- m = None
- if 'ProductID' in attrs.get('Device', {}):
- m = attrs['Device']['ProductID']
- if 'USBModel' in attrs.get('Device', {}):
- m = attrs['Device']['USBModel']
- # if we only have a single product ID, attempt to get nicer name
- if len(attrs['Device'].get('ProductID', [''])) <= 1 and \
- 'Product' in attrs.get('Device', {}) and \
- '/' not in attrs['Device']['Product']:
- m = attrs['Device']['Product']
- if 'Model' in attrs.get('Device', {}):
- m = attrs['Device']['Model'][0]
-
- if type(m) == type([]):
- m = '_'.join(m)
- m = m.replace(' ', '_').replace(';', '_').replace('*', '').replace('(',
- '').replace(')', '').lower()
- assert m
-
- assert '*' not in m, m
- assert '[' not in m, m
- assert ';' not in m, m
- assert '(' not in m, m
- assert ')' not in m, m
- assert ' ' not in m, m
-
- # a lot of product names start with vendor name
- if m.startswith(v):
- m = m[len(v):]
- if m.startswith('_'):
- m = m[1:]
-
- print attrs['Device'], '->', '"%s-%s"' % (v, m)
-
- return '%s-%s' % (v, m)
-
-def usb_ids_to_device_match(attrs):
- '''convert the USB IDs we gathered to a DeviceMatch string appropriate
- for mpi files'''
-
- if not 'VendorID' in attrs['Device'].keys():
- return
-
- if not 'ProductID' in attrs['Device'].keys():
- attrs['Device']['ProductID'] = [ '*' ]
-
- device_match = ''
- for id in attrs['Device']['ProductID']:
- device_match += 'usb:'+ attrs['Device']['VendorID'][0] + ':' + id + ';'
-
- attrs['Device']['DeviceMatch'] = device_match
- del attrs['Device']['VendorID']
- del attrs['Device']['ProductID']
-
-
-def write_mpi(attrs, filename):
- '''Write mpi file for attrs.'''
-
- # define order of sections
- sections = ['Device', 'Media', 'Playlist', 'storage']
-
- # a lot of product names start with vendor name
- if attrs['Device'].has_key('Vendor') and attrs['Device'].has_key('Product'):
- product = attrs['Device']['Product']
- vendor = attrs['Device']['Vendor']
- if product.startswith(vendor):
- attrs['Device']['Product'] = product[len(vendor):].strip()
-
- usb_ids_to_device_match(attrs)
-
- # only keep the most specific model name
- if attrs['Device'].has_key('Model'):
- attrs['Device']['Model'] = attrs['Device']['Model'][0]
-
- assert set(attrs.keys()) <= set(sections)
-
- f = open(os.path.join('media-players', filename + '.mpi'), 'w')
-
- for section in sections:
- if section not in attrs:
- continue
- print >> f, '[%s]' % section
- for k, v in attrs[section].iteritems():
- if type(v) == type([]):
- v = ';'.join(v)
- print >> f, '%s=%s' % (k, v)
- print >> f
-
- f.close()
-
-def parse_leaf_match(node, current_vendor, current_model):
- '''Parse leaf match.
-
- Construct udev matches from all parent matches and then write property mpi
- file from all attached properties.
- '''
- # this is from the "Set common keys for detected audio player" section,
- # which we want to ignore
- if node.attributes['key'].nodeValue == 'portable_audio_player.access_method.protocols':
- return
-
- attrs = {'Media': {'OutputFormats': ['audio/mpeg']}}
-
- n = node
- while n:
- collect_attributes(n, attrs)
-
- key = n.attributes['key'].nodeValue
- device_attr = _hal_match2mpi[key]
- if device_attr:
- glb = match_op2glob(n)
- if type(glb) == type([]):
- attrs.setdefault('Device', {}).setdefault(device_attr, []).extend(glb)
- else:
- attrs.setdefault('Device', {}).setdefault(device_attr, []).append(glb)
- while True:
- n = n.parentNode
- if n is None or (n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE and
- n.tagName == 'match'):
- break
-
- if current_model:
- attrs.setdefault('Device', {})['Product'] = current_model
- if current_vendor:
- attrs.setdefault('Device', {})['Vendor'] = current_vendor
-
- fname = mkfilename(attrs, current_vendor)
- write_mpi(attrs, fname)
-
-def parse_fdi(fdi):
- '''Parse music player fdi node.'''
-
- current_vendor = None
-
- # find all <match> leaf nodes
- for match_node in fdi.getElementsByTagName('match'):
- current_model = None
-
- c = get_node_comment(match_node)
-
- # filter out a few weird cases in current hal-info
- if c and ('No-name' in c or 'require' in c or 'media files' in c):
- c = None
- if c and ('TODO' in c):
- c = 'Apple'
- if c and ('MegaScreen' in c):
- c = 'Nexia'
- if c and ('PSP' in c):
- c = 'Sony'
-
- if c:
- match_key = match_node.attributes['key'].nodeValue
- if 'model' in match_key or 'product' in match_key:
- current_model = c
- elif 'vendor' in match_key:
- current_vendor = c
- else:
- if 'subsystem' in match_key or 'protocols' in match_key or 'category' in match_key:
- pass
- else:
- raise NotImplementedError, 'do not know how to interpret comment ' + c
-
- children = set([n.tagName for n in match_node.childNodes
- if n.nodeType == xml.dom.minidom.Node.ELEMENT_NODE])
-
- if u'match' in children:
- continue
-
- parse_leaf_match(match_node, current_vendor, current_model)
-
-#
-# main
-#
-
-for f in sys.argv[1:]:
- parse_fdi(xml.dom.minidom.parse(f))