The attached patch teaches virt-manager how to parse
sound device xml for virtual machines. Each separate
<sound model='blah'/> will show up as a separate
device in the VM details listing. The patch also
implements deleting these devices.
I put a screenshot up that should explain most of the
changes:
http://crobinso.fedorapeople.org/virt-manager/vmm-sound.png
Thanks,
Cole
# HG changeset patch
# User "Cole Robinson <[EMAIL PROTECTED]>"
# Date 1216848252 14400
# Node ID 8a86b6ed3a80104a0704fda2480b1a05d9ed4ca0
# Parent f4c491621a100ed8101622601a87c5dc978ceb47
Allow viewing and removing sound devices
diff -r f4c491621a10 -r 8a86b6ed3a80 src/virtManager/details.py
--- a/src/virtManager/details.py Wed Jul 23 16:23:56 2008 -0400
+++ b/src/virtManager/details.py Wed Jul 23 17:24:12 2008 -0400
@@ -55,6 +55,7 @@
HW_LIST_TYPE_NIC = 4
HW_LIST_TYPE_INPUT = 5
HW_LIST_TYPE_GRAPHICS = 6
+HW_LIST_TYPE_SOUND = 7
# Console pages
PAGE_UNAVAILABLE = 0
@@ -252,6 +253,7 @@
"on_config_network_remove_clicked": self.remove_network,
"on_config_input_remove_clicked": self.remove_input,
"on_config_graphics_remove_clicked": self.remove_graphics,
+ "on_config_sound_remove_clicked": self.remove_sound,
"on_add_hardware_button_clicked": self.add_hardware,
"on_details_menu_view_fullscreen_activate": self.toggle_fullscreen,
@@ -536,6 +538,8 @@
self.refresh_input_page()
elif pagetype == HW_LIST_TYPE_GRAPHICS:
self.refresh_graphics_page()
+ elif pagetype == HW_LIST_TYPE_SOUND:
+ self.refresh_sound_page()
elif pagetype == HW_LIST_TYPE_BOOT:
self.refresh_boot_page()
self.window.get_widget("config-boot-options-apply").set_sensitive(False)
@@ -720,6 +724,8 @@
self.refresh_input_page()
elif pagetype == HW_LIST_TYPE_GRAPHICS:
self.refresh_graphics_page()
+ elif pagetype == HW_LIST_TYPE_SOUND:
+ self.refresh_sound_page()
def refresh_summary(self):
self.window.get_widget("overview-cpu-usage-text").set_text("%d %%" %
self.vm.cpu_time_percentage())
@@ -889,6 +895,21 @@
self.window.get_widget("config-input-remove").set_sensitive(False)
else:
self.window.get_widget("config-input-remove").set_sensitive(True)
+
+ def refresh_sound_page(self):
+ vmlist = self.window.get_widget("hw-list")
+ selection = vmlist.get_selection()
+ active = selection.get_selected()
+ if active[1] is None:
+ return
+ sound = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
+ self.window.get_widget("sound-model").set_text(sound[3])
+
+ # Can't remove sound dev from live guest
+ if self.vm.is_active():
+ self.window.get_widget("config-sound-remove").set_sensitive(False)
+ else:
+ self.window.get_widget("config-sound-remove").set_sensitive(True)
def refresh_boot_page(self):
# Refresh autostart
@@ -1296,6 +1317,18 @@
self.remove_device(xml)
self.refresh_resources()
+ def remove_sound(self, src):
+ vmlist = self.window.get_widget("hw-list")
+ selection = vmlist.get_selection()
+ active = selection.get_selected()
+ if active[1] is None:
+ return
+ sound = active[0].get_value(active[1], HW_LIST_COL_DEVICE)
+
+ xml = "<sound model='%s'/>" % sound[3]
+ self.remove_device(xml)
+ self.refresh_resources()
+
def prepare_hw_list(self):
hw_list_model = gtk.ListStore(str, str, int, gtk.gdk.Pixbuf, int,
gobject.TYPE_PYOBJECT)
self.window.get_widget("hw-list").set_model(hw_list_model)
@@ -1426,6 +1459,25 @@
if missing:
hw_list_model.insert(insertAt, [_("Display"),
gtk.STOCK_SELECT_COLOR, gtk.ICON_SIZE_LARGE_TOOLBAR, None,
HW_LIST_TYPE_GRAPHICS, graphic])
+ # Populate list of sound devices
+ currentSounds = {}
+ for sound in self.vm.get_sound_devices():
+ missing = True
+ insertAt = 0
+ currentSounds[sound[3]] = 1
+ for row in hw_list_model:
+ if row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_SOUND and \
+ row[HW_LIST_COL_DEVICE][3] == sound[3]:
+ # Update metadata
+ row[HW_LIST_COL_DEVICE] = sound
+ missing = False
+
+ if row[HW_LIST_COL_TYPE] <= HW_LIST_TYPE_SOUND:
+ insertAt = insertAt + 1
+ # Add in row
+ if missing:
+ hw_list_model.insert(insertAt, [_("Sound: %s" % sound[3]),
gtk.STOCK_MEDIA_PLAY, gtk.ICON_SIZE_LARGE_TOOLBAR, None, HW_LIST_TYPE_SOUND,
sound])
+
# Now remove any no longer current devs
devs = range(len(hw_list_model))
devs.reverse()
@@ -1441,6 +1493,9 @@
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_INPUT and not
currentInputs.has_key(row[HW_LIST_COL_DEVICE][3]):
removeIt = True
elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_GRAPHICS and not
currentGraphics.has_key(row[HW_LIST_COL_DEVICE][3]):
+ removeIt = True
+ elif row[HW_LIST_COL_TYPE] == HW_LIST_TYPE_SOUND and not \
+ currentSounds.has_key(row[HW_LIST_COL_DEVICE][3]):
removeIt = True
if removeIt:
diff -r f4c491621a10 -r 8a86b6ed3a80 src/virtManager/domain.py
--- a/src/virtManager/domain.py Wed Jul 23 16:23:56 2008 -0400
+++ b/src/virtManager/domain.py Wed Jul 23 17:24:12 2008 -0400
@@ -692,6 +692,16 @@
return self._parse_device_xml(_parse_graphics_devs)
+ def get_sound_devices(self):
+ def _parse_sound_devs(ctx):
+ sound = []
+ ret = ctx.xpathEval("/domain/devices/sound")
+ for node in ret:
+ sound.append([None, None, None, node.prop("model")])
+ return sound
+
+ return self._parse_device_xml(_parse_sound_devs)
+
def _parse_device_xml(self, parse_function):
doc = None
ctx = None
@@ -808,6 +818,22 @@
logging.debug("Redefine with " + newxml)
self.get_connection().define_domain(newxml)
+ elif dev_type == "sound":
+ model = dev_ctx.xpathEval("/sound/@model")
+ if len(model) > 0 and model[0].content != None:
+ logging.debug("Looking for type %s" % model[0].content)
+ ret = ctx.xpathEval("/domain/devices/[EMAIL
PROTECTED]'%s']" % model[0].content)
+ if len(ret) > 0:
+ ret[0].unlinkNode()
+ ret[0].freeNode()
+ newxml=doc.serialize()
+ logging.debug("Redefine with " + newxml)
+ self.get_connection().define_domain(newxml)
+
+ else:
+ raise RuntimeError, _("Unknown device type '%s'" %
+ dev_type)
+
finally:
if ctx != None:
ctx.xpathFreeContext()
diff -r f4c491621a10 -r 8a86b6ed3a80 src/vmm-details.glade
--- a/src/vmm-details.glade Wed Jul 23 16:23:56 2008 -0400
+++ b/src/vmm-details.glade Wed Jul 23 17:24:12 2008 -0400
@@ -4476,6 +4476,188 @@
<property name="type">tab</property>
</packing>
</child>
+
+ <child>
+ <widget class="GtkVBox" id="vbox58">
+ <property name="visible">True</property>
+ <property name="homogeneous">False</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkFrame" id="frame13">
+ <property name="visible">True</property>
+ <property name="label_xalign">0</property>
+ <property name="label_yalign">0.5</property>
+ <property
name="shadow_type">GTK_SHADOW_NONE</property>
+
+ <child>
+ <widget class="GtkAlignment" id="alignment159">
+ <property name="visible">True</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="xscale">1</property>
+ <property name="yscale">1</property>
+ <property name="top_padding">5</property>
+ <property name="bottom_padding">3</property>
+ <property name="left_padding">12</property>
+ <property name="right_padding">0</property>
+
+ <child>
+ <widget class="GtkTable" id="table36">
+ <property name="border_width">3</property>
+ <property name="visible">True</property>
+ <property name="n_rows">1</property>
+ <property name="n_columns">2</property>
+ <property name="homogeneous">False</property>
+ <property name="row_spacing">3</property>
+ <property name="column_spacing">3</property>
+
+ <child>
+ <widget class="GtkLabel" id="label452">
+ <property name="visible">True</property>
+ <property name="label"
translatable="yes">Device Model:</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</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">1</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="GtkLabel" id="sound-model">
+ <property name="visible">True</property>
+ <property name="label"
translatable="yes">insert sound model</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</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">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">0</property>
+ <property
name="bottom_attach">1</property>
+ <property name="y_padding">1</property>
+ <property name="x_options">fill</property>
+ <property name="y_options"></property>
+ </packing>
+ </child>
+ </widget>
+ </child>
+ </widget>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label451">
+ <property name="visible">True</property>
+ <property name="label"
translatable="yes"><b>Sound Device</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.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="type">label_item</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">15</property>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkHButtonBox" id="hbuttonbox14">
+ <property name="border_width">6</property>
+ <property name="visible">True</property>
+ <property
name="layout_style">GTK_BUTTONBOX_END</property>
+ <property name="spacing">0</property>
+
+ <child>
+ <widget class="GtkButton" id="config-sound-remove">
+ <property name="visible">True</property>
+ <property name="can_default">True</property>
+ <property name="can_focus">True</property>
+ <property name="label">gtk-remove</property>
+ <property name="use_stock">True</property>
+ <property
name="relief">GTK_RELIEF_NORMAL</property>
+ <property name="focus_on_click">True</property>
+ <signal name="clicked"
handler="on_config_sound_remove_clicked" last_modification_time="Wed, 23 Jul
2008 21:17:37 GMT"/>
+ </widget>
+ </child>
+ </widget>
+ <packing>
+ <property name="padding">0</property>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ </packing>
+ </child>
+ </widget>
+ <packing>
+ <property name="tab_expand">False</property>
+ <property name="tab_fill">True</property>
+ </packing>
+ </child>
+
+ <child>
+ <widget class="GtkLabel" id="label440">
+ <property name="visible">True</property>
+ <property name="label" translatable="yes">Sound</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="type">tab</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="shrink">True</property>
_______________________________________________
et-mgmt-tools mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/et-mgmt-tools