Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python2
- # -*- Encoding: UTF-8 -*-
- import gtk
- import gtk.gdk
- import gobject
- import json
- import os
- import datetime
- import time
- import subprocess
- import threading
- #import pynotify
- from Queue import Queue
- # use process to exec/call wmctrl -l -G and parse fields (0-7), 0 - w_id hex integer, 1 - PID = PID of the window as decimal integer, 2 - x-offset, 3 - y-offset, 4 - width, 5 - height, 6 - client machine name, 7 - Window title (with spacecs(possibly))
- UPDATE_TIMEOUT = 1 # in seconds
- APP_TITLE="Deko"
- _lock = threading.Lock()
- class objectview(object):
- def __init__(self, d):
- self.__dict__ = d
- class Launchers:
- def __init__(self):
- self._item = 0
- self._deets = []
- def add_launcher(self,name,stream="source",ref=0):
- fing={"item":self._item,"name":name,"state":0,"proc":0,"sven":"nada","ref":ref,"stream":stream}
- self._item+=1
- self._deets.append(objectview(fing))
- def count(self):
- return len(self._deets)
- def lol(self):
- return self._deets
- def info(*args):
- with _lock:
- print("%s %s" % (threading.current_thread(), " ".join(map(str, args))))
- class WindowDeko(gtk.Window):
- def __init__(self):
- gtk.Window.__init__(self)
- self.set_size_request(640,480)
- self.set_border_width(10)
- self.set_title(APP_TITLE)
- self.treeview = gtk.TreeView()
- self.fileTime = ""
- vbox_app = gtk.VBox(False, 0)
- self.add(vbox_app)
- vbox_app.show()
- self.CORE=0
- self.firstPass=True
- # self.speed=["audio","mobile","low","medium","high","source"]
- hbox_info = gtk.HBox(False, 0)
- ## icon in window top left
- image_ref = gtk.Image()
- image_ref.set_from_stock(gtk.STOCK_SELECT_COLOR,6)
- image_ref.set_alignment(0, 0.5)
- hbox_info.pack_start(image_ref, True, True, 0)
- image_ref.show()
- label_app = gtk.Label(self.fileTime)
- hbox_info.pack_start(label_app, True, True, 0)
- label_app.show()
- self.legend = label_app
- vbox_app.pack_start(hbox_info, False, False, 6)
- hbox_info.show()
- self.treeview.show()
- scrollTree = gtk.ScrolledWindow()
- scrollTree.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- scrollTree.add(self.treeview)
- scrollTree.show()
- vbox_app.pack_start(scrollTree, True, True, 6)
- hbox_close = gtk.HBox(False, 0)
- button_do = gtk.Button(stock=gtk.STOCK_MEDIA_PLAY)
- button_do.connect("clicked", self.btn_show)
- button_do.set_flags(gtk.CAN_DEFAULT)
- hbox_close.pack_start(button_do, True, True, 0)
- button_do.show()
- button_close = gtk.Button(stock=gtk.STOCK_CLOSE)
- button_close.connect("clicked", lambda w: gtk.main_quit())
- # button_close.set_flags(gtk.CAN_DEFAULT)
- hbox_close.pack_start(button_close, True, True, 0)
- button_close.show()
- hbox_close.show()
- vbox_app.pack_start(hbox_close, False, False, 6)
- # Place after association to hbox/vbox to avoid the following error:
- # GtkWarning: gtkwidget.c:5460: widget not within a GtkWindow
- #button_close.grab_default()
- self.pastyfirst=True
- self.launchers=Launchers()
- self.updater = Updater()
- self._update_id = None
- self.popTree()
- self.update()
- return
- def rowActivated(self,treeview, path, column):
- self.dekoIt()
- # self.playIt()
- def cell_toggled(widget, path, model):
- model[path][3] = not model[path][3]
- def popTree(self):
- try:
- holder=self.getWM("/home/sky/sktwitch")
- self.legend.set_text(self.fileTime)
- notifymsg=""
- cols=["W_ID","PID","x-offset","y-offset","width","height","title","deco"]
- if self.firstPass==True:
- self.llama = holder
- self.firstPass=False
- self.treeview.set_model(self.llama)
- if self.treeview.get_columns():
- for meany in self.treeview.get_columns():
- self.treeview.remove_column(meany)
- count=0
- for col in cols:
- column=gtk.TreeViewColumn(col)
- cell = gtk.CellRendererText()
- column.pack_start(cell)
- column.set_resizable(True)
- column.add_attribute(cell,'text',count)
- self.treeview.append_column(column)
- count+=1
- self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
- self.treeview.connect('row-activated', self.rowActivated)
- notifymsg+="\n"+" Started"
- else:
- # add/update current
- for entry in holder:
- exists=False
- for existing in self.llama:
- if entry[0]==existing[0]:
- exists=True
- for c in range(1,len(cols)):
- if existing[c]!=entry[c]:
- existing[c]=entry[c]
- break
- if exists==False:
- self.llama.append(entry)
- # remove gone
- for existing in self.llama:
- exists=False
- for entry in holder:
- if entry[0]==existing[0]:
- exists=True
- break
- if exists==False:
- self.llama.remove(existing.iter)
- if notifymsg !="":
- temp=0
- #pynotify.init(APP_TITLE)
- #notice = pynotify.Notification(APP_TITLE, notifymsg)
- #notice.show()
- except OSError:
- self.legend.set_text("File Error!")
- info("os error")
- def XpopTree(self):
- try:
- holder=self.getWM("/home/sky/sktwitch")
- self.legend.set_text(self.fileTime)
- notifymsg=""
- if self.firstPass==True:
- self.llama = holder
- self.firstPass=False
- self.treeview.set_model(self.llama)
- column1 = gtk.TreeViewColumn("W_ID")
- column2 = gtk.TreeViewColumn("PID")
- column3 = gtk.TreeViewColumn("x-offset")
- column4 = gtk.TreeViewColumn("y-offset")
- column5 = gtk.TreeViewColumn("width")
- column6 = gtk.TreeViewColumn("height")
- column7 = gtk.TreeViewColumn("title")
- cell1 = gtk.CellRendererText()
- cell2 = gtk.CellRendererText()
- cell3 = gtk.CellRendererText()
- cell4 = gtk.CellRendererText()
- cell5 = gtk.CellRendererText()
- cell6 = gtk.CellRendererText()
- cell7 = gtk.CellRendererText()
- ## cell4.set_property('alignment',2)
- ## cell5.set_property('alignment',2)
- # cell4.add_attribute(cellrenderer_pixbuf, "stock-id", 1)
- # cell4.connect("toggled", cell_toggled, self.llama)
- # cell4.set_property('activatable', True)
- # cell4.set_property('active', True)
- column1.pack_start(cell1)
- column2.pack_start(cell2)
- column3.pack_start(cell3)
- column4.pack_start(cell4)
- column5.pack_start(cell5)
- column6.pack_start(cell6)
- column7.pack_start(cell7)
- column1.set_resizable(True)
- column1.add_attribute(cell1,'text',0)
- column2.set_resizable(True)
- column2.add_attribute(cell2,'text',1)
- column3.set_resizable(True)
- column3.add_attribute(cell3,'text',2)
- column4.set_resizable(True)
- column4.add_attribute(cell4,'text',3)
- column5.set_resizable(True)
- column5.add_attribute(cell5,'text',4)
- column6.set_resizable(True)
- column6.add_attribute(cell6,'text',5)
- column7.set_resizable(True)
- column7.add_attribute(cell7,'text',6)
- if self.treeview.get_columns():
- for meany in self.treeview.get_columns():
- self.treeview.remove_column(meany)
- self.treeview.append_column(column1)
- self.treeview.append_column(column2)
- self.treeview.append_column(column3)
- self.treeview.append_column(column4)
- self.treeview.append_column(column5)
- self.treeview.append_column(column6)
- self.treeview.append_column(column7)
- self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
- self.treeview.connect('row-activated', self.rowActivated)
- notifymsg+="\n"+" Started"
- else:
- # add/update current
- for entry in holder:
- exists=False
- for existing in self.llama:
- if entry[0]==existing[0]:
- exists=True
- existing[1]=entry[1]
- existing[2]=entry[2]
- existing[4]=entry[4]
- break
- if exists==False:
- self.llama.append([entry[0],entry[1],entry[2],"■",entry[4]])
- if notifymsg!="":
- notifymsg+="\n"
- notifymsg+="{ +++ } "+entry[0]+", now streamering "+entry[1]+"."
- # remove gone
- for existing in self.llama:
- exists=False
- for entry in holder:
- if entry[0]==existing[0]:
- exists=True
- break
- if exists==False:
- if notifymsg!="":
- notifymsg+="\n"
- notifymsg+=") --- ( "+existing[0]+" removed from streamers"
- self.llama.remove(existing.iter)
- if notifymsg !="":
- temp=1
- #pynotify.init(APP_TITLE)
- #notice = pynotify.Notification(APP_TITLE, notifymsg)
- #notice.show()
- except OSError:
- self.legend.set_text("File Error!")
- info("os error")
- def modification_date(self,filename):
- t = os.path.getmtime(filename)
- return datetime.datetime.fromtimestamp(t)
- def getWM(self,json_file):
- store=gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING)
- root = gtk.gdk.get_default_root_window()
- for id in root.property_get('_NET_CLIENT_LIST')[2]:
- w = gtk.gdk.window_foreign_new(id)
- if w:
- dc=w.get_decorations()
- dekod=""
- dsep=""
- for dek in dc.value_names:
- dekod+=dsep+dek
- dsep=","
- d=w.property_get('WM_NAME')
- p=w.property_get('WM_PID')
- if d:
- if not p is None:
- print p
- geo=w.get_geometry()
- pos=w.get_origin()
- b1,b2=pos
- a1,a2,a3,a4,a5=geo
- c1,c2,c3=d
- # outee={"wid":str(id),"pid":str(p),"x":str(b1),"y":str(b2),"w":str(a3),"h":,"mac":"this","title":c3}
- # if d[2]==q:
- # w.set_decorations(p)
- # gtk.gdk.window_process_all_updates()
- store.append([str(id),str(p),str(b1),str(b2),str(a3),str(a4),c3,dekod])
- return store
- def getList(self,json_file):
- store=gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING,gobject.TYPE_STRING)
- tim=self.modification_date(json_file)
- self.fileTime=str(tim.year) + "-" + str(tim.month).zfill(2) + "-" + str(tim.day).zfill(2) + " " + str(tim.hour).zfill(2) + ":" + str(tim.minute).zfill(2)
- json_data=open(json_file)
- data = json.load(json_data)
- json_data.close()
- streams=json.loads(data)
- for streamer in streams["streams"]:
- # print str(streamer["viewers"])
- store.append([streamer["channel"]["display_name"],streamer["channel"]["game"],streamer["channel"]["status"],"■",str(streamer["viewers"])])
- return store
- def btn_force(self,evt):
- self.legend.set_text("Forcing Update From Twitch.tv!")
- self.launchers.add_launcher(".")
- def btn_refresh(self,evt):
- self.do_Refresh()
- def do_Refresh(self):
- self.legend.set_text("Refreshing!")
- self.CORE=0
- self.popTree()
- def btn_hide(self,evt):
- print "STOP FOR WHAT"
- def btn_show(self,evt):
- # what to do with evt??
- self.dekoIt()
- # self.playIt()
- def playIt(self):
- self.pastyfirst=True
- tree_selection = self.treeview.get_selection()
- (model, pathlist) = tree_selection.get_selected_rows()
- for path in pathlist :
- tree_iter = model.get_iter(path)
- name = model.get_value(tree_iter,0)
- stat = model.get_value(tree_iter,3)
- if stat == "■":
- # print "in name:" + name
- ref=gtk.TreeRowReference(model,path)
- SetCell(ref,"▶")
- self.launchers.add_launcher(name,self.speed[self.combo.get_active()],ref)
- def dekoIt(self):
- tree_selection = self.treeview.get_selection()
- (model, pathlist) = tree_selection.get_selected_rows()
- for path in pathlist :
- tree_iter = model.get_iter(path)
- wid = model.get_value(tree_iter,0)
- nam = model.get_value(tree_iter,6)
- root = gtk.gdk.get_default_root_window()
- for id in root.property_get('_NET_CLIENT_LIST')[2]:
- if str(id)==wid:
- w = gtk.gdk.window_foreign_new(id)
- if w:
- dc=w.get_decorations()
- dekod=False
- for dek in dc.value_names:
- dekod=True
- w.set_decorations(not dekod)
- gtk.gdk.window_process_all_updates()
- break
- def update(self):
- lcount=self.launchers.count()
- self.popTree() #info("Updatng", 0)
- #info( str(self.CORE)+" U:" , lcount)
- self.CORE+=1
- if self.CORE==60: # one minute try quicker gtkdeko
- self.CORE=0
- self.do_Refresh()
- deletes=[]
- if self.pastyfirst==True:
- self.pastyfirst=False
- else:
- if lcount>0:
- rCount=" - "
- # fing={"item":self._item,"name":name,"state":0,"proc":0,"sven":"nada","ref":ref,"stream":stream}
- for launcher in self.launchers._deets:
- rCount+=str(launcher.item)
- if launcher.state==0:
- rCount+=" - yah"
- launcher.state=1
- if self._update_id is not None:
- gobject.source_remove(self._update_id)
- self.updater.add_update(self.done_updating,launcher) # returns immediately
- elif launcher.state==1:
- rCount+=" - snf"
- elif launcher.state==2:
- if self._update_id is not None:
- gobject.source_remove(self._update_id)
- self.updater.add_update(self.done_updating,launcher) # returns immediately
- rCount+=" - **["+launcher.sven+"]**"
- elif launcher.state==3:
- if self._update_id is not None:
- gobject.source_remove(self._update_id)
- self.updater.add_update(self.done_updating,launcher) # returns immediately
- rCount+=" - **["+launcher.sven+"]**"
- elif launcher.state==5:
- launcher.state=6
- rCount+=" - pop"
- print "popping"
- self.popTree()
- elif launcher.state==6:
- rCount+="fin."
- deletes.append(launcher)
- rCount+=", "
- info( "Poll("+rCount+")")
- if len(deletes)>0:
- for launcher in deletes:
- if launcher.ref!=0:
- SetCell(launcher.ref,"■")
- self.launchers._deets.remove(launcher)
- # call in UPDATE_TIMEOUT seconds
- self._update_id = gobject.timeout_add(
- int(UPDATE_TIMEOUT*1000), self.update)
- def done_updating(self, task_id,args):
- a=True
- # info('done updating', task_id)
- # info('dbata',args.state)
- #self.button.set_label("done updating %s" % task_id)
- def SetCell(ref,txt):
- # also check if ref is valid()
- path=ref.get_path()
- model=ref.get_model()
- tree_iter = model.get_iter(path)
- line = txt.replace("\n", "")
- model.set_value(tree_iter,3,line)
- class Updater:
- def __init__(self):
- self._task_id = 0
- self._queue = Queue(maxsize=100) #NOTE: GUI blocks if queue is full
- for _ in range(9):
- t = threading.Thread(target=self._work)
- t.daemon = True
- t.start()
- def _work(self):
- # executed in background thread
- # fing={"item":self._item,"name":name,"state":0,"proc":0,"sven":"nada","ref":ref,"stream":stream}
- for task_id, done, args in iter(self._queue.get, None):
- if args[0].state==1:
- if args[0].name==".":
- print "forced"
- #info("Forcing Update.")
- args[0].state=2
- args[0].proc = subprocess.Popen('/home/sky/Documents/sktwitch.py',shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
- else:
- SetCell(args[0].ref,"Launching "+args[0].name+"'s Live Stream")
- args[0].state=2
- # args[0].proc = subprocess.Popen('livestreamer -p vlc twitch.tv/'+args[0].name+' '+args[0].stream,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
- args[0].proc = subprocess.Popen('hexchat --existing --command="join #'+args[0].name.lower()+'"; livestreamer -p vlc twitch.tv/'+args[0].name+' '+args[0].stream,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
- elif args[0].state==2:
- args[0].state=3
- elif args[0].state==3:
- args[0].state=99
- nextline = None
- buf = ''
- while True:
- #--- extract line using read(1)
- try:
- out = args[0].proc.stdout.read(1)
- except AttributeError:
- break
- if out == '' and args[0].proc.poll() != None: break
- if out != '':
- buf += out
- if out == '\n':
- nextline = buf
- buf = ''
- if not nextline: continue
- line = nextline
- nextline = None
- #--- eol or eof reached
- #info(args[0].name,':', line)
- # args[0].sven=line
- #--- do something with line, maybe?
- # (model, pathlist) = tree_selection.get_selected_rows()
- # for path in pathlist :
- if args[0].ref!=0:
- SetCell(args[0].ref,line)
- if args[0].name==".":
- args[0].state=5
- else:
- args[0].state=6
- # #info(args[0].state,"{ - ",args[0].name," - }")
- elif args[0].state==6:
- dummy=1
- #info(" O V A H ")
- # signal task completion; run done() in the main thread
- gobject.idle_add(done, *((task_id,) + args))
- def add_update(self, callback, *args):
- # executed in the main thread
- self._task_id += 1
- self._queue.put((self._task_id, callback, args))
- gobject.threads_init() # init threads?
- win = WindowDeko()
- win.connect("delete-event", gtk.main_quit)
- win.show_all()
- gtk.main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement