// -*- tab-width: 4 -*-
/*
valac --pkg gtk+-2.0 --pkg gio-2.0 --pkg gstreamer-0.10 --pkg unique-1.0 sccplayer.vala
sccplayer http://yp.shoutcast.com/sbin/tunein-station.pls?id=6687
*/
using Gtk;
using Gst;
using Unique;
public class SccPlayer : Gtk.Object {
enum Command {
COMMAND_0,
COMMAND_PLAYURI
}
private Gtk.Window main_window;
private Gtk.Label channel_label;
private Gtk.Label track_label;
private Gtk.Statusbar status_bar;
public dynamic Gst.Element play_src;
private const string uistring =
"""
""";
[CCode (instance_pos = -1)]
public void
/******************************************************************************/
on_main_window_destroy () {
play_src.set_state (State.PAUSED);
play_src.set_state (State.NULL);
Gtk.main_quit();
}
static bool
/******************************************************************************/
command_line_ok (string[] args) {
if (args.length <= 1) {
stdout.printf ("Usage: %s \n", args[0]);
return false;
}
return true;
}
static void
/******************************************************************************/
handle_fail_or_user_cancel () {
stdout.printf ("TODO: handle libunique cancel/fail...\n");
}
public bool
/******************************************************************************/
do_command_playuri (Unique.MessageData message) {
status_bar.push (1, "Waiting...");
this.play (message.get_text());
return true;
}
public Unique.Response
/******************************************************************************/
message_received_cb (
int command, Unique.MessageData message, uint time){
Unique.Response res;
switch (command) {
case Unique.Command.ACTIVATE:
res = Unique.Response.OK;
break;
case Command.COMMAND_PLAYURI:
if (do_command_playuri (message))
res = Unique.Response.OK;
else
res = Unique.Response.FAIL;
break;
default:
res = Unique.Response.OK;
break;
}
return res;
}
public void
/******************************************************************************/
foreach_tag (Gst.TagList list, string tag) {
string tag_string;
switch (tag) {
case "title":
list.get_string (tag, out tag_string);
main_window.title = tag_string.strip();
tag_string = tag_string.replace ("&", "&");
track_label.label = "" + tag_string.strip() + "";
while (events_pending()) main_iteration();
break;
default:
break;
}
}
public bool
/******************************************************************************/
bus_callback (Gst.Bus bus, Gst.Message message) {
GLib.Error err;
string debug;
Gst.State oldstate;
Gst.State newstate;
Gst.State pendstate;
Gst.TagList tag_list;
switch (message.type) {
case Gst.MessageType.ERROR:
play_src.set_state (State.NULL);
message.parse_error (out err, out debug);
stdout.printf ("Error: %s\n", err.message);
break;
case Gst.MessageType.EOS:
stdout.printf ("eos\n");
break;
case Gst.MessageType.STATE_CHANGED:
string blah;
message.parse_state_changed
(out oldstate, out newstate, out pendstate);
if (newstate == Gst.State.PLAYING) {
blah = "Playing...";
} else if (oldstate == Gst.State.READY
&& newstate == Gst.State.NULL
&& pendstate == Gst.State.VOID_PENDING) {
blah = "Buffering...";
} else if (newstate == Gst.State.READY) {
blah = "Waiting...";
} else if (newstate == Gst.State.PAUSED) {
blah = "Paused...";
} else {
blah = "%s > %s | %s".printf (
oldstate.to_string(), newstate.to_string()
,pendstate.to_string());
}
status_bar.push (1, blah);
break;
case Gst.MessageType.TAG:
message.parse_tag (out tag_list);
tag_list.foreach (foreach_tag);
break;
default:
break;
}
return true;
}
public string
/******************************************************************************/
get_channel (string playlist_uri) {
//TODO: should we do "balancing" or at least check if stream full ?
var file = File.new_for_commandline_arg (playlist_uri);
string outval = "";
try {
var in_stream = new DataInputStream (file.read (null));
string line;
string[] keyval;
while ((line = in_stream.read_line (null, null)) != null) {
keyval = line.split ("=", 2);
if (keyval[0] == "Title1") {
string[] tt = keyval[1].split (")", 2);
tt[1] = tt[1].replace ("&", "&");
channel_label.label = tt[1].strip();
while (events_pending()) main_iteration();
}
if (keyval[0] == "File1") {
outval = keyval[1];
}
}
} catch (IOError e) {
error ("%s", e.message);
}
return outval;
}
public void
/******************************************************************************/
play (string playlist_uri) {
main_window.set_title ("::Waiting for Title::");
channel_label.set_markup ("::Fetching Channel Name::");
track_label.set_markup ("::Waiting for Title::");
play_src.set_state (State.PAUSED);
play_src.set_state (State.NULL);
while (events_pending()) main_iteration();
string foo = get_channel (playlist_uri);
play_src.uri = foo;
play_src.set_state (State.PLAYING);
}
public
/******************************************************************************/
SccPlayer () {
try {
var builder = new Builder ();
// builder.add_from_file ("sccplayer.ui");
builder.add_from_string (uistring, uistring.len());
builder.connect_signals (null);
main_window = builder.get_object ("main_window") as Gtk.Window;
channel_label = builder.get_object ("channel_label") as Gtk.Label;
track_label = builder.get_object ("track_label") as Gtk.Label;
status_bar = builder.get_object ("status_bar") as Gtk.Statusbar;
main_window.show_all ();
} catch (Error e) {
stderr.printf ("Could not load UI: %s\n", e.message);
}
Bus bus;
play_src = ElementFactory.make ("playbin", "play_src");
bus = play_src.get_bus ();
bus.add_watch (bus_callback);
play_src.set_state (State.NULL);
}
public static int
/******************************************************************************/
main (string[] args) {
if (!command_line_ok (args))
return 1;
Unique.App app;
Gtk.init (ref args);
Gst.init (ref args);
app = new Unique.App.with_commands (
"de.osku.sccplayer", null,
"playuri", Command.COMMAND_PLAYURI, null);
if (app.is_running) {
Unique.Command command;
Unique.Response response;
Unique.MessageData message;
message = new MessageData ();
command = (Unique.Command) Command.COMMAND_PLAYURI;
message.set_text (args[1], args[1].len());
response = app.send_message (command, message);
if (response == Unique.Response.OK) return 0;
else handle_fail_or_user_cancel ();
} else {
var player = new SccPlayer ();
player.play (args[1]);
app.watch_window (player.main_window);
app.message_received += player.message_received_cb;
Gtk.main ();
}
return 0;
}
} // class
// vim:tabstop=4: