Hello VALAds, i now have my first "useful" tool/code "done", well at least to the extend that it "works for me" :) (eeepc701, ubuntu 9.04, valac7.2) (bug reports, suggestions, rant, etc. highly welcome!)
SccPlayer "Player for shoutcast.com playlist streams" Give it a file:// or http:// uri of the playlist file. Yeah, you could call this "re-inventing the wheel", but i did it as an exercise (and itch:) to learn Vala and GTK, and programming in general. And yes, i'm one of those hobby hackers who "can't do quality software" but there's hope -> http://see.stanford.edu/ ! ;P seen that, been there, next please. Andre "Osku" Schmidt ps. no, i don't have anything to do with shoutcast.com, it just happens to be the "internet radio uri database" i used. and the name _is_, as the code too, just a "working-title"...
// -*- 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 = """ <?xml version="1.0"?> <interface> <requires lib="gtk+" version="2.16"/> <!-- interface-naming-policy project-wide --> <object class="GtkWindow" id="main_window"> <property name="width_request">320</property> <property name="title" translatable="yes">SccPlayer</property> <property name="icon_name">media-playback-start</property> <signal name="destroy" handler="scc_player_on_main_window_destroy"/> <child> <object class="GtkVBox" id="vbox1"> <property name="visible">True</property> <property name="orientation">vertical</property> <child> <object class="GtkVBox" id="vbox2"> <property name="visible">True</property> <property name="border_width">6</property> <property name="orientation">vertical</property> <child> <object class="GtkLabel" id="channel_label"> <property name="visible">True</property> <property name="xalign">0</property> <property name="label" translatable="yes">label</property> <property name="use_markup">True</property> <property name="selectable">True</property> <property name="ellipsize">end</property> </object> <packing> <property name="position">0</property> </packing> </child> <child> <object class="GtkLabel" id="track_label"> <property name="visible">True</property> <property name="xalign">0</property> <property name="label" translatable="yes">label</property> <property name="use_markup">True</property> <property name="selectable">True</property> <property name="ellipsize">end</property> </object> <packing> <property name="position">1</property> </packing> </child> </object> <packing> <property name="position">0</property> </packing> </child> <child> <object class="GtkStatusbar" id="status_bar"> <property name="visible">True</property> <property name="spacing">2</property> </object> <packing> <property name="expand">False</property> <property name="position">1</property> </packing> </child> </object> </child> </object> </interface> """; [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 <playlist uri>\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 = "<b>" + tag_string.strip() + "</b>"; 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 ("<i>::Fetching Channel Name::</i>"); track_label.set_markup ("<b><i>::Waiting for Title::</i></b>"); 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:
_______________________________________________ Vala-list mailing list [email protected] http://mail.gnome.org/mailman/listinfo/vala-list
