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 <crobinso@xxxxxxxxxx>" # 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/sound[@model='%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 et-mgmt-tools@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/et-mgmt-tools