]> git.sesse.net Git - vlc/commitdiff
libVLC examples, from GCI work
authorJean-Baptiste Kempf <jb@videolan.org>
Wed, 8 Dec 2010 20:22:37 +0000 (21:22 +0100)
committerJean-Baptiste Kempf <jb@videolan.org>
Wed, 8 Dec 2010 20:24:22 +0000 (21:24 +0100)
 - Gtk+ player
 - wx   player
 - Qt   player
 - DVD ripper using Gtk

doc/libvlc/QtPlayer/LICENSE [new file with mode: 0644]
doc/libvlc/QtPlayer/QtVLC.pro [new file with mode: 0644]
doc/libvlc/QtPlayer/main.cpp [new file with mode: 0644]
doc/libvlc/QtPlayer/player.cpp [new file with mode: 0644]
doc/libvlc/QtPlayer/player.h [new file with mode: 0644]
doc/libvlc/gtk_player.c [new file with mode: 0644]
doc/libvlc/libvlc_DVD_ripper.c [new file with mode: 0644]
doc/libvlc/wx_player.cpp [new file with mode: 0644]

diff --git a/doc/libvlc/QtPlayer/LICENSE b/doc/libvlc/QtPlayer/LICENSE
new file mode 100644 (file)
index 0000000..39a257d
--- /dev/null
@@ -0,0 +1,13 @@
+            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+                    Version 2, December 2004
+
+ Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
+
+ Everyone is permitted to copy and distribute verbatim or modified
+ copies of this license document, and changing it is allowed as long
+ as the name is changed.
+
+            DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. You just DO WHAT THE FUCK YOU WANT TO. 
diff --git a/doc/libvlc/QtPlayer/QtVLC.pro b/doc/libvlc/QtPlayer/QtVLC.pro
new file mode 100644 (file)
index 0000000..c050c97
--- /dev/null
@@ -0,0 +1,9 @@
+TEMPLATE = app
+TARGET = qtvlc
+DEPENDPATH += .
+INCLUDEPATH += .
+LIBS += -lvlc -lX11
+
+# Input
+HEADERS += player.h
+SOURCES += main.cpp player.cpp
diff --git a/doc/libvlc/QtPlayer/main.cpp b/doc/libvlc/QtPlayer/main.cpp
new file mode 100644 (file)
index 0000000..4ebf3f9
--- /dev/null
@@ -0,0 +1,26 @@
+/******************************
+ * Qt player using libVLC     *
+ * By protonux                *
+ *                            *
+ * Under WTFPL                *
+ ******************************/
+
+#include <QApplication>
+#include "player.h"
+
+#ifdef Q_WS_X11
+    #include <X11/Xlib.h>
+#endif
+
+int main(int argc, char *argv[]) {
+#ifdef Q_WS_X11
+    XInitThreads();
+#endif
+
+    QApplication app(argc, argv);
+
+    Mwindow player;
+    player.show();
+
+    return app.exec();
+}
diff --git a/doc/libvlc/QtPlayer/player.cpp b/doc/libvlc/QtPlayer/player.cpp
new file mode 100644 (file)
index 0000000..1aa6c8b
--- /dev/null
@@ -0,0 +1,210 @@
+/******************************
+ * Qt player using libVLC     *
+ * By protonux                *
+ *                            *
+ * Under WTFPL                *
+ ******************************/
+#include "player.h"
+#include <vlc/vlc.h>
+
+#define qtu( i ) ((i).toUtf8().constData())
+
+#include <QtGui>
+
+Mwindow::Mwindow() {
+    vlcPlayer = NULL;
+
+    /* Init libVLC */
+    if((vlcObject = libvlc_new(0,NULL)) == NULL) {
+        printf("Could not init libVLC");
+        exit(1);
+    }
+
+    /* Display libVLC version */
+    printf("libVLC version: %s\n",libvlc_get_version());
+
+    /* Interface initialisation */
+    initMenus();
+    initComponents();
+}
+
+Mwindow::~Mwindow() {
+    if(vlcObject)
+        libvlc_release(vlcObject);
+}
+
+void Mwindow::initMenus() {
+
+    centralWidget = new QWidget;
+
+    videoWidget = new QWidget;
+    videoWidget->setAutoFillBackground( true );
+    QPalette plt = palette();
+    plt.setColor( QPalette::Window, Qt::black );
+    videoWidget->setPalette( plt );
+
+    QMenu *fileMenu = menuBar()->addMenu("&File");
+    QMenu *editMenu = menuBar()->addMenu("&Edit");
+
+    QAction *Open = new QAction("&Open", this);
+    QAction *Quit = new QAction("&Quit", this);
+    QAction *playAc = new QAction("&Play/Pause", this);
+
+    Open->setShortcut(QKeySequence("Ctrl+O"));
+    Quit->setShortcut(QKeySequence("Ctrl+Q"));
+
+    fileMenu->addAction(Open);
+    fileMenu->addAction(Quit);
+    editMenu->addAction(playAc);
+
+    connect(Open, SIGNAL(triggered()), this, SLOT(openFile()));
+    connect(playAc, SIGNAL(triggered()), this, SLOT(play()));
+    connect(Quit, SIGNAL(triggered()), qApp, SLOT(quit()));
+}
+
+void Mwindow::initComponents() {
+
+    playBut = new QPushButton("Play");
+    QObject::connect(playBut, SIGNAL(clicked()), this, SLOT(play()));
+
+    stopBut = new QPushButton("Stop");
+    QObject::connect(stopBut, SIGNAL(clicked()), this, SLOT(stop()));
+
+    muteBut = new QPushButton("Mute");
+    QObject::connect(muteBut, SIGNAL(clicked()), this, SLOT(mute()));
+
+    volumeSlider = new QSlider(Qt::Horizontal);
+    QObject::connect(volumeSlider, SIGNAL(sliderMoved(int)), this, SLOT(changeVolume(int)));
+    volumeSlider->setValue(80);
+
+    slider = new QSlider(Qt::Horizontal);
+    slider->setMaximum(1000);
+    QObject::connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(changePosition(int)));
+
+    QTimer *timer = new QTimer(this);
+    connect(timer, SIGNAL(timeout()), this, SLOT(updateInterface()));
+    timer->start(100);
+
+    QHBoxLayout *layout = new QHBoxLayout;
+    layout->addWidget(playBut);
+    layout->addWidget(stopBut);
+    layout->addWidget(muteBut);
+    layout->addWidget(volumeSlider);
+
+    QVBoxLayout *layout2 = new QVBoxLayout;
+    layout2->addWidget(videoWidget);
+    layout2->addWidget(slider);
+    layout2->addLayout(layout);
+
+    centralWidget->setLayout(layout2);
+    setCentralWidget(centralWidget);
+    resize( 600, 400);
+}
+
+void Mwindow::openFile() {
+    /* Just the basic file-select box */
+    QString fileOpen = QFileDialog::getOpenFileName(this,tr("Load a file"), "~");
+
+    /* Stop if something is playing */
+    if( vlcPlayer && libvlc_media_player_is_playing(vlcPlayer) )
+        stop();
+
+    /* New Media */
+    libvlc_media_t *vlcMedia = libvlc_media_new_path(vlcObject,qtu(fileOpen));
+    if( !vlcMedia )
+        return;
+
+    vlcPlayer = libvlc_media_player_new_from_media (vlcMedia);
+    libvlc_media_release(vlcMedia);
+
+    /* Integrate the video in the interface */
+#if defined(Q_OS_MAC)
+    libvlc_media_player_set_nsobject(vlcPlayer, videoWidget->winId());
+#elif defined(Q_OS_UNIX)
+    libvlc_media_player_set_xwindow(vlcPlayer, videoWidget->winId());
+#elif defined(Q_OS_WIN)
+    libvlc_media_player_set_hwnd(vlcPlayer, videoWidget->winId());
+#endif
+
+    /* And play */
+    libvlc_media_player_play (vlcPlayer);
+
+    //Set vars and text correctly
+    playBut->setText("Pause");
+}
+
+void Mwindow::play() {
+
+    if(vlcPlayer)
+    {
+        if (libvlc_media_player_is_playing(vlcPlayer))
+        {
+            libvlc_media_player_pause(vlcPlayer);
+            playBut->setText("Play");
+        }
+        else
+        {
+            libvlc_media_player_play(vlcPlayer);
+            playBut->setText("Pause");
+        }
+    }
+}
+
+int Mwindow::changeVolume(int vol) { //Called if you change the volume slider
+
+    if(vlcPlayer)
+        return libvlc_audio_set_volume (vlcPlayer,vol);
+
+    return 0;
+}
+
+void Mwindow::changePosition(int pos) { //Called if you change the position slider
+
+    if(vlcPlayer) //It segfault if vlcPlayer don't exist
+        libvlc_media_player_set_position(vlcPlayer,(float)pos/(float)1000);
+}
+
+void Mwindow::updateInterface() { //Update interface and check if song is finished
+
+    if(vlcPlayer) //It segfault if vlcPlayer don't exist
+    {
+        /* update the timeline */
+        float pos = libvlc_media_player_get_position(vlcPlayer);
+        int siderPos=(int)(pos*(float)(1000));
+        slider->setValue(siderPos);
+
+        /* Stop the media */
+        if (libvlc_media_player_get_state(vlcPlayer) == 6) { this->stop(); }
+    }
+}
+
+void Mwindow::stop() {
+    if(vlcPlayer) {
+        libvlc_media_player_stop(vlcPlayer);
+        libvlc_media_player_release(vlcPlayer);
+        slider->setValue(0);
+        playBut->setText("Play");
+    }
+    vlcPlayer = NULL;
+}
+
+void Mwindow::mute() {
+    if(vlcPlayer) {
+        if(volumeSlider->value() == 0) { //if already muted...
+
+                this->changeVolume(80);
+                volumeSlider->setValue(80);
+
+        } else { //else mute volume
+
+                this->changeVolume(0);
+                volumeSlider->setValue(0);
+
+        }
+    }
+}
+
+void Mwindow::closeEvent(QCloseEvent *event) {
+    stop();
+    event->accept();
+}
diff --git a/doc/libvlc/QtPlayer/player.h b/doc/libvlc/QtPlayer/player.h
new file mode 100644 (file)
index 0000000..4cba9fa
--- /dev/null
@@ -0,0 +1,52 @@
+/******************************
+ * Qt player using libVLC     *
+ * By protonux                *
+ *                            *
+ * Under WTFPL                *
+ ******************************/
+
+#ifndef PLAYER
+#define PLAYER
+
+#include <QtGui>
+#include <vlc/vlc.h>
+
+class Mwindow : public QMainWindow {
+
+    Q_OBJECT
+
+        public:
+               Mwindow();
+               virtual ~Mwindow();
+
+        private slots:
+               void openFile();
+               void play();
+               void stop();
+               void mute();
+
+               int changeVolume(int);
+               void changePosition(int);
+               void updateInterface();
+
+        protected:
+               virtual void closeEvent(QCloseEvent*);
+
+        private:
+               QString current;
+               QPushButton *playBut;
+               QPushButton *stopBut;
+               QPushButton *muteBut;
+               QSlider *volumeSlider;
+               QSlider *slider;
+               QWidget *videoWidget;
+               QWidget *centralWidget;
+               libvlc_instance_t *vlcObject;
+               libvlc_media_player_t *vlcPlayer;
+
+               void initMenus();
+               void initComponents();
+};
+
+
+#endif
diff --git a/doc/libvlc/gtk_player.c b/doc/libvlc/gtk_player.c
new file mode 100644 (file)
index 0000000..8196476
--- /dev/null
@@ -0,0 +1,141 @@
+// gcc -o gtk_player gtk_player.c `pkg-config --libs gtk+-2.0 libvlc` `pkg-config --cflags gtk+-2.0 libvlc`
+
+/* License WTFPL http://sam.zoy.org/wtfpl/ */
+/* Written by Vincent Schüßler */
+
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <vlc/vlc.h>
+
+#define BORDER_WIDTH 6
+
+void destroy(GtkWidget *widget, gpointer data);
+void player_widget_on_realize(GtkWidget *widget, gpointer data);
+void on_open(GtkWidget *widget, gpointer data);
+void open_media(const char* uri);
+void play(void);
+void pause_player(void);
+void on_playpause(GtkWidget *widget, gpointer data);
+void on_stop(GtkWidget *widget, gpointer data);
+
+libvlc_media_player_t *media_player;
+libvlc_instance_t *vlc_inst;
+GtkWidget *playpause_button;
+
+void destroy(GtkWidget *widget, gpointer data) {
+    gtk_main_quit();
+}
+
+void player_widget_on_realize(GtkWidget *widget, gpointer data) {
+    libvlc_media_player_set_xwindow(media_player, GDK_WINDOW_XID(gtk_widget_get_window(widget)));
+}
+
+void on_open(GtkWidget *widget, gpointer data) {
+    GtkWidget *dialog;
+    dialog = gtk_file_chooser_dialog_new("Choose Media", data, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
+    if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+        char *uri;
+        uri = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(dialog));
+        open_media(uri);
+        g_free(uri);
+    }
+    gtk_widget_destroy(dialog);
+}
+
+void open_media(const char* uri) {
+    libvlc_media_t *media;
+    media = libvlc_media_new_location(vlc_inst, uri);
+    libvlc_media_player_set_media(media_player, media);
+    play();
+    libvlc_media_release(media);
+}
+
+void on_playpause(GtkWidget *widget, gpointer data) {
+    if(libvlc_media_player_is_playing(media_player) == 1) {
+        pause_player();
+    }
+    else {
+        play();
+    }
+}
+
+void on_stop(GtkWidget *widget, gpointer data) {
+    pause_player();
+    libvlc_media_player_stop(media_player);
+}
+
+void play(void) {
+    libvlc_media_player_play(media_player);
+    gtk_button_set_label(GTK_BUTTON(playpause_button), "gtk-media-pause");
+}
+
+void pause_player(void) {
+    libvlc_media_player_pause(media_player);
+    gtk_button_set_label(GTK_BUTTON(playpause_button), "gtk-media-play");
+}
+
+int main( int argc, char *argv[] ) {
+    GtkWidget *window,
+              *vbox,
+              *menubar,
+              *filemenu,
+              *fileitem,
+              *filemenu_openitem,
+              *player_widget,
+              *hbuttonbox,
+              *stop_button;
+    
+    gtk_init (&argc, &argv);
+    // setup window
+    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_window_set_default_size(GTK_WINDOW(window), 400, 300);
+    g_signal_connect(window, "destroy", G_CALLBACK(destroy), NULL);
+    gtk_container_set_border_width (GTK_CONTAINER (window), 0);
+    gtk_window_set_title(GTK_WINDOW(window), "GTK+ libVLC Demo");
+
+    //setup vbox
+    vbox = gtk_vbox_new(FALSE, 0);
+    gtk_container_add(GTK_CONTAINER(window), vbox);
+
+    //setup menu
+    menubar = gtk_menu_bar_new();
+    filemenu = gtk_menu_new();
+    fileitem = gtk_menu_item_new_with_label ("File");
+    filemenu_openitem = gtk_menu_item_new_with_label("Open");
+    gtk_menu_shell_append(GTK_MENU_SHELL(filemenu), filemenu_openitem);
+    gtk_menu_item_set_submenu(GTK_MENU_ITEM(fileitem), filemenu);
+    gtk_menu_bar_append(GTK_MENU_BAR(menubar), fileitem);
+    gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, FALSE, 0);
+    g_signal_connect(filemenu_openitem, "activate", G_CALLBACK(on_open), window);
+
+    //setup player widget
+    player_widget = gtk_drawing_area_new();
+    gtk_box_pack_start(GTK_BOX(vbox), player_widget, TRUE, TRUE, 0);
+
+    //setup controls
+    //playpause_button = gtk_button_new_from_stock(GTK_STOCK_MEDIA_PLAY);
+    playpause_button = gtk_button_new_with_label("gtk-media-play");
+    gtk_button_set_use_stock(GTK_BUTTON(playpause_button), TRUE);
+    stop_button = gtk_button_new_from_stock(GTK_STOCK_MEDIA_STOP);
+    g_signal_connect(playpause_button, "clicked", G_CALLBACK(on_playpause), NULL);
+    g_signal_connect(stop_button, "clicked", G_CALLBACK(on_stop), NULL);
+    hbuttonbox = gtk_hbutton_box_new();
+    gtk_container_set_border_width(GTK_CONTAINER(hbuttonbox), BORDER_WIDTH);
+    gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_START);
+    gtk_box_pack_start(GTK_BOX(hbuttonbox), playpause_button, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(hbuttonbox), stop_button, FALSE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), hbuttonbox, FALSE, FALSE, 0);
+
+    //setup vlc
+    vlc_inst = libvlc_new(0, NULL);
+    media_player = libvlc_media_player_new(vlc_inst);
+    g_signal_connect(G_OBJECT(player_widget), "realize", G_CALLBACK(player_widget_on_realize), NULL);
+
+    gtk_widget_show_all(window);
+    gtk_main ();
+
+    libvlc_media_player_release(media_player);
+    libvlc_release(vlc_inst);
+    return 0;
+}
diff --git a/doc/libvlc/libvlc_DVD_ripper.c b/doc/libvlc/libvlc_DVD_ripper.c
new file mode 100644 (file)
index 0000000..57fc896
--- /dev/null
@@ -0,0 +1,306 @@
+// gcc -o main main.c `pkg-config --cflags --libs gtk+-2.0 libvlc`
+
+/* Written by Vincent Schüßler */
+/* License WTFPL http://sam.zoy.org/wtfpl/ */
+
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <gtk/gtk.h>
+#include <vlc/vlc.h>
+
+#define PRESET_H264_AAC_MP4_HIGH "MP4 high (h.264 + AAC)"
+#define PRESET_H264_AAC_MP4_LOW "MP4 low (h.264 + AAC)"
+#define PRESET_THEORA_VORBIS_OGG_HIGH "OGG high (Theora + Vorbis)"
+#define PRESET_THEORA_VORBIS_OGG_LOW "OGG low (Theora + Vorbis)"
+#define PRESET_VP8_VORBIS_WEBM_HIGH "WebM high (VP8 + Vorbis)"
+#define PRESET_VP8_VORBIS_WEBM_LOW "WebM low (VP8 + Vorbis)"
+#define BORDER_WIDTH 6
+
+GtkWidget *window;
+GtkWidget *source_entry, *dest_entry;
+GtkWidget *progressbar;
+libvlc_instance_t *vlcinst;
+libvlc_media_list_t *medialist;
+GtkWidget *run_button, *format_chooser, *spinner;
+char stopped;
+
+gchar* get_filepath(GtkWidget* widget, GtkFileChooserAction action) {
+    GtkWidget *dialog;
+    gchar *path;
+    dialog = gtk_file_chooser_dialog_new("Choose location", GTK_WINDOW(gtk_widget_get_toplevel(widget)), action, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
+    if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
+        path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
+    }
+    else {
+        path = NULL;
+    }
+    gtk_widget_destroy(dialog);
+    return path;
+}
+
+void on_select_source_path(GtkWidget *widget, gpointer data) {
+    char *path;
+    char scheme[] = "file://";
+    char *uri;
+
+    if(data==NULL) {
+        path = (char*) get_filepath(widget, GTK_FILE_CHOOSER_ACTION_OPEN);
+    }
+    else {
+        path = (char*) get_filepath(widget, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
+    }
+    if(path != NULL) {
+        uri = malloc((strlen(scheme)+strlen(path)+1) * sizeof(char));
+        if(uri == NULL) return;
+        uri[0] = '\0';
+        strncat(uri, scheme, strlen(scheme));
+        strncat(uri, path, strlen(path));
+        g_free(path);
+        
+        gtk_entry_set_text(GTK_ENTRY(source_entry), uri);
+        free(uri);
+    }
+}
+
+void on_select_dest_path(GtkWidget *widget, gpointer data) {
+    gchar *path;
+    path = get_filepath(widget, GTK_FILE_CHOOSER_ACTION_SAVE);
+    if(path != NULL) {
+        gtk_entry_set_text(GTK_ENTRY(dest_entry), path);
+        g_free(path);
+    }
+}
+
+char* get_pos_string(float pos) {
+    int len;
+    const char format[] = "%.3f %%";
+    char *pos_string;
+    pos *= 100;
+    len = snprintf(NULL, 0, format, pos);
+    pos_string = malloc(len);
+    if(pos_string==NULL) return NULL;
+    sprintf(pos_string, format, pos);
+    return pos_string;
+}
+
+gboolean update_progressbar(char *handle) {
+    float pos = libvlc_vlm_get_media_instance_position(vlcinst, handle, 0);
+    char *pos_string;
+    if(pos < 1.0 && 0.0 <= pos) {
+        gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), pos);
+        pos_string = get_pos_string(pos);
+        if(pos_string != NULL) {
+            gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progressbar), pos_string);
+            free(pos_string);
+        }
+        return TRUE;
+    }
+    if(stopped = 1) {
+        free(handle);
+        return FALSE;
+    }
+}
+
+const char* get_transcode_string(char *preset) {
+    static const char mp4_high[] = "#transcode{vcodec=h264,venc=x264{cfr=16},scale=1,acodec=mp4a,ab=160,channels=2,samplerate=44100}";
+    static const char mp4_low[] = "#transcode{vcodec=h264,venc=x264{cfr=40},scale=1,acodec=mp4a,ab=96,channels=2,samplerate=44100}";
+    static const char ogg_high[] = "#transcode{vcodec=theo,venc=theora{quality=9},scale=1,acodec=vorb,ab=160,channels=2,samplerate=44100}";
+    static const char ogg_low[] = "#transcode{vcodec=theo,venc=theora{quality=4},scale=1,acodec=vorb,ab=96,channels=2,samplerate=44100}";
+    static const char webm_high[] = "#transcode{vcodec=VP80,vb=2000,scale=1,acodec=vorb,ab=160,channels=2,samplerate=44100}";
+    static const char webm_low[] = "#transcode{vcodec=VP80,vb=1000,scale=1,acodec=vorb,ab=96,channels=2,samplerate=44100}";
+    static const char nothing[] = "";
+    if(0 == strcmp(preset, PRESET_H264_AAC_MP4_HIGH)) {
+        return mp4_high;
+    }
+    else if(0 == strcmp(preset, PRESET_H264_AAC_MP4_LOW)) {
+        return mp4_low;
+    }
+    else if(0 == strcmp(preset, PRESET_THEORA_VORBIS_OGG_HIGH)) {
+        return ogg_high;
+    }
+    else if(0 == strcmp(preset, PRESET_THEORA_VORBIS_OGG_LOW)) {
+        return ogg_low;
+    }
+    else if(0 == strcmp(preset, PRESET_VP8_VORBIS_WEBM_HIGH)) {
+        return webm_high;
+    }
+    else if(0 == strcmp(preset, PRESET_VP8_VORBIS_WEBM_LOW)) {
+        return webm_low;
+    }
+    else {
+        return nothing;
+    }
+}
+
+void on_run(GtkWidget *widget, gpointer data) {
+    char *handle;
+    const char *transcode;
+    char *source = (char*) gtk_entry_get_text(GTK_ENTRY(source_entry));
+    char *dest = (char*) gtk_entry_get_text(GTK_ENTRY(dest_entry));
+    char *preset= (char*) gtk_combo_box_get_active_text(GTK_COMBO_BOX(format_chooser));
+    int i;
+    char file_begin[] = ":file{dst=";
+    char file_end[] = "}";
+    char *sout;
+    if(preset == NULL) return;
+    gtk_widget_set_sensitive(widget, FALSE);
+    handle = malloc((strlen(source)+4+1) * sizeof(char));
+    if(handle == NULL) return;
+    strncpy(handle, source, strlen(source));
+    for(i=0;i<=3;++i) {
+        handle[strlen(source)+i] = (char) (((unsigned int) rand()) & 63) + '0';
+    }
+    handle[strlen(source)+4] = '\0';
+    transcode = get_transcode_string(preset);
+    free(preset);
+    sout = malloc((strlen(transcode)+strlen(file_begin)+strlen(dest)+strlen(file_end)+1) * sizeof(char));
+    if(sout == NULL) return;
+    strncpy(sout, transcode, strlen(transcode)+1);
+    strncat(sout, file_begin, strlen(file_begin));
+    strncat(sout, dest, strlen(dest));
+    strncat(sout, file_end, strlen(file_end));
+    libvlc_vlm_add_broadcast(vlcinst, handle, source, sout, 0, NULL, 1, 0);
+    free(sout);
+    libvlc_vlm_play_media(vlcinst, handle);
+    gtk_widget_show(spinner);
+    gtk_spinner_start(GTK_SPINNER(spinner));
+    stopped = 0;
+    g_timeout_add(50, (GSourceFunc) update_progressbar, handle);
+}
+
+void stop(void) {
+    stopped = 1;
+    gtk_spinner_stop(GTK_SPINNER(spinner));
+    gtk_widget_hide(spinner);
+    gtk_widget_set_sensitive(run_button, TRUE);
+    gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar), 0.0);
+    gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progressbar), "");
+}
+
+gboolean on_end(void) {
+    GtkWidget *dialog;
+    stop();
+    dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, "Rip done");
+    gtk_dialog_run(GTK_DIALOG(dialog));
+    gtk_widget_destroy(dialog);
+    return FALSE;
+}
+
+void on_end_vlc(const libvlc_event_t *event, void *data) {
+    g_idle_add((GSourceFunc) on_end, NULL);
+}
+
+gboolean on_error(void) {
+    GtkWidget *dialog;
+    stop();
+    dialog = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Error");gtk_dialog_run(GTK_DIALOG(dialog));
+    gtk_widget_destroy(dialog);
+    return FALSE;
+}
+
+void on_error_vlc(const libvlc_event_t *event, void *data) {
+    g_idle_add((GSourceFunc) on_error, NULL);
+}
+
+int main (int argc, char *argv[]) {
+    GtkWidget *media_list, *scrolled;
+    GtkWidget *choose_frame, *output_frame, *run_frame;
+    GtkWidget *vbox, *choose_table, *output_table, *run_table;
+    GtkWidget *source_label, *source_button, *source_folder_button;
+    GtkWidget *dest_label, *dest_button;
+
+    libvlc_event_manager_t *evtman;
+
+    gtk_init(&argc, &argv);
+
+    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+    gtk_container_set_border_width(GTK_CONTAINER(window), BORDER_WIDTH);
+    gtk_window_set_title(GTK_WINDOW(window), "libVLC DVD ripper");
+
+    //setup vbox
+    vbox = gtk_vbox_new(FALSE, BORDER_WIDTH);
+    gtk_container_add(GTK_CONTAINER(window), vbox);
+
+    // setup media list with scrolled window
+    media_list = gtk_tree_view_new();
+    gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(media_list), FALSE);
+    scrolled = gtk_scrolled_window_new(NULL, NULL);
+    gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_container_add(GTK_CONTAINER(scrolled), media_list);
+
+    // setup "choose"-frame
+    choose_frame = gtk_frame_new("Choose DVD");
+    gtk_box_pack_start(GTK_BOX(vbox), choose_frame, TRUE, TRUE, 0);
+    choose_table = gtk_table_new(1, 4, FALSE);
+    gtk_table_set_row_spacings(GTK_TABLE(choose_table), BORDER_WIDTH/2);
+    gtk_table_set_col_spacings(GTK_TABLE(choose_table), BORDER_WIDTH/2);
+    gtk_container_set_border_width(GTK_CONTAINER(choose_table), BORDER_WIDTH);
+    source_label = gtk_label_new("Input file or folder:");
+    source_entry = gtk_entry_new();
+    gtk_entry_set_text(GTK_ENTRY(source_entry), "dvd://");
+    source_button = gtk_button_new_with_label("Open file");
+    source_folder_button = gtk_button_new_with_label("Open folder");
+    g_signal_connect(G_OBJECT(source_button), "clicked", G_CALLBACK(on_select_source_path), NULL);
+    g_signal_connect(G_OBJECT(source_folder_button), "clicked", G_CALLBACK(on_select_source_path), (gpointer) 1);
+    gtk_table_attach(GTK_TABLE(choose_table), source_label, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+    gtk_table_attach(GTK_TABLE(choose_table), source_entry, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
+    gtk_table_attach(GTK_TABLE(choose_table), source_button, 2, 3, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+    gtk_table_attach(GTK_TABLE(choose_table), source_folder_button, 3, 4, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+    gtk_container_add(GTK_CONTAINER(choose_frame), choose_table);
+
+    // setup "output"-frame
+    output_frame = gtk_frame_new("Output settings");
+    gtk_box_pack_start(GTK_BOX(vbox), output_frame, TRUE, TRUE, 0);
+    output_table = gtk_table_new(2, 3, FALSE);
+    gtk_table_set_row_spacings(GTK_TABLE(output_table), BORDER_WIDTH/2);
+    gtk_table_set_col_spacings(GTK_TABLE(output_table), BORDER_WIDTH/2);
+    gtk_container_set_border_width(GTK_CONTAINER(output_table), BORDER_WIDTH);
+    gtk_container_add(GTK_CONTAINER(output_frame), output_table);
+    dest_label = gtk_label_new("Output file:");
+    dest_entry = gtk_entry_new();
+    format_chooser = gtk_combo_box_new_text();
+    gtk_combo_box_append_text(GTK_COMBO_BOX(format_chooser), PRESET_H264_AAC_MP4_HIGH);
+    gtk_combo_box_append_text(GTK_COMBO_BOX(format_chooser), PRESET_H264_AAC_MP4_LOW);
+    gtk_combo_box_append_text(GTK_COMBO_BOX(format_chooser), PRESET_THEORA_VORBIS_OGG_HIGH);
+    gtk_combo_box_append_text(GTK_COMBO_BOX(format_chooser), PRESET_THEORA_VORBIS_OGG_LOW);
+    gtk_combo_box_append_text(GTK_COMBO_BOX(format_chooser), PRESET_VP8_VORBIS_WEBM_HIGH);
+    gtk_combo_box_append_text(GTK_COMBO_BOX(format_chooser), PRESET_VP8_VORBIS_WEBM_LOW);
+    gtk_combo_box_set_active(GTK_COMBO_BOX(format_chooser), 0);
+    dest_button = gtk_button_new_from_stock(GTK_STOCK_OPEN);
+    g_signal_connect(G_OBJECT(dest_button), "clicked", G_CALLBACK(on_select_dest_path), NULL);
+    gtk_table_attach(GTK_TABLE(output_table), dest_label, 0, 1, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+    gtk_table_attach(GTK_TABLE(output_table), dest_entry, 1, 2, 0, 1, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
+    gtk_table_attach(GTK_TABLE(output_table), dest_button, 2, 3, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
+    gtk_table_attach(GTK_TABLE(output_table), format_chooser, 0, 4, 1, 2, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
+
+    // setup "run"-frame
+    run_frame = gtk_frame_new("Run");
+    gtk_box_pack_start(GTK_BOX(vbox), run_frame, TRUE, TRUE, 0);
+    run_table = gtk_table_new(3, 2, FALSE);
+    gtk_table_set_row_spacings(GTK_TABLE(run_table), BORDER_WIDTH/2);
+    gtk_table_set_col_spacings(GTK_TABLE(run_table), BORDER_WIDTH/2);
+    gtk_container_set_border_width(GTK_CONTAINER(run_table), BORDER_WIDTH);
+    gtk_container_add(GTK_CONTAINER(run_frame), run_table);
+    progressbar = gtk_progress_bar_new();
+    spinner = gtk_spinner_new();
+    run_button = gtk_button_new_from_stock(GTK_STOCK_OK);
+    g_signal_connect(G_OBJECT(run_button), "clicked", G_CALLBACK(on_run), NULL);
+    gtk_table_attach(GTK_TABLE(run_table), progressbar, 0, 3, 0, 1, GTK_EXPAND | GTK_FILL, GTK_SHRINK, 0, 0);
+    gtk_table_attach(GTK_TABLE(run_table), gtk_label_new(""), 0, 1, 1, 2, GTK_EXPAND, GTK_SHRINK, 0, 0);
+    gtk_table_attach(GTK_TABLE(run_table), spinner, 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+    gtk_table_attach(GTK_TABLE(run_table), run_button, 2, 3, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
+
+    // setup vlc
+    vlcinst = libvlc_new(0, NULL);
+    evtman = libvlc_vlm_get_event_manager(vlcinst);
+       libvlc_event_attach(evtman, libvlc_VlmMediaInstanceStatusEnd, on_end_vlc, NULL);
+       libvlc_event_attach(evtman, libvlc_VlmMediaInstanceStatusError, on_error_vlc, NULL);
+
+    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
+    gtk_widget_show_all(window);
+    gtk_widget_hide(spinner);
+    gtk_main ();
+    libvlc_release(vlcinst);
+    return 0;
+}
diff --git a/doc/libvlc/wx_player.cpp b/doc/libvlc/wx_player.cpp
new file mode 100644 (file)
index 0000000..fbd4a0f
--- /dev/null
@@ -0,0 +1,263 @@
+// g++ wx_player.cpp `wx-config --libs` `wx-config --cxxflags` `pkg-config --cflags gtk+-2.0 libvlc` `pkg-config --libs gtk+-2.0 libvlc` -o wx_player
+
+/* License WTFPL http://sam.zoy.org/wtfpl/ */
+/* Written by Vincent Schüßler */
+
+#include <wx/wx.h>
+#include <wx/filename.h>
+#include <vlc/vlc.h>
+#include <climits>
+
+#ifdef __WXGTK__
+    #include <gdk/gdkx.h>
+    #include <gtk/gtk.h>
+    #include <wx/gtk/win_gtk.h>
+    #define GET_XID(window) GDK_WINDOW_XWINDOW(GTK_PIZZA(window->m_wxwindow)->bin_window)
+#endif
+
+#define myID_PLAYPAUSE wxID_HIGHEST+1
+#define myID_STOP wxID_HIGHEST+2
+#define myID_TIMELINE wxID_HIGHEST+3
+#define myID_VOLUME wxID_HIGHEST+4
+
+#define TIMELINE_MAX (INT_MAX-9)
+#define VOLUME_MAX 100
+
+DECLARE_EVENT_TYPE(vlcEVT_END, -1)
+DECLARE_EVENT_TYPE(vlcEVT_POS, -1)
+DEFINE_EVENT_TYPE(vlcEVT_END)
+DEFINE_EVENT_TYPE(vlcEVT_POS)
+
+void OnPositionChanged_VLC(const libvlc_event_t *event, void *data);
+void OnEndReached_VLC(const libvlc_event_t *event, void *data);
+
+class MainWindow : public wxFrame {
+    public:
+        MainWindow(const wxString& title);
+        ~MainWindow();
+
+    private:
+        void initVLC();
+
+        void OnOpen(wxCommandEvent& event);
+        void OnPlayPause(wxCommandEvent& event);
+        void OnStop(wxCommandEvent& event);
+        void OnPositionChanged_USR(wxCommandEvent& event);
+        void OnPositionChanged_VLC(wxCommandEvent& event);
+        void OnEndReached_VLC(wxCommandEvent& event);
+        void OnVolumeChanged(wxCommandEvent& event);
+        void OnVolumeClicked(wxMouseEvent& event);
+        void OnTimelineClicked(wxMouseEvent& event);
+
+        void play();
+        void pause();
+        void stop();
+        void setTimeline(float value);
+        void connectTimeline();
+
+        wxButton *playpause_button;
+        wxButton *stop_button;
+        wxSlider *timeline;
+        wxSlider *volume_slider;
+        wxWindow *player_widget;
+
+        libvlc_media_player_t *media_player;
+        libvlc_instance_t *vlc_inst;
+        libvlc_event_manager_t *vlc_evt_man;
+};
+
+MainWindow *mainWindow;
+
+MainWindow::MainWindow(const wxString& title) : wxFrame(NULL, wxID_ANY, title, wxDefaultPosition) {
+    // setup menubar
+    wxMenuBar *menubar;
+    wxMenu *file;
+    menubar = new wxMenuBar;
+    file = new wxMenu;
+    file->Append(wxID_OPEN, wxT("&Open"));
+    menubar->Append(file, wxT("&File"));
+    SetMenuBar(menubar);
+    Connect(wxID_OPEN, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MainWindow::OnOpen));
+
+    // setup vbox
+    wxBoxSizer *vbox = new wxBoxSizer(wxVERTICAL);
+    this->SetSizer(vbox);
+
+    //setup player widget
+    player_widget = new wxWindow(this, wxID_ANY);
+    player_widget->SetBackgroundColour(wxColour(wxT("black")));
+    vbox->Add(player_widget, 1, wxEXPAND | wxALIGN_TOP);
+
+    //setup timeline slider
+    timeline = new wxSlider(this, myID_TIMELINE, 0, 0, TIMELINE_MAX);
+    timeline->Enable(false);
+    vbox->Add(timeline, 0, wxEXPAND);
+    connectTimeline();
+    timeline->Connect(myID_TIMELINE, wxEVT_LEFT_UP, wxMouseEventHandler(MainWindow::OnTimelineClicked));
+
+    //setup control panel
+    wxPanel *controlPanel = new wxPanel(this, wxID_ANY);
+
+    //setup hbox
+    wxBoxSizer *hbox = new wxBoxSizer(wxHORIZONTAL);
+    controlPanel->SetSizer(hbox);
+    vbox->Add(controlPanel, 0, wxEXPAND);
+
+    //setup controls
+    playpause_button = new wxButton(controlPanel, myID_PLAYPAUSE, wxT("Play"));
+    stop_button = new wxButton(controlPanel, myID_STOP, wxT("Stop"));
+    volume_slider = new wxSlider(controlPanel, myID_VOLUME, VOLUME_MAX, 0, VOLUME_MAX, wxDefaultPosition, wxSize(100, -1));
+    playpause_button->Enable(false);
+    stop_button->Enable(false);
+    hbox->Add(playpause_button);
+    hbox->Add(stop_button);
+    hbox->AddStretchSpacer();
+    hbox->Add(volume_slider);
+    Connect(myID_PLAYPAUSE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainWindow::OnPlayPause));
+    Connect(myID_STOP, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MainWindow::OnStop));
+    Connect(myID_VOLUME, wxEVT_COMMAND_SLIDER_UPDATED, wxCommandEventHandler(MainWindow::OnVolumeChanged));
+    volume_slider->Connect(myID_VOLUME, wxEVT_LEFT_UP, wxMouseEventHandler(MainWindow::OnVolumeClicked));
+
+    //setup vlc
+    vlc_inst = libvlc_new(0, NULL);
+    media_player = libvlc_media_player_new(vlc_inst);
+    vlc_evt_man = libvlc_media_player_event_manager(media_player);
+    libvlc_event_attach(vlc_evt_man, libvlc_MediaPlayerEndReached, ::OnEndReached_VLC, NULL);
+    libvlc_event_attach(vlc_evt_man, libvlc_MediaPlayerPositionChanged, ::OnPositionChanged_VLC, NULL);
+    Connect(wxID_ANY, vlcEVT_END, wxCommandEventHandler(MainWindow::OnEndReached_VLC));
+    Connect(wxID_ANY, vlcEVT_POS, wxCommandEventHandler(MainWindow::OnPositionChanged_VLC));
+
+    Show(true);
+    initVLC();
+}
+
+MainWindow::~MainWindow() {
+    libvlc_media_player_release(media_player);
+    libvlc_release(vlc_inst);
+}
+
+void MainWindow::initVLC() {
+    #ifdef __WXGTK__
+        libvlc_media_player_set_xwindow(media_player, GET_XID(this->player_widget));
+    #else
+        libvlc_media_player_set_hwnd(media_player, this->player_widget->GetHandle());
+    #endif
+}
+
+void MainWindow::OnOpen(wxCommandEvent& event) {
+    wxFileDialog openFileDialog(this, wxT("Choose File"));
+
+    if (openFileDialog.ShowModal() == wxID_CANCEL) {
+        return;
+    }
+    else {
+        libvlc_media_t *media;
+        wxFileName filename = wxFileName::FileName(openFileDialog.GetPath());
+        filename.MakeRelativeTo();
+        media = libvlc_media_new_path(vlc_inst, filename.GetFullPath().mb_str());
+        libvlc_media_player_set_media(media_player, media);
+        play();
+        libvlc_media_release(media);
+    }
+}
+
+void MainWindow::OnPlayPause(wxCommandEvent& event) {
+    if(libvlc_media_player_is_playing(media_player) == 1) {
+        pause();
+    }
+    else {
+        play();
+    }
+}
+
+void MainWindow::OnStop(wxCommandEvent& event) {
+    stop();
+}
+
+void MainWindow::OnPositionChanged_USR(wxCommandEvent& event) {
+    libvlc_media_player_set_position(media_player, (float) event.GetInt() / (float) TIMELINE_MAX);
+}
+
+void MainWindow::OnPositionChanged_VLC(wxCommandEvent& event) {
+    float factor = libvlc_media_player_get_position(media_player);
+    setTimeline(factor);
+}
+
+void MainWindow::OnEndReached_VLC(wxCommandEvent& event) {
+    stop();
+}
+
+void MainWindow::OnVolumeChanged(wxCommandEvent& event) {
+    libvlc_audio_set_volume(media_player, volume_slider->GetValue());
+}
+
+void MainWindow::OnVolumeClicked(wxMouseEvent& event) {
+    wxSize size = mainWindow->volume_slider->GetSize();
+    float position = (float) event.GetX() / (float) size.GetWidth();
+    mainWindow->volume_slider->SetValue(position*VOLUME_MAX);
+    libvlc_audio_set_volume(mainWindow->media_player, position*VOLUME_MAX);
+    event.Skip();
+}
+
+void MainWindow::OnTimelineClicked(wxMouseEvent& event) {
+    wxSize size = mainWindow->timeline->GetSize();
+    float position = (float) event.GetX() / (float) size.GetWidth();
+    libvlc_media_player_set_position(mainWindow->media_player, position);
+    mainWindow->setTimeline(position);
+    event.Skip();
+}
+
+void MainWindow::play() {
+    libvlc_media_player_play(media_player);
+    playpause_button->SetLabel(wxT("Pause"));
+    playpause_button->Enable(true);
+    stop_button->Enable(true);
+    timeline->Enable(true);
+}
+
+void MainWindow::pause() {
+    libvlc_media_player_pause(media_player);
+    playpause_button->SetLabel(wxT("Play"));
+}
+
+void MainWindow::stop() {
+    pause();
+    libvlc_media_player_stop(media_player);
+    stop_button->Enable(false);
+    setTimeline(0.0);
+    timeline->Enable(false);
+}
+
+void MainWindow::setTimeline(float value) {
+    if(value < 0.0) value = 0.0;
+    if(value > 1.0) value = 1.0;
+    Disconnect(myID_TIMELINE);
+    timeline->SetValue((int) (value * TIMELINE_MAX));
+    connectTimeline();
+}
+
+void MainWindow::connectTimeline() {
+    Connect(myID_TIMELINE, wxEVT_COMMAND_SLIDER_UPDATED, wxCommandEventHandler(MainWindow::OnPositionChanged_USR));
+}
+
+class MyApp : public wxApp {
+    public:
+        virtual bool OnInit();
+};
+
+void OnPositionChanged_VLC(const libvlc_event_t *event, void *data) {
+    wxCommandEvent evt(vlcEVT_POS, wxID_ANY);
+    mainWindow->AddPendingEvent(evt);
+}
+
+void OnEndReached_VLC(const libvlc_event_t *event, void *data) {
+    wxCommandEvent evt(vlcEVT_END, wxID_ANY);
+    mainWindow->AddPendingEvent(evt);
+}
+
+bool MyApp::OnInit() {
+    mainWindow = new MainWindow(wxT("wxWidgets libVLC demo"));
+    return true;
+}
+
+IMPLEMENT_APP(MyApp)