Index: share/luasubtitles/opensubtitles.lua
===================================================================
--- share/luasubtitles/opensubtitles.lua	(révision 0)
+++ share/luasubtitles/opensubtitles.lua	(révision 0)
@@ -0,0 +1,164 @@
+-- Author: Jean-Philippe ANDRE <jpeg CHEZ via POINT ecp POINT fr>
+-- TODO: proprifier le code, corriger l'anglais,
+-- faire quelque chose de chouette, quoi
+
+
+-- These two first functions are designed to parse an XML file
+function parseargs(s)
+    local arg = {}
+    string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a)
+    arg[w] = a
+    end)
+    return arg
+end
+
+function collect(s)
+    local stack = {}
+    local top = {}
+    table.insert(stack, top)
+    local ni,c,label,xarg, empty
+    local i, j = 1, 1
+
+    while true do
+        ni,j,c,label,xarg, empty = string.find(s, "<(%/?)(%w+)(.-)(%/?)>", j)
+        if not ni then break end
+        local text = string.sub(s, i, ni-1)
+        if not string.find(text, "^%s*$") then
+            table.insert(top, text)
+        end
+        if empty == "/" then  -- empty element tag
+    --         print( label ) 
+            table.insert(top, {label=label, xarg=parseargs(xarg), empty=1})
+        elseif c == "" then   -- start tag
+            top = {label=label, xarg=parseargs(xarg)}
+    --         print( top.label )
+            table.insert(stack, top)   -- new level
+        else  -- end tag
+            local toclose = table.remove(stack)  -- remove top
+            top = stack[#stack]
+            if #stack < 1 then
+            error("nothing to close with "..label)
+            end
+            if toclose.label ~= label then
+            error("trying to close "..toclose.label.." with "..label)
+            end
+    --         print( toclose.label )
+            table.insert(top, toclose)
+        end
+        i = j+1
+    end
+
+    local text = string.sub(s, i)
+    if not string.find(text, "^%s*$") then
+    table.insert(stack[stack.n], text)
+    end
+    if #stack > 1 then
+    error("unclosed "..stack[stack.n].label)
+    end
+    return stack[1]
+end
+-- Return the artwork
+function fetch_sublist()
+    if vlc.title then
+        title = vlc.title
+    else
+        return nil
+    end
+
+    -- Look on OpenSubtitles.Org
+    -- http://www.opensubtitles.com/en/search/sublanguageid-eng/moviename-the%20wall/simplexml
+    lang = "fre"
+    if vlc.language then
+        lang = vlc.language
+    end
+    
+    xmlurl = "http://www.opensubtitles.org/en/search/sublanguageid-" .. lang .. "/moviename-" .. title .. "/simplexml"
+--    print( "Opening " .. xmlurl )
+    fd = vlc.stream_new( xmlurl )
+    xmlpage = vlc.stream_read( fd, 65653 )
+    vlc.stream_delete( fd )
+--    print( "We received :" )
+--    print( xmlpage )
+    if xmlpage == nil then return nil end
+    
+--     local fd = io.open( "/home/videolan/vlc/trunk/share/luameta/example.xml" )
+--     local xmlpage = fd:read( "*a" )
+--     io.close( fd )
+    
+    local xmldata = collect( xmlpage )
+    for a,b in pairs(xmldata) do
+        if type(b) == "table" then
+            if b.label == "search" then
+                xmldata = b
+            end
+        end
+    end
+
+    if xmldata == nil then return nil end
+
+    -- Subtitles information data
+    local subname = {}
+    local suburl = {}
+    local sublang = {}
+    local subformat = {}
+    local subfilenum = {}
+    local subnum = 1
+    local baseurl = ""
+    
+    -- Let's browse iteratively the 'xmldata' tree
+    -- OK, the variables' names aren't explicit enough, but just remember a couple
+    -- a,b contains the index (a) and the data (b) of the table, which might also be a table
+    for a,b in pairs(xmldata) do
+        if type(b) == "table" then
+            if b.label == "results" then
+                for c,d in pairs(b) do
+                    if type(d) == "table" then
+                        if d.label == "subtitle" then
+                            for e,f in pairs(d) do
+                                if type(f) == "table" then
+                                    if f.label == "releasename" then
+                                        if f[1] ~= nil then subname[subnum] = f[1]
+                                        else subname[subnum] = "" end
+                                    else if f.label == "download" then
+                                        if f[1] ~= nil then suburl[subnum] = f[1]
+                                        else suburl[subnum] = "" end
+                                    else if f.label == "language" then
+                                        if f[1] ~= nil then sublang[subnum] = f[1]
+                                        else sublang[subnum] = "" end
+                                    else if f.label == "files" then
+                                        if f[1] ~= nil then subfilenum[subnum] = f[1]
+                                        else subfilenum[subnum] = "" end
+                                    else if f.label == "format" then
+                                        if f[1] ~= nil then subformat[subnum] = f[1]
+                                        else subformat[subnum] = "" end
+                                    end end end end end
+                                end
+                            end
+                            subnum = subnum + 1
+                        end
+                    end
+                end
+            else if b.label == "base" then
+                baseurl = b[1]
+            end end
+        end
+    end
+
+    if subnum <= 0 then
+        return nil
+    end
+    
+    -- Let's return a TAB-separated string containing interesting data
+    -- Format : Name, Full URL, Language, File number (#CDs)
+    -- Subtitles File Format: sub, srt... -- unused
+    ret = subnum .. "\n"
+
+    for i = 1,(subnum - 1) do
+        fullURL = baseurl .. "/" .. suburl[i]
+        realName = string.gsub( subname[i], "..CDATA.", "" ) 
+        realName = string.gsub( realName, "..>", "" ) 
+        ret = ret .. realName .. "\t" .. fullURL .. "\t" .. sublang[i] .. "\t" .. subfilenum[i] .. "\n" 
+    end
+    
+    return ret
+end
Index: modules/gui/qt4/dialogs/help.cpp
===================================================================
--- modules/gui/qt4/dialogs/help.cpp	(révision 24316)
+++ modules/gui/qt4/dialogs/help.cpp	(copie de travail)
@@ -6,6 +6,7 @@
  *
  * Authors: Jean-Baptiste Kempf <jb (at) videolan.org>
  *          Rémi Duraffort <ivoire (at) via.ecp.fr>
+ *          Jean-Philippe André <jpeg CHEZ via POINT ecp POINT fr>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -293,3 +294,207 @@
 
 
 #endif
+
+
+#ifdef DOWNLOAD_SUBTITLES
+/* callback to get information from the core */
+static void SubDownloadCallback( void *data )
+{
+    SubDownloadDialog* SDDialog = (SubDownloadDialog *)data;
+    QEvent *event = new QEvent( QEvent::User );
+    QApplication::postEvent( SDDialog, event );
+}
+
+SubDownloadDialog *SubDownloadDialog::instance = NULL;
+
+SubDownloadDialog::SubDownloadDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf )
+{
+    setWindowTitle( qtr( "Download Subtitles" ) );
+    memset( &sublist, 0, sizeof( subtitles_list_t) );
+
+    QGridLayout *layout = new QGridLayout( this );
+
+    QLabel *movieNameLabel = new QLabel( this );
+    movieNameLabel->setText( qtr( "Movie's name" ) );
+    layout->addWidget( movieNameLabel, 0, 0 );
+    
+    movieNameEdit = new QLineEdit( this );
+    movieNameEdit->setText( getCurrentTitle() );
+    layout->addWidget( movieNameEdit, 0, 1, 1, 2 );
+
+    QBoxLayout *optionsLayout = new QBoxLayout( QBoxLayout::LeftToRight );
+    
+    QLabel *languageLabel = new QLabel( this );
+    languageLabel->setText( qtr( "Language" ) );
+    optionsLayout->addWidget( languageLabel );
+    
+    languageCombo = new QComboBox( this );
+//     languageCombo->setEditable( true );
+    optionsLayout->addWidget( languageCombo );
+    
+//     serverCombo = new QComboBox( this );
+//     serverCombo->setEditable( true );
+//     optionsLayout->addWidget( serverCombo );
+    
+    layout->addLayout( optionsLayout, 1, 0, 1, 3 );
+    
+    
+    subtitlesList = new QTreeWidget( this );
+    subtitlesList->setRootIsDecorated( false );
+    subtitlesList->setAlternatingRowColors( true );
+    subtitlesList->setSelectionMode( QAbstractItemView::ExtendedSelection );
+    subtitlesList->setSelectionBehavior( QAbstractItemView::SelectRows );
+    subtitlesList->setEditTriggers( QAbstractItemView::SelectedClicked );
+    subtitlesList->setColumnCount( 3 );
+    {
+        QStringList headerLabels;
+        headerLabels << qtr( "Language" );
+        headerLabels << qtr( "Title" );
+        headerLabels << qtr( "URL" );
+        subtitlesList->setHeaderLabels( headerLabels );
+    }
+    layout->addWidget ( subtitlesList, 2, 0, 1, 3 );
+    
+    fetchListButton = new QPushButton( qtr( "&Fetch List" ) );
+    layout->addWidget( fetchListButton, 3, 0 );
+    
+    downloadButton = new QPushButton( qtr( "&Download File" ) );
+    downloadButton->setEnabled( false ); /* TODO */
+    layout->addWidget( downloadButton, 3, 1 );
+    
+    closeButton = new QPushButton( qtr( "&Close" ) );
+    layout->addWidget( closeButton, 3, 2 );
+
+    BUTTONACT( closeButton, close() );
+    BUTTONACT( downloadButton, downloadFile() );
+    BUTTONACT( fetchListButton, fetchList() );
+    
+    /* FIXME: pushing Enter closes the dialogbox */
+//     CONNECT( movieNameEdit, SIGNAL(returnPressed()),
+//              this, SLOT(fetchList()) );
+    
+    fillComboBoxes();
+}
+
+SubDownloadDialog::~SubDownloadDialog()
+{
+    /* TODO: free memory in struct subtitles_list_ */
+}
+
+void SubDownloadDialog::close()
+{
+    hide();
+}
+
+void SubDownloadDialog::fillComboBoxes()
+{
+    /* Now we have to fill the comboboxes with Ids of languages and servers */
+    /* TODO */
+            
+//     serverCombo->addItem( "OpenSubtitles.Org", "opensubtitles.lua" );
+    
+    languageCombo->addItem( qtr( "French" ), "FR" );
+    languageCombo->addItem( qtr( "English" ), "EN" );
+    languageCombo->addItem( qtr( "German" ), "DE" );
+    /* And so on... not hard-coded would maybe be better ? */
+}
+
+void SubDownloadDialog::fetchList()
+{
+//     listURLString += serverCombo->itemData( serverCombo->currentIndex() ).toString();
+    /** TODO threader tout ce bordel */
+    
+    int i_ret;
+    module_t *p_module;
+    
+    p_intf->p_private = &sublist;
+    QString qs_Title = movieNameEdit->text();
+    char * psz_title;
+    asprintf( &psz_title, "%s", qPrintable( qs_Title ) );
+    sublist.psz_title = psz_title;
+    
+    p_module = module_Need( p_intf, "subtitles finder", 0, VLC_FALSE );
+    
+//     free( psz_title );
+    
+    if( p_module )
+    {
+        msg_Dbg( p_intf, "found subtitles finder" );
+        i_ret = 1;
+    }
+    else
+        msg_Dbg( p_intf, "unable to load module" );
+    
+    if ( sublist.ppsz_subtitles_urls )
+    {
+        int i = 0;
+        for ( ; i < sublist.count; i++ )
+        {
+            QStringList row;
+            row << QString( sublist.ppsz_subtitles_langs[i] );
+            row << QString( sublist.ppsz_subtitles_names[i] );
+            row << QString( sublist.ppsz_subtitles_urls[i] );
+            QTreeWidgetItem *item = new QTreeWidgetItem( subtitlesList, row );
+            item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable |
+                            Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
+            subtitlesList->insertTopLevelItem( i, item );
+        }
+    }
+    
+    if( p_module )
+        module_Unneed( p_intf, p_module );
+}
+
+void SubDownloadDialog::downloadFile()
+{
+    /* TODO */
+     QMessageBox::warning( this, qtr( "S.I.D." ), qtr( "This feature is not yet implemented !" ) );
+}
+
+void SubDownloadDialog::customEvent( QEvent * event )
+{
+    updateStatus();
+    event->accept();
+}
+
+int SubDownloadDialog::updateStatus()
+{
+     QMessageBox::warning( this, qtr( "Not implemented yet !" ), "caca" );
+}
+
+QString SubDownloadDialog::getCurrentTitle()
+{
+    QString qsTitle;
+    char * psz_name;
+    
+    playlist_t *p_playlist = pl_Get( p_intf );
+    playlist_item_t *p_item = ( p_playlist ? p_playlist->status.p_item : NULL );
+    input_item_t *p_input = (p_item ? p_item->p_input : NULL);
+    if( !p_input )
+    {
+        if ( p_playlist->items.i_size )
+        {
+            p_item = p_playlist->items.p_elems[0];
+            if ( !p_item )
+                return QString( "" );
+            else
+                p_input = p_item->p_input;
+        }
+    }
+    if ( !p_input )
+                return QString( "" );
+    
+    psz_name = input_item_GetName( p_input ) ;
+    qsTitle = QString( psz_name );
+    free( psz_name );
+    
+    return qsTitle;
+}
+
+void SubDownloadDialog::showEvent( QShowEvent * event )
+{
+    /* Reactualize movie's name when showing the dialog */
+    movieNameEdit->setText( getCurrentTitle() );
+}
+
+#endif
Index: modules/gui/qt4/dialogs/help.hpp
===================================================================
--- modules/gui/qt4/dialogs/help.hpp	(révision 24316)
+++ modules/gui/qt4/dialogs/help.hpp	(copie de travail)
@@ -28,6 +28,15 @@
 
 #include "util/qvlcframe.hpp"
 
+#define DOWNLOAD_SUBTITLES tamere
+#ifdef DOWNLOAD_SUBTITLES
+#include <QLineEdit>
+#include <QTreeWidget>
+#include <QComboBox>
+#include <QMessageBox>
+#include <../modules/misc/lua/vlc.h> /** FIXME */
+#endif
+
 class QPushButton;
 class QTextBrowser;
 class QLabel;
@@ -106,4 +115,39 @@
 };
 #endif
 
+#ifdef DOWNLOAD_SUBTITLES
+class SubDownloadDialog : public QVLCFrame
+{
+    Q_OBJECT;
+public:
+    static SubDownloadDialog * getInstance( intf_thread_t *p_intf )
+    {
+        if( !instance )
+            instance = new SubDownloadDialog( p_intf );
+        return instance;
+    }
+    virtual ~SubDownloadDialog();
+
+private:
+    SubDownloadDialog( intf_thread_t * );
+    static SubDownloadDialog *instance;
+    QComboBox *languageCombo; //, *serverCombo;
+    QTreeWidget *subtitlesList;
+    QPushButton *downloadButton, *fetchListButton, *closeButton;
+    QLineEdit *movieNameEdit;
+    void fillComboBoxes();
+    int updateStatus();
+    subtitles_list_t sublist;
+    QString getCurrentTitle();
+    /* Event handling */
+    void customEvent( QEvent * );
+    void showEvent( QShowEvent * );
+
+private slots:
+    void close();
+    void fetchList();
+    void downloadFile();
+};
 #endif
+
+#endif
Index: modules/gui/qt4/dialogs_provider.hpp
===================================================================
--- modules/gui/qt4/dialogs_provider.hpp	(révision 24316)
+++ modules/gui/qt4/dialogs_provider.hpp	(copie de travail)
@@ -154,6 +154,12 @@
 #ifdef UPDATE_CHECK
     void updateDialog();
 #endif
+    
+#define DOWNLOAD_SUBTITLES tamere
+#ifdef DOWNLOAD_SUBTITLES
+    void subDownloadDialog();
+#endif
+    
     void aboutDialog();
     void gotoTimeDialog();
     void podcastConfigureDialog();
Index: modules/gui/qt4/menus.cpp
===================================================================
--- modules/gui/qt4/menus.cpp	(révision 24316)
+++ modules/gui/qt4/menus.cpp	(copie de travail)
@@ -464,6 +464,10 @@
 #ifdef UPDATE_CHECK
     addDPStaticEntry( menu, qtr( "Update" ) , "", "", SLOT( updateDialog() ), "");
 #endif
+#define DOWNLOAD_SUBTITLES tamere
+#ifdef DOWNLOAD_SUBTITLES
+    addDPStaticEntry( menu, qtr( "Download Subtitles" ) , "", "", SLOT( subDownloadDialog() ), "");
+#endif
     menu->addSeparator();
     addDPStaticEntry( menu, qtr( I_MENU_ABOUT ), "", "", SLOT( aboutDialog() ),
         "Ctrl+F1" );
Index: modules/gui/qt4/dialogs_provider.cpp
===================================================================
--- modules/gui/qt4/dialogs_provider.cpp	(révision 24316)
+++ modules/gui/qt4/dialogs_provider.cpp	(copie de travail)
@@ -188,6 +188,13 @@
 }
 #endif
 
+#ifdef DOWNLOAD_SUBTITLES
+void DialogsProvider::subDownloadDialog()
+{
+    SubDownloadDialog::getInstance( p_intf )->toggleVisible();
+}
+#endif
+
 void DialogsProvider::aboutDialog()
 {
     AboutDialog::getInstance( p_intf )->toggleVisible();
Index: modules/misc/lua/Modules.am
===================================================================
--- modules/misc/lua/Modules.am	(révision 24316)
+++ modules/misc/lua/Modules.am	(copie de travail)
@@ -1 +1 @@
-SOURCES_lua = playlist.c meta.c intf.c vlc.c vlc.h callbacks.c objects.c variables.c configuration.c net.c vlm.c httpd.c acl.c sd.c
+SOURCES_lua = playlist.c meta.c intf.c vlc.c vlc.h callbacks.c objects.c variables.c configuration.c net.c vlm.c httpd.c acl.c sd.c subtitles.c
Index: modules/misc/lua/vlc.c
===================================================================
--- modules/misc/lua/vlc.c	(révision 24316)
+++ modules/misc/lua/vlc.c	(copie de travail)
@@ -87,6 +87,12 @@
         add_string( "lua-config", "", NULL,
                     CONFIG_TEXT, CONFIG_LONGTEXT, VLC_FALSE );
         set_callbacks( E_(Open_LuaIntf), E_(Close_LuaIntf) );
+    add_submodule();
+        add_shortcut( "luasubtitles" );
+        set_shortname( N_( "Lua Subtitles" ) );
+        set_description( _("Fetch subtitles list using lua scripts") );
+        set_capability( "subtitles finder", 10 );
+        set_callbacks( E_(FindSubtitles), NULL );
 vlc_module_end();
 
 /*****************************************************************************
Index: modules/misc/lua/vlc.h
===================================================================
--- modules/misc/lua/vlc.h	(révision 24316)
+++ modules/misc/lua/vlc.h	(copie de travail)
@@ -48,6 +48,31 @@
 #include <lauxlib.h>    /* Higher level C API */
 #include <lualib.h>     /* Lua libs */
 
+#ifndef DOWNLOAD_SUBTITLES
+# define DOWNLOAD_SUBTITLES prout
+#endif
+#ifdef DOWNLOAD_SUBTITLES
+struct subtitles_list_t {
+//     VLC_COMMON_MEMBERS
+    /* Input values */
+//     playlist_t *p_playlist;
+    char *psz_scriptname;
+    char *psz_title; /* Unused yet */
+    /* Output values */
+    int count; /* Number of subtitles found */
+    char **ppsz_subtitles_names; /* Subtitles names */
+    char **ppsz_subtitles_langs; /* language, maybe we could use int ID values ? */
+    char **ppsz_subtitles_urls; /* URL */
+    int *pi_filenum; /* CDs number */
+    /** We could use ARRAYs instead of this shit */
+    /* TYPEDEF_ARRAY ( char_list, char * ) ... */
+};
+typedef struct subtitles_list_t subtitles_list_t;
+#define SUB_NAME_MAX_LEN 100
+#define SUB_URL_MAX_LEN 500
+#define SUB_LANG_MAX_LEN 20
+#endif
+
 /*****************************************************************************
  * Module entry points
  *****************************************************************************/
@@ -60,6 +85,7 @@
 int E_(Open_LuaIntf)( vlc_object_t * );
 void E_(Close_LuaIntf)( vlc_object_t * );
 
+int E_(FindSubtitles)( vlc_object_t * );
 
 /*****************************************************************************
  * Lua debug
