Skip to content

Instantly share code, notes, and snippets.

@rennex
Created December 2, 2018 02:05
Show Gist options
  • Save rennex/78c06ac782753a54809d61e972004151 to your computer and use it in GitHub Desktop.
Save rennex/78c06ac782753a54809d61e972004151 to your computer and use it in GitHub Desktop.
Media Player Classic activity logger
# encoding: UTF-8
# ----- Settings: -----
# what machine's MPC is monitored, and on which port
MPC_HOST = "localhost:13579"
LOGFILE = "log.txt"
PRINTLOG = false # also print to console?
ENDTOLERANCE = 0.95 # seen 95% = seen all of it
INTERVAL = 5 # seconds to wait after each status update
OUTPUT_CHARSET = "CP850" # this is a fix for windows's cmd.exe
LOG_TIME_FORMAT = "%d.%m.%Y %H:%M:%S"
# ---------------------
# todo: "undefined method `strip' for 720:Fixnum" seen sometimes
require "open-uri"
# require "json"
MPCStatus = Struct.new(:filename, :status, :pos, :posstr, :dur, :durstr, :muted, :volume, :seen_upto)
class MPCMonitor
def initialize(host)
@host = host
@prev = emptystatus
end
def getstatus
begin
# fetch the status data by http
str = open("http://#@host/status.html").read.force_encoding("UTF-8")
if str =~ /^OnStatus\((.+)\)/
status = $1
args = []
status.scan(/(\d+|"(([^"]|\\")*?)")(, )?/) do
args << ($2 || $1.to_i)
end
#x = $1.tr('"\'', '\'"')
#args = JSON.parse "[#{x}]"
#p args
# get the file name from the window title
#args[0].sub!(/( - )?Media Player Classic.*?$/, "")
args[0] = args.slice!(-1)
args[0] = nil if args[0].strip == ""
args[1] = nil if args[1].strip == ""
return MPCStatus[*args, 0]
else
raise "invalid data received (something other than MPC running at #@host)"
end
rescue OpenURI::HTTPError
raise "unable to connect to MPC - #$!"
rescue Errno::ECONNREFUSED, EOFError
# if it's not running at all (connection refused)
# or exited while replying (EOFError)
return emptystatus
end
end
def emptystatus
MPCStatus[nil, nil, 0, "00:00:00", 0, "00:00:00", 0, 100, 0]
end
def ms2txt(ms)
s = ms/1000
min = s/60
s %= 60
h = min/60
min %= 60
"%02d:%02d:%02d" % [h,min,s]
end
def run
puts "Commencing monitoring. Polling MPC every #{INTERVAL} seconds."
#p STDOUT.external_encoding
#STDOUT.set_encoding "CP850"
#puts "äöå"
#puts "äöå".encode("CP850")
#puts "äöå".encoding.name
#p Encoding.default_external.name
#p __ENCODING__
#p STDOUT.external_encoding
loop do
begin
s = getstatus()
# different file?
if s.filename != @prev.filename
if @prev.filename
uptotxt = "watched up to #{ms2txt(@prev.seen_upto)}"
if @prev.seen_upto.to_f / @prev.dur >= ENDTOLERANCE
uptotxt += ") (finished"
end
log "Closed file (#{uptotxt})"
end
if s.filename
log "Started playing #{s.filename}"
# forget the old file at this point
@prev = s
s.status = "Playing"
s.seen_upto = s.pos
end
end
# status changed?
# NOTE: keep the "if s.filename" because sometimes it's nil and s.status=="Opening..."
if s.filename && s.status != @prev.status
log "#{s.status} at #{s.posstr}"
end
# how much has been viewed?
s.seen_upto = [s.pos, @prev.seen_upto].max
@prev = s
rescue
puts $!.inspect, *$@
#puts "mpclog error: #$!"
#puts "Backtrace:\n\t#{$!.backtrace.join("\n\t")}"
end
sleep INTERVAL
end
end
def log(txt)
logline = "#{Time.now.strftime(LOG_TIME_FORMAT)} - #{txt}"
File.open(LOGFILE, "a") do |f|
f.puts logline
end
puts logline if PRINTLOG
end
def puts(*args)
STDOUT.puts(*(args.map {|a| a.to_s.encode(OUTPUT_CHARSET, invalid: :replace, undef: :replace, replace: "?")}))
end
end
begin
mon = MPCMonitor.new(MPC_HOST)
mon.run
rescue Interrupt
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment