serial-watcher 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,42 @@
1
+
2
+ module Gui
3
+ class MetaDialog < Gtk::Dialog
4
+
5
+ type_register
6
+ def initialize(hash)
7
+ serial = hash[:serial]
8
+ hash = nil
9
+ super
10
+
11
+
12
+ set_title "Serial Meta Edit"
13
+ add_buttons [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_OK],
14
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL]
15
+ has_separator = false
16
+
17
+ table = Gtk::Table.new 5, 2, true
18
+ table.border_width = 10
19
+
20
+ entry = Gtk::Entry.new
21
+ @status = Status.instance
22
+
23
+ # 1st row
24
+ label = Gtk::Label.new("Name: ")
25
+ @name_entry = Gtk::Entry.new
26
+ @name_entry.text = serial.meta.name || serial.name
27
+ table.attach label, 0, 1, 0, 1
28
+ table.attach @name_entry, 1, 2, 0, 1
29
+
30
+ # 2nd row
31
+
32
+ vbox.add(table)
33
+ show_all
34
+ end
35
+
36
+ def values
37
+ data = {
38
+ :name => @name_entry.text
39
+ }
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,44 @@
1
+
2
+ module Gui
3
+ class SettingsDialog < Gtk::Dialog
4
+
5
+ type_register
6
+ def initialize()
7
+ super
8
+ set_title "Serial Watcher Settings"
9
+ add_buttons [Gtk::Stock::SAVE, Gtk::Dialog::RESPONSE_OK],
10
+ [Gtk::Stock::CANCEL, Gtk::Dialog::RESPONSE_CANCEL]
11
+ has_separator = false
12
+
13
+ table = Gtk::Table.new 5, 2, true
14
+ table.border_width = 10
15
+
16
+ @status = Status.instance
17
+ @original_path = @status.data_dir
18
+
19
+ entry = Gtk::Entry.new
20
+
21
+ # 1st row
22
+ label = Gtk::Label.new("Serials directory: ")
23
+ @path_chooser = Gtk::FileChooserButton.new( "Choose a Folder", Gtk::FileChooser::ACTION_SELECT_FOLDER)
24
+ @path_chooser.current_folder = @status.data_dir
25
+ table.attach label, 0, 1, 0, 1
26
+ table.attach @path_chooser, 1, 2, 0, 1
27
+
28
+ # 2nd row
29
+
30
+ vbox.add(table)
31
+ show_all
32
+ end
33
+
34
+ def path_changed?
35
+ @original_path != @path_chooser.current_folder
36
+ end
37
+
38
+ def values
39
+ data = {
40
+ :path => @path_chooser.current_folder
41
+ }
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,73 @@
1
+
2
+ require 'serial'
3
+ require 'fs'
4
+
5
+ module Gui
6
+ class TitleBox < Gtk::VBox
7
+ type_register
8
+ attr_accessor :serials
9
+
10
+ signal_new("title_changed", GLib::Signal::RUN_FIRST, nil, nil, Serial)
11
+ signal_new("loaded", GLib::Signal::RUN_FIRST, nil, nil, false)
12
+
13
+ def initialize
14
+ @colormap = Gtk::Widget.default_colormap
15
+ @fs = Fs.instance
16
+ @status = Status.instance
17
+ super
18
+ end
19
+
20
+ def clear
21
+ self.each_forall do |e|
22
+ remove(e) if e.class.to_s == "Gtk::Button"
23
+ end
24
+ end
25
+
26
+ def load(dir = @status.data_dir)
27
+ clear
28
+
29
+ @fs.init dir
30
+ series = @fs.series || []
31
+ series.each do |serial|
32
+
33
+ # button
34
+ button = Gtk::Button.new " #{serial.name} "
35
+ button.use_stock = true
36
+ button.set_xalign 0.0
37
+ button.set_image Gtk::Image.new( serial.image || File.join($STATIC_PATH, 'images/dash.png') )
38
+ button.set_image_position Gtk::POS_LEFT
39
+
40
+ button.signal_connect "clicked" do
41
+ self.modify_current_button button
42
+ self.signal_emit( "title_changed", serial )
43
+ end
44
+
45
+ if serial.path == @status.get_last_serial
46
+ button.signal_emit "clicked"
47
+ end
48
+
49
+ pack_start button, false, false, 3
50
+ end
51
+ self.show_all
52
+ self.signal_emit( "loaded" , false)
53
+ end
54
+
55
+ def modify_current_button button
56
+ self.each_forall do |btn|
57
+ if btn.class.to_s == "Gtk::Button"
58
+ btn.modify_bg(Gtk::STATE_NORMAL, nil)
59
+ btn.modify_bg(Gtk::STATE_PRELIGHT, nil)
60
+ end
61
+ end
62
+ button.modify_bg(Gtk::STATE_NORMAL, Gdk::Color.new(45535, 45535, 65535))
63
+ button.modify_bg(Gtk::STATE_PRELIGHT, Gdk::Color.new(40535, 40535, 65535))
64
+ end
65
+
66
+ def signal_do_title_changed(arg)
67
+ end
68
+
69
+ def signal_do_loaded(arg)
70
+ end
71
+ end
72
+ end
73
+
@@ -0,0 +1,42 @@
1
+
2
+ require 'thread'
3
+
4
+ module Gui
5
+ class TorrentPanel < Gtk::VBox
6
+
7
+ type_register
8
+
9
+ def initialize()
10
+ height_request = 50
11
+ super
12
+ end
13
+
14
+ def clear
15
+ each_forall do |e| remove(e) end
16
+ end
17
+
18
+ def load(serial)
19
+ clear
20
+
21
+ Thread.new do
22
+ @torrent = ::Torrent::Torrentz.instance
23
+ @torrent.load serial.meta.name
24
+ @torrent.get_last_feeds.each do |torrent|
25
+
26
+ torrent_link = Gtk::LinkButton.new torrent[:url], "#{torrent[:date]} / #{torrent[:name]}"
27
+
28
+ torrent_link.set_alignment 0, 0.5
29
+ torrent_link.signal_connect "clicked" do |link_btn|
30
+ Thread.new do
31
+ `chromium #{link_btn.uri}`
32
+ end
33
+ end
34
+
35
+ pack_start_defaults torrent_link#, true, true #false, false
36
+
37
+ end
38
+ show_all
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,53 @@
1
+
2
+ $LOAD_PATH << '.'
3
+
4
+ require 'lockfile'
5
+ require 'gui/main'
6
+
7
+ $DATADIR = ''
8
+ $INITIAL_SERIAL = ""
9
+ $INITIAL_EPISODE = 0
10
+
11
+ $DEBUG = false
12
+ #$DEBUG = true
13
+
14
+ class SerialWatcher
15
+ def initialize
16
+ begin
17
+ Lockfile("/tmp/serial-watcher.lock", :retries => 0, :debug => $DEBUG, :poll_retries => 1) do
18
+ Gtk.init
19
+ window = Gui::Main.new
20
+ window.show_all
21
+ Gtk.main
22
+ end
23
+ rescue Lockfile::MaxTriesLockError
24
+ notify "Another instance is running"
25
+ self.raise_window
26
+ end
27
+ self.quit
28
+ end
29
+
30
+ def raise_window
31
+ begin
32
+ window_id = `xdotool search --name "Serial\ Watcher"`
33
+ `xdotool windowraise #{window_id}`
34
+ `xdotool windowfocus #{window_id}`
35
+ rescue
36
+ notify "you need to install xdotool to raise opened window"
37
+ end
38
+ end
39
+
40
+ def quit
41
+ log "Quiting .."
42
+ Kernel.exit(1)
43
+ end
44
+ end
45
+
46
+ def notify(message)
47
+ `notify-send '#{message}'`
48
+ end
49
+
50
+ def log(message)
51
+ puts message
52
+ end
53
+
@@ -0,0 +1,43 @@
1
+
2
+ class Meta
3
+ def initialize(serial)
4
+ @serial = serial
5
+ end
6
+
7
+ def name
8
+ @name ||= (@name.nil? ? @serial.name : @name)
9
+ end
10
+
11
+ def path
12
+ "#{@serial.path}/.meta"
13
+ end
14
+
15
+ def meta_data
16
+ data = {
17
+ :name => name
18
+ }
19
+ end
20
+
21
+ def create_file
22
+ begin
23
+ File.open(path, 'w') { |f| f.write( meta_data.to_yaml ) }
24
+ rescue
25
+ puts "cannot create meta-file"
26
+ end
27
+ end
28
+
29
+ def load_file
30
+ meta = File.exists?(path) ? YAML.load(File.open(path)) : meta_data
31
+ meta_data.each { |key, value|
32
+ eval("@#{key} = ?", meta.try('[]', key))
33
+ }
34
+ end
35
+
36
+ def save_file meta
37
+ meta_data.each do |key, value|
38
+ eval("@#{key} = ?", meta.try('[]', key))
39
+ end
40
+ create_file
41
+ end
42
+ end
43
+
@@ -0,0 +1,58 @@
1
+ require 'singleton'
2
+ require 'gtk2'
3
+
4
+ require 'status'
5
+
6
+ class Player < Gtk::Object
7
+
8
+ include Singleton
9
+ type_register
10
+
11
+ attr_accessor :status
12
+
13
+ signal_new("playing_ended", GLib::Signal::RUN_FIRST, nil, nil, String)
14
+
15
+ def initialize
16
+ super
17
+ @status = Status.instance
18
+ end
19
+
20
+ def play_episode episode
21
+ @status.save_status episode
22
+ begin
23
+ @thr = Thread.new do
24
+
25
+ Thread.abort_on_exception = true
26
+ #s = `mplayer -identify -fs \'#{episode.path}\' 2>&1 | tail -n 1`
27
+ `killall mplayer 2>&1 > /dev/null`
28
+ s = `mplayer -identify \'#{episode.path}\' #{"-fs" if @status.data[:fullscreen]} 2>&1 | tail -n 1`
29
+ if s == "ID_EXIT=EOF\n"
30
+ signal_emit("playing_ended", "param")
31
+ #raise "playing ended"
32
+ end
33
+
34
+ Thread.exit
35
+ end
36
+
37
+ Thread.new do
38
+ sleep 2
39
+ 4.times do
40
+ # TODO fix it all
41
+ m_id=`xwininfo -name MPlayer |grep 'Window id:' |cut -d" " -f4`.strip
42
+ cmd = "xdotool key --window #{m_id} 114"
43
+ `#{cmd}`
44
+ end
45
+ Thread.exit
46
+ end
47
+
48
+ rescue
49
+ puts "resque"
50
+ end
51
+
52
+ end
53
+
54
+ def signal_do_playing_ended param
55
+ end
56
+
57
+ end
58
+
@@ -0,0 +1,29 @@
1
+
2
+ require 'simple-rss'
3
+ require 'open-uri'
4
+ require 'singleton'
5
+
6
+ module Torrent
7
+ class Main
8
+ attr_reader :url, :rss
9
+ include Singleton
10
+
11
+ def initialize
12
+ @data = {}
13
+ end
14
+
15
+ def rss_load
16
+ @rss = @data[@name] || (@data[@name] = SimpleRSS.parse open(@url) if @url)
17
+ end
18
+
19
+ def human_format
20
+ raise "Method need to be overloaded"
21
+ end
22
+
23
+
24
+ def get_last_feeds(num = 5, trim = 40)
25
+ return [] if not @rss
26
+ human_format(@rss.channel.items.sort{|b,a| a[:pubDate] <=> b[:pubDate]}[0,5], trim)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+
2
+ require 'date'
3
+ require 'plugins/torrent/main'
4
+
5
+ module Torrent
6
+ class Torrentz < Main
7
+
8
+ def load(name)
9
+ @name = name
10
+ @url = ("http://torrentz.eu/feed?q=#{CGI.escape(name)}" if name) || nil
11
+ rss_load if @url
12
+ end
13
+
14
+ def human_format list, trim
15
+ list.map do |item|
16
+ nitem = {}
17
+ nitem[:name] = item[:title].length > trim ? "#{item[:title][0, trim]}.." : item[:title]
18
+ nitem[:date] = "#{(Date.today - item[:pubDate].to_date).to_i} days ago"
19
+ nitem[:url] = item[:link]
20
+ nitem
21
+ end
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,25 @@
1
+
2
+ require 'date'
3
+ require 'plugins/torrent/main'
4
+
5
+ module Torrent
6
+ class TPB < Main
7
+
8
+ def load(name)
9
+ @name = name
10
+ @url = ""#http://torrentz.eu/feed?q=#{CGI.escape(name)}"
11
+ rss_load
12
+ end
13
+
14
+ def human_format list, trim
15
+ list.map do |item|
16
+ nitem = {}
17
+ nitem[:name] = "#{item[:title][0, trim]}.." if item[:title].length > trim
18
+ nitem[:date] = item[:pubDate]
19
+ nitem[:url] = item[:link]
20
+ nitem
21
+ end
22
+ end
23
+ end
24
+ end
25
+