Gtk.Vte and feed_child: command sent two time - python

i'm building a tabbed python terminal to manage multiple ssh connection (like superputty or putty manager on windows), so i use feed_child to send command to terminal, but there is a little problem: the command is written 2 time in the terminal, on time before everything.. code is better:
I use this to send the command (in this case for example the command is uptime)
if self.command != "":
self.length_command = len(self.command) + 1
self.hbox.term.feed_child(self.command + "\n", self.length_command)
but in the terminal i get this result
uptime
maurelio#myhost1 ~ $ uptime
19:04:18 up 15 days, 14:32, 2 users, load average: 0,04, 0,07, 0,14
maurelio#myhost1
As you can see, uptime appears in terminal like normal text when i start the program or open a new tab, then appear the prompt and the command is correctly executed. i'd like to get just this:
maurelio#myhost1 ~ $ uptime
19:04:18 up 15 days, 14:32, 2 users, load average: 0,04, 0,07, 0,14
maurelio#myhost1
Any idea?
Update
Here there is a complete code (that should works) :-)
#!/usr/bin/env python
# -*- coding: utf-8; -*-
from gi.repository import Gtk, Vte, GLib
import os
class Terminal(Vte.Terminal):
"""Just create a standard terminal with some configuration
"""
def __init__(self):
super(Terminal, self).__init__()
self.configure_terminal()
def configure_terminal(self):
self.set_audible_bell(False)
self.set_visible_bell(False)
self.set_sensitive(True)
self.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/bash"],
[], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
class Window(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Terminal")
self.box = Gtk.Box(spacing=6)
self.add(self.box)
self.term = Terminal()
self.box.pack_start(self.term, True, True, 0)
self.term.set_audible_bell(False)
self.term.set_visible_bell(False)
self.term.set_sensitive(True)
self.term.fork_command_full(Vte.PtyFlags.DEFAULT, os.environ['HOME'], ["/bin/bash"],
[], GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, None)
self.command = 'uptime'
self.length_command = len(self.command) + 1
self.term.feed_child(self.command + "\n", self.length_command)
self.term.connect("child-exited", Gtk.main_quit)
win = Window()
win.connect("delete-event", Gtk.main_quit)
win.show_all()
Gtk.main()
If you run this, you will see the problem.
Thanks.

You forgot to add the Vte terminal to a ScrolledWindow first:
Gtk.Window.__init__(self, title="Terminal")
self.set_default_size(600, 300)
self.box = Gtk.Box(spacing=6)
self.add(self.box)
self.term = Terminal()
self.sw = Gtk.ScrolledWindow()
self.sw.add(self.term)
self.box.pack_start(self.sw, True, True, 0)

Related

python gtk.entry() icon connect: is it possible?

I'm using in Pygtk 2.7 a gtk.Entry. I have set an Icon on this, I would like to know if it's possible to connect the icon to a fonction.
My construction is like this:
def info(self, a, b):
print "INFOS & HELP"
def __init__(self):
window = gtk.window(gtk.WINDOW_TOPLEVEL)
#[...]
self.champ_adr_canal = gtk.Entry()
self.champ_adr_canal.connect("activate", self.download, self.champ_adr_canal)
self.champ_adr_canal.set_text("")
boite_adr.pack_start(self.champ_adr_canal, False, True, 0)
self.champ_adr_canal.set_icon_from_stock(1, gtk.STOCK_DIALOG_QUESTION) # the icon is here
### this line is a pseudo code ####
self.champ_adr_canal.connect("clicked", self.info, "bouton info") # how can I do this?
### ####
self.champ_adr_canal.show()
Thanks!
According to the documentation, you need to make the icon activatable and connect to the icon-press or icon-release signal:
self.champ_adr_canal.set_icon_activatable(1, True)
self.champ_adr_canal.connect("icon-release", self.info)

Gtk 3, python, appindicator, disable icon near label

I write openweathermap site appindicator in python, but i need only text label in indicator without icon. But when i leave "" then show me empty icon. Why, i need only text. In Ubuntu 12.04 python-appindicator don't need a icon if leave "" then not load a empty icon, but in ubuntu 14.04 leave empty icon. How to disable the icon?? Any ideas?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import urllib2
import json
import time
import datetime
from gi.repository import Gtk, Gdk, GLib, GObject
from gi.repository import AppIndicator3 as appindicator
class programa:
def __init__(self):
# Create Indicator with icon and label
# If leave empty "" then load empty icon
self.ind = appindicator.Indicator.new("Weather","",appindicator.IndicatorCategory.APPLICATION_STATUS)
self.ind.set_status(appindicator.IndicatorStatus.ACTIVE) #
self.menu_structure()
# Menu structure
def menu_structure(self):
refresh = 720 # Refresh interval in seconds
url = urllib2.Request('http://api.openweathermap.org/data/2.5/weather?q=siauliai&units=metric')
openup = urllib2.urlopen(url) # open url
json_string = openup.read() #read data
parsed_json = json.loads(json_string)
# Get data
temp = parsed_json['main']['temp'] # Temperature in metric system
wind = parsed_json['wind']['speed'] # Wind speed
humidity = parsed_json['main']['humidity']
clouds = parsed_json['clouds']['all']
weather = parsed_json['weather'][0]['main']
weather_desc = parsed_json['weather'][0]['description']
update_time = parsed_json['dt']
updated = datetime.datetime.fromtimestamp(int(update_time)).strftime('%H:%M')
# GTK menu
self.menu = Gtk.Menu()
self.menu_updated = Gtk.MenuItem("Updatet: "+updated)
self.menu_weather = Gtk.MenuItem("Weather: "+weather)
self.menu_desc = Gtk.MenuItem("Desc: "+weather_desc)
self.menu_clouds = Gtk.MenuItem("Clouds: "+str(clouds)+"%")
self.menu_humidity = Gtk.MenuItem("Humidity: "+str(humidity)+"%")
self.menu_wind = Gtk.MenuItem("Wind: "+str(wind)+" m/s")
self.separator = Gtk.SeparatorMenuItem()
self.exit = Gtk.MenuItem("Exit")
self.exit.connect("activate", self.quit)
#show menu
self.menu_updated.show()
self.menu_weather.show()
self.menu_desc.show()
self.menu_clouds.show()
self.menu_humidity.show()
self.menu_wind.show()
self.separator.show()
self.exit.show()
# Append menu
self.menu.append(self.menu_updated)
self.menu.append(self.menu_weather)
self.menu.append(self.menu_desc)
self.menu.append(self.menu_clouds)
self.menu.append(self.menu_humidity)
self.menu.append(self.menu_wind)
self.menu.append(self.separator)
self.menu.append(self.exit)
self.ind.set_menu(self.menu)
# Set label in celcius temperature
self.ind.set_label(str(temp)+u"\u2103".encode('utf-8'),"")
# close url
openup.close()
# Refresh indicator
GLib.timeout_add_seconds(refresh,self.menu_structure)
def quit(self, widget):
sys.exit(0)
if __name__ == "__main__":
indicator = programa()
Gtk.main()
The only way I've found is to either use your own thin invisible icon or to use a thin and subtle existing ubuntu png such as /usr/share/unity/icons/panel-shadow.png or you could implement a little of both:
icon_image = os.path.dirname(__file__) + "/my_thin_inv_icon.png"
if not os.path.isfile(icon_image):
icon_image = "/usr/share/unity/icons/panel-shadow.png"
self.ind = appindicator.Indicator.new("Weather",icon_image,appindicator.IndicatorCategory.APPLICATION_STATUS)

Printing a calendar via Python. Code is not working =/

I am making a small program in Python (PyGTK) that prints out a calendar (Gregorian) for a year the user inputs.
Here is my code:
#!/usr/bin/env python
import pygtk, gtk, subprocess
pygtk.require("2.0")
class Base:
def printing(self, widget):
text = self.textbox.get_text()
printingit = "cal -y %s | lpr" % (text)
process = subprocess.Popen(printingit.split(), stdout=subprocess.PIPE)
output = process.communicate()[0]
def __init__(self):
self.win = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.win.set_position(gtk.WIN_POS_CENTER)
self.win.set_size_request(350, 200)
self.win.set_resizable(False)
self.win.set_title("Calendar")
self.win.connect('destroy',lambda w: gtk.main_quit())
self.textbox = gtk.Entry()
self.textbox.set_size_request(70, 30)
self.lable = gtk.Label("Year:")
self.button = gtk.Button("Print")
self.button.set_size_request(60, 45)
self.button.connect("clicked", self.printing)
box = gtk.Fixed()
box.put(self.lable, 160, 25)
box.put(self.textbox, 140, 40)
box.put(self.button, 145, 100)
self.win.add(box)
self.win.show_all()
def main(self):
gtk.main()
if __name__ == "__main__":
base = Base()
base.main()
It's not working when actually printing the command cal -y %s | lpr % (text). I have made it so it replaces the textbox's text with the final command it should get and it changes to what I want it to be cal -y 2015 | lpr. I tried just putting that into terminal and it worked as usual, it's confusing me a lot!
I ran the program in terminal and this is the message I recieve when it tries to print:
Usage: cal [general options] [-hjy] [[month] year]
cal [general options] [-hj] [-m month] [year]
ncal [general options] [-bhJjpwySM] [-s country_code] [[month] year]
ncal [general options] [-bhJeoSM] [year]
General options: [-NC3] [-A months] [-B months]
For debug the highlighting: [-H yyyy-mm-dd] [-d yyyy-mm]
If anyone understands why this is happening I would be extremely grateful! Thank you in advance =D
Harry
If you want to use shell syntax (pipe) in your command, you need to pass the command as as string to the Popen constructor, not as list. And you must use shell=True:
output = subprocess.check_output(printingit, shell=True)
Without that, the executed command would be the same as:
cal '-y' 'text' '|' 'lpr'
But as you're getting part of the input from a text field, you shouldn't directly pass it tho a shell.
Alternatively, you can create the pipe yourself:
lpr = subprocess.Popen('lpr', stdin=subprocess.PIPE, stdout=subprocess.PIPE)
process = subprocess.Popen(['cal', '-y', text], stdout=lpr.stdin)
output = lpr.communicate()
process.wait()
By the way, instead of using subprocess to invoke cal you could use the calendar module. cal -y 2012 does the same as calendar.calendar(2014), so you could replace your code with:
cal = calendar.calendar(int(text))
process = subprocess.Popen(['lpr'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
output = process.communicate(cal) # cal.encode(locale.getpreferredencoding(False)) for python3

Output of youtube-dl using QProcess

I am so new to python and am in process of learning this powerful language. I managed to write the following script. It does get a partial output ( only two lines of it ) the I don't know what is going wrong! Please help me.
#!/usr/bin/env python
#-*- coding: utf-8 -*-
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import (QProcess,QRect,SIGNAL,SLOT,QString,QStringList,qDebug)
from PyQt4.QtGui import (QMainWindow,QWidget,QPushButton,QTextEdit,QApplication)
class YTDL (QtGui.QMainWindow):
def __init__ (self,parent=None):
super(YTDL,self).__init__(parent)
self.resize(400,300)
self.setWindowTitle("Youtube-dl output using QProcess")
self.__init_Components()
self.__ui_event_handler()
def __init_Components(self):
self.proc = QProcess()
self.cw = QWidget(self)
self.btn = QPushButton(self.cw)
self.btn.setText("Run")
self.btn.setGeometry(QRect(270,10,110,27))
self.te = QTextEdit(self.cw)
self.te.setReadOnly(True)
self.te.setOverwriteMode(False)
self.te.setGeometry(QRect(10,40,380,170))
self.setCentralWidget(self.cw)
def __ui_event_handler(self):
self.connect(self.btn, SIGNAL('clicked()'),self.Button_Clicked)
def Button_Clicked(self):
args = '-ct -f 18 --extract-audio --audio-quality 320k --audio-format mp3 -k http://www.youtube.com/watch?v=OiPO_TAAZPc'
cmd = 'youtube-dl'
self.proc.setWorkingDirectory("~/Videos/Folder1")
self.connect(self.proc, SIGNAL('readyRead()'),self._read)
self.proc.setOpenMode(self.proc.ReadWrite)
self.proc.start(cmd ,args)
if not self.proc.waitForStarted():
exit(1)
def _read(self):
s = self.proc.readAllStandardOutput()
qDebug (s)
print (s)
self.te.append(QString(s))
def main():
import sys
app = QApplication(sys.argv)
ytdl = YTDL()
ytdl.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
I think I figured it out myself. Here is an all improved version below. If there is something I need to improve upon, I will welcome any recommendations.
class YTDL (QtGui.QMainWindow):
def init (self,parent=None):
super(YTDL,self).init(parent)
self.resize(400,350)
self.setWindowTitle("Youtube-dl output using QProcess")
self.__init_Components()
self.__ui_event_handler()
def __init_Components(self):
self.proc = QProcess()
self.cw = QWidget(self)
self.btn = QPushButton(self.cw)
self.btn.setText("Run")
self.btn.setGeometry(QRect(270,10,110,27))
self.te = QTextEdit(self.cw)
self.te.setReadOnly(True)
self.te.setOverwriteMode(False)
self.te.setGeometry(QRect(10,40,380,170))
self.progbar = QProgressBar(self.cw)
self.progbar.setGeometry(QRect(10,220,380,18))
self.progbar.setRange(0,100)
self.progbar.setValue(0)
self.progbar.show()
self.setCentralWidget(self.cw)
def __ui_event_handler(self):
self.connect(self.btn, SIGNAL('clicked()'),self.Button_Clicked)
self.connect(self.proc, SIGNAL('readyReadStandardOutput()'),self._read)
self.connect(self.proc, SIGNAL('readyReadStandardError()'),self._readError)
def Button_Clicked(self):
args = "-ct -f 18 --extract-audio --audio-quality 320k --audio-format mp3 -k http://www.youtube.com/watch?v=SjUrib_Gh0Y"
cmd = "youtube-dl"
cmd = cmd + " " + args
print (cmd)
self.proc.setWorkingDirectory("~/Videos/Folder1")
self.proc.setOpenMode(self.proc.ReadWrite)
self.proc.start(cmd)
self.proc.waitForStarted()
def _read(self):
s = str(self.proc.readAllStandardOutput())
download_progress_exp = re.compile(r'.\d+\.\d+\%', re.MULTILINE)
progbarresult = download_progress_exp.findall(s)
i = 0
if progbarresult != []:
for i in range(0,len(progbarresult)):
self.progbar.setValue(float(progbarresult[i].strip("%")))
self.te.append(QString(s))
def _readError(self):
self.te.append(str(self.proc.readAllStandardError()))

gstreamer appsrc works for xvimagesink but no in theoraenc ! oggmux

I am trying to stream cast a computer generated video using gstreamer and icecast, but I cannot get gstreamer appsrc to work. My app works as expected if I use xvimagesink as the sink(see commented code below). But once I pipe it to theoraenc it does not run.
I exchanged shout2send with filesink to check if the problem was icecast, the result is that no data is written to the file. Substituting appsrc with testvideosrc works as expected. Any suggestion?
#!/usr/bin/env python
import sys, os, pygtk, gtk, gobject
import pygst
pygst.require("0.10")
import gst
import numpy as np
class GTK_Main:
def __init__(self):
window = gtk.Window(gtk.WINDOW_TOPLEVEL)
window.connect("destroy", gtk.main_quit, "WM destroy")
vbox = gtk.VBox()
window.add(vbox)
self.button = gtk.Button("Start")
self.button.connect("clicked", self.start_stop)
vbox.add(self.button)
window.show_all()
self.player = gst.Pipeline("player")
source = gst.element_factory_make("appsrc", "source")
caps = gst.Caps("video/x-raw-gray,bpp=16,endianness=1234,width=320,height=240,framerate=(fraction)10/1")
source.set_property('caps',caps)
source.set_property('blocksize',320*240*2)
source.connect('need-data', self.needdata)
colorspace = gst.element_factory_make('ffmpegcolorspace')
enc = gst.element_factory_make('theoraenc')
mux = gst.element_factory_make('oggmux')
shout = gst.element_factory_make('shout2send')
shout.set_property("ip","localhost")
shout.set_property("password","hackme")
shout.set_property("mount","/stream")
caps = gst.Caps("video/x-raw-yuv,width=320,height=240,framerate=(fraction)10/1,format=(fourcc)I420")
enc.caps = caps
videosink = gst.element_factory_make('xvimagesink')
videosink.caps = caps
self.player.add(source, colorspace, enc, mux, shout)
gst.element_link_many(source, colorspace, enc, mux, shout)
#self.player.add(source, colorspace, videosink)
#gst.element_link_many(source, colorspace, videosink)
def start_stop(self, w):
if self.button.get_label() == "Start":
self.button.set_label("Stop")
self.player.set_state(gst.STATE_PLAYING)
else:
self.player.set_state(gst.STATE_NULL)
self.button.set_label("Start")
def needdata(self, src, length):
bytes = np.int16(np.random.rand(length/2)*30000).data
src.emit('push-buffer', gst.Buffer(bytes))
GTK_Main()
gtk.gdk.threads_init()
gtk.main()
I think that your problem is most likely to do with timestamping of the buffers. I've done some quick testing, using that code and replacing the shout element with oggdemux, theoradec, ffmpegcolorspace and ximagesink. At first, I got no output, but after I dispensed with the muxing/demuxing altogether, I got a static image, along with some debug messages about timestamps. I got the correct output after setting the is-live and do-timestamp properties to true on appsrc.
I assume that it should be possible to directly set the timestamps on the buffers that you are pushing out of appsrc, but alas I've not discovered how to do that.

Categories