File: playlist.rb

package info (click to toggle)
ruby-gnome 4.2.2-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 26,648 kB
  • sloc: ruby: 67,701; ansic: 67,431; xml: 350; sh: 201; cpp: 45; makefile: 42
file content (180 lines) | stat: -rw-r--r-- 4,807 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/env ruby
# coding: utf-8

if ARGV.empty?
  puts "Usage: #{$0} <m3u file>|<media file> ..."
  exit(false)
elsif (file = ARGV.first).end_with?('.m3u')
  base = File.dirname(file)
  file_list = File.read(file).split("\n").map{|f| File.expand_path(f, base)}
else
  file_list = ARGV.map{|f| File.expand_path(f)}
end

unless %w(gtk3 gtk2).find{|l| begin; require l; rescue LoadError; false; end}
  puts "This sample requires gtk3 or gtk2."
  exit(false)
end
if Gtk.check_version?(3, 0, 0)
  def set_background(widget)
    widget.override_background_color(:normal, Gdk::RGBA.new(0, 0, 0, 0))
  end
elsif Gtk.check_version?(2, 16, 0)
  def set_background(widget)
    widget.modify_bg(:normal, Gdk::Color.new(0, 0, 0))
  end
else
  puts "This sample requires GTK+ 2.16.0 or later."
  exit(false)
end
require 'gvlc'

class Playlist
  COL_MEDIA     = 0
  COL_FILENAME  = 1

  def initialize(file_list)
    @builder = Gtk::Builder.new.add(__FILE__.sub(/\.rb$/, '.glade'))
    @builder.connect_signals{|name| method(name)}
    @window, @adjustment, @playlist, @listview = %w(win_main adj_position win_playlist tree_playlist).map{|n| @builder[n]}

    @listview.model = Gtk::ListStore.new(VLC::Media, String)
    column = Gtk::TreeViewColumn.new('file', Gtk::CellRendererText.new, text: COL_FILENAME)
    @listview.append_column(column)

    @listplayer = VLC::MediaListPlayer.new
    @player = @listplayer.media_player
    @list = @listplayer.media_list
    @player.attach_event(:mediaplayer_playing){|*a| on_mediaplayer_playing(*a)}
    @player.attach_event(:mediaplayer_timechanged){|*a| on_mediaplayer_timechanged(*a)}
    @list.lock do |list|
      file_list.each{|f| add_media(f)}
    end
  end

  def run
    @window.show_all
    @playlist.show_all
    @listplayer.play
    Gtk.main
  end

  def add_media(file)
    iter = @listview.model.append
    iter[COL_MEDIA]     = @list.add_media(path: file)
    iter[COL_FILENAME]  = File.basename(file)
  end

  def toggle_fullscreen
    if @window.window.state.fullscreen?
      @builder['box_control'].show_all
      @window.unfullscreen
    else
      @builder['box_control'].hide
      @window.fullscreen
    end
  end

  def time_str(time)
    return '' unless time

    time = (time / 1000).to_i
    time, sec = time.divmod(60)
    hour, min = time.divmod(60)
    '%d:%02d:%02d' % [hour, min, sec]
  end

  def on_mediaplayer_playing(player, event)
    @duration = nil
    size = player.get_size(0)
    @builder['draw_video'].set_size_request(*size) if size

    mrl = player.media.mrl
    iter = @listview.model.each{|m, p, i| break i if i[COL_MEDIA].mrl == mrl}
    @listview.selection.select_iter(iter)
    @window.title = iter[COL_FILENAME]
  end

  def on_mediaplayer_timechanged(player, event)
    return if @position_change

    @duration ||= player.media.duration
    @adjustment.upper = @duration
    @adjustment.page_increment = @duration / 10
    @adjustment.step_increment = @duration / 100
    @adjustment.value = player.time
  end

  def on_draw_video_realize(widget)
    @player.xwindow = widget.window.xid
    set_background(widget)
  end

  def on_scale_position_adjust_bounds(widget, value)
    @position_pending = value
  end

  def on_scale_position_button_press_event(widget, event)
    @position_change = true
    false
  end

  def on_scale_position_button_release_event(widget, event)
    @position_change = false
    @player.time, @position_pending = @position_pending, nil if @position_pending
    false
  end

  def on_win_main_scroll_event(widget, event)
    case event.direction
    when Gdk::EventScroll::Direction::UP
      @player.time += @adjustment.step_increment
    when Gdk::EventScroll::Direction::DOWN
      @player.time -= @adjustment.step_increment
    end
  end

  def on_scale_position_format_value(widget, value)
    "#{time_str(value)}/#{time_str(@duration)}"
  end

  def on_draw_video_button_press_event(widget, event)
    case event.event_type
    when Gdk::Event::Type::BUTTON_PRESS
      @listplayer.pause
    when Gdk::Event::Type::BUTTON2_PRESS
      toggle_fullscreen
    end
  end

  def on_action_activate(action)
    case action = action.name[/^act_(.*)/, 1].to_sym
    when :play, :pause, :stop, :previous, :next
      @listplayer.send(action)
    when :seek_backward
      @player.time -= @adjustment.page_increment
    when :seek_forward
      @player.time += @adjustment.page_increment
    when :playlist
      @playlist.show_all
    when :fullscreen
      toggle_fullscreen
    end
  end

  def on_tree_playlist_row_activated(widget, path, column)
    @listplayer.play(widget.model.get_iter(path)[COL_MEDIA])
  end

  def on_win_playlist_delete_event(widget, event)
    @playlist.hide
    true
  end

  def on_win_main_destroy(widget)
    Gtk.main_quit
  end
end

Playlist.new(file_list).run