root/applications/osmo4_w32/Osmo4.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. BEGIN_MESSAGE_MAP
  2. DoDataExchange
  3. OnInitDialog
  4. OnClose
  5. GetPassword
  6. Osmo4_progress_cbk
  7. log_msg
  8. Osmo4_EventProc
  9. static_gpac_get_url
  10. osmo4_do_log
  11. InitInstance
  12. ExitInstance
  13. DoDataExchange
  14. BEGIN_MESSAGE_MAP
  15. OnInitDialog
  16. OnGogpac
  17. SetOptions
  18. OnOpenUrl
  19. GetFileFilter
  20. OnOpenFile
  21. Pause
  22. OnMainPause
  23. OnFileStep
  24. OnUpdateFileStep
  25. PlayFromTime
  26. OnFileReload
  27. OnFileMigrate
  28. OnConfigReload
  29. UpdatePlayButton
  30. OnFilePlay
  31. OnUpdateFilePlay
  32. OnFileStop
  33. OnUpdateFileStop
  34. OnSwitchRender
  35. UpdateRenderSwitch

// GPAC.cpp : Defines the class behaviors for the application.
//

#include "stdafx.h"
#include "Osmo4.h"
#include <gpac/network.h>
#include <direct.h>
#include "MainFrm.h"
#include "OpenUrl.h"
#include "resource.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// Osmo4

BEGIN_MESSAGE_MAP(Osmo4, CWinApp)
        //{{AFX_MSG_MAP(Osmo4)
        ON_COMMAND(ID_OPEN_FILE, OnOpenFile)
        ON_COMMAND(ID_FILE_STEP, OnFileStep)
        ON_COMMAND(ID_OPEN_URL, OnOpenUrl)
        ON_COMMAND(ID_FILE_RELOAD, OnFileReload)
        ON_COMMAND(ID_CONFIG_RELOAD, OnConfigReload)
        ON_COMMAND(ID_FILE_PLAY, OnFilePlay)
        ON_UPDATE_COMMAND_UI(ID_FILE_PLAY, OnUpdateFilePlay)
        ON_UPDATE_COMMAND_UI(ID_FILE_STEP, OnUpdateFileStep)
        ON_COMMAND(ID_FILE_STOP, OnFileStop)
        ON_UPDATE_COMMAND_UI(ID_FILE_STOP, OnUpdateFileStop)
        ON_COMMAND(ID_SWITCH_RENDER, OnSwitchRender)
        ON_UPDATE_COMMAND_UI(ID_FILE_RELOAD, OnUpdateFileStop)
        ON_COMMAND(ID_H_ABOUT, OnAbout)
        ON_COMMAND(ID_FILE_MIGRATE, OnFileMigrate)
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// Osmo4 construction

Osmo4::Osmo4()
{
}

/////////////////////////////////////////////////////////////////////////////
// The one and only Osmo4 object

Osmo4 theApp;



class UserPassDialog : public CDialog
{
// Construction
public:
        UserPassDialog(CWnd* pParent = NULL);   // standard constructor

        Bool GetPassword(const char *site_url, char *user, char *password);

// Dialog Data
        //{{AFX_DATA(UserPassDialog)
        enum { IDD = IDD_PASSWD };
        CStatic m_SiteURL;
        CEdit m_User;
        CEdit m_Pass;
        //}}AFX_DATA

        void SetSelection(u32 sel);
        char cur_ext[200], cur_mime[200];

// Overrides
        // ClassWizard generated virtual function overrides
        //{{AFX_VIRTUAL(UserPassDialog)
protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
        //}}AFX_VIRTUAL

// Implementation
protected:
        const char *m_site_url;
        char *m_user, *m_password;

        // Generated message map functions
        //{{AFX_MSG(UserPassDialog)
        virtual BOOL OnInitDialog();
        afx_msg void OnClose();
        //}}AFX_MSG
};

UserPassDialog::UserPassDialog(CWnd* pParent /*=NULL*/)
        : CDialog(UserPassDialog::IDD, pParent)
{
        //{{AFX_DATA_INIT(COptStream)
        //}}AFX_DATA_INIT
}

void UserPassDialog::DoDataExchange(CDataExchange* pDX)
{
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(UserPassDialog)
        DDX_Control(pDX, IDC_TXT_SITE, m_SiteURL);
        DDX_Control(pDX, IDC_EDIT_USER, m_User);
        DDX_Control(pDX, IDC_EDIT_PASSWORD, m_Pass);
        //}}AFX_DATA_MAP
}

BOOL UserPassDialog::OnInitDialog()
{
        CDialog::OnInitDialog();
        m_SiteURL.SetWindowText(m_site_url);
        m_User.SetWindowText(m_user);
        m_Pass.SetWindowText("");
        return TRUE;
}

void UserPassDialog::OnClose()
{
        m_User.GetWindowText(m_user, 50);
        m_Pass.GetWindowText(m_password, 50);
}

Bool UserPassDialog::GetPassword(const char *site_url, char *user, char *password)
{
        m_site_url = site_url;
        m_user = user;
        if (DoModal() != IDOK) return GF_FALSE;
        return GF_TRUE;
}


static void Osmo4_progress_cbk(const void *usr, const char *title, u64 done, u64 total)
{
        if (!total) return;
        CMainFrame *pFrame = (CMainFrame *) ((Osmo4 *) usr)->m_pMainWnd;
        s32 prog = (s32) ( (100 * (u64)done) / total);
        if (pFrame->m_last_prog < prog) {
                pFrame->console_err = GF_OK;
                pFrame->m_last_prog = prog;
                pFrame->console_message.Format("%s %02d %%", title, prog);
                pFrame->PostMessage(WM_CONSOLEMSG, 0, 0);
                if (done==total) pFrame->m_last_prog = -1;
        }
}

#define W32_MIN_WIDTH 120

static void log_msg(char *msg)
{
        ::MessageBox(NULL, msg, "GPAC", MB_OK);
}
Bool Osmo4_EventProc(void *priv, GF_Event *evt)
{
        u32 dur;
        Osmo4 *gpac = (Osmo4 *) priv;
        CMainFrame *pFrame = (CMainFrame *) gpac->m_pMainWnd;
        /*shutdown*/
        if (!pFrame) return GF_FALSE;

        switch (evt->type) {
        case GF_EVENT_DURATION:
                dur = (u32) (1000 * evt->duration.duration);
                //if (dur<1100) dur = 0;
                pFrame->m_pPlayList->SetDuration((u32) evt->duration.duration );
                gpac->max_duration = dur;
                gpac->can_seek = evt->duration.can_seek;
                if (!gpac->can_seek) {
                        pFrame->m_Sliders.m_PosSlider.EnableWindow(FALSE);
                } else {
                        pFrame->m_Sliders.m_PosSlider.EnableWindow(TRUE);
                        pFrame->m_Sliders.m_PosSlider.SetRangeMin(0);
                        pFrame->m_Sliders.m_PosSlider.SetRangeMax(dur);
                }
                break;

        case GF_EVENT_MESSAGE:
                if (!evt->message.service || !strcmp(evt->message.service, (LPCSTR) pFrame->m_pPlayList->GetURL() )) {
                        pFrame->console_service = "main service";
                } else {
                        pFrame->console_service = evt->message.service;
                }
                if (evt->message.error!=GF_OK) {
                        if (evt->message.error<GF_OK || !gpac->m_NoConsole) {
                                pFrame->console_err = evt->message.error;
                                pFrame->console_message = evt->message.message;
                                gpac->m_pMainWnd->PostMessage(WM_CONSOLEMSG, 0, 0);

                                /*any error before connection confirm is a service connection error*/
                                if (!gpac->m_isopen) pFrame->m_pPlayList->SetDead();
                        }
                        return GF_FALSE;
                }
                if (gpac->m_NoConsole) return GF_FALSE;

                /*process user message*/
                pFrame->console_err = GF_OK;
                pFrame->console_message = evt->message.message;
                gpac->m_pMainWnd->PostMessage(WM_CONSOLEMSG, 0, 0);
                break;
        case GF_EVENT_PROGRESS:
                char *szType;
                if (evt->progress.progress_type==0) szType = "Buffer ";
                else if (evt->progress.progress_type==1) szType = "Download ";
                else if (evt->progress.progress_type==2) szType = "Import ";
                gf_set_progress(szType, evt->progress.done, evt->progress.total);
                break;
        case GF_EVENT_NAVIGATE_INFO:
                pFrame->console_message = evt->navigate.to_url;
                gpac->m_pMainWnd->PostMessage(WM_CONSOLEMSG, 1000, 0);
                break;

        case GF_EVENT_SCENE_SIZE:
                if (evt->size.width && evt->size.height) {
                        gpac->orig_width = evt->size.width;
                        gpac->orig_height = evt->size.height;
                        if (gpac->m_term && !pFrame->m_bFullScreen)
                                pFrame->PostMessage(WM_SETSIZE, evt->size.width, evt->size.height);
                }
                break;
                /*don't resize on win32 msg notif*/
#if 0
        case GF_EVENT_SIZE:
                if (/*gpac->m_term && !pFrame->m_bFullScreen && */gpac->orig_width && (evt->size.width < W32_MIN_WIDTH) )
                        pFrame->PostMessage(WM_SETSIZE, W32_MIN_WIDTH, (W32_MIN_WIDTH*gpac->orig_height) / gpac->orig_width);
                else
                        pFrame->PostMessage(WM_SETSIZE, evt->size.width, evt->size.height);
                break;
#endif

        case GF_EVENT_CONNECT:
//              if (pFrame->m_bStartupFile) return 0;

                pFrame->BuildStreamList(GF_TRUE);
                if (evt->connect.is_connected) {
                        pFrame->BuildChapterList(GF_FALSE);
                        gpac->m_isopen = GF_TRUE;
                        //resetting sliders when opening a new file creates a deadlock on the window thread which is disconnecting
                        pFrame->m_wndToolBar.SetButtonInfo(5, ID_FILE_PLAY, TBBS_BUTTON, gpac->m_isopen ? 4 : 3);
                        pFrame->m_Sliders.m_PosSlider.SetPos(0);
                        pFrame->SetProgTimer(GF_TRUE);
                } else {
                        gpac->max_duration = 0;
                        gpac->m_isopen = GF_FALSE;
                        pFrame->BuildChapterList(GF_TRUE);
                }
                if (!pFrame->m_bFullScreen) {
                        pFrame->SetFocus();
                        pFrame->SetForegroundWindow();
                }
                break;

        case GF_EVENT_QUIT:
                pFrame->PostMessage(WM_CLOSE, 0L, 0L);
                break;
        case GF_EVENT_MIGRATE:
        {
        }
        break;
        case GF_EVENT_KEYDOWN:
                gf_term_process_shortcut(gpac->m_term, evt);
                /*update volume control*/
                pFrame->m_Sliders.SetVolume();

                switch (evt->key.key_code) {
                case GF_KEY_HOME:
                        gf_term_set_option(gpac->m_term, GF_OPT_NAVIGATION_TYPE, 1);
                        break;
                case GF_KEY_ESCAPE:
                        pFrame->PostMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
                        break;
                case GF_KEY_MEDIANEXTTRACK:
                        pFrame->m_pPlayList->PlayNext();
                        break;
                case GF_KEY_MEDIAPREVIOUSTRACK:
                        pFrame->m_pPlayList->PlayPrev();
                        break;
                case GF_KEY_H:
                        if ((evt->key.flags & GF_KEY_MOD_CTRL) && gpac->m_isopen)
                                gf_term_switch_quality(gpac->m_term, GF_TRUE);
                        break;
                case GF_KEY_L:
                        if ((evt->key.flags & GF_KEY_MOD_CTRL) && gpac->m_isopen)
                                gf_term_switch_quality(gpac->m_term, GF_FALSE);
                        break;
                case GF_KEY_LEFT:
                case GF_KEY_RIGHT:
                        if (gpac->m_isopen && (gf_term_get_option(gpac->m_term, GF_OPT_NAVIGATION) == GF_NAVIGATE_NONE)) {
                                if (evt->key.flags & GF_KEY_MOD_CTRL) {
                                        if (evt->key.key_code==GF_KEY_LEFT) pFrame->m_pPlayList->PlayPrev();
                                        else if (evt->key.key_code==GF_KEY_RIGHT) pFrame->m_pPlayList->PlayNext();
                                }
                                else if (gpac->can_seek && (evt->key.flags & GF_KEY_MOD_ALT)) {
                                        u32 duration = gpac->max_duration;
                                        s32 current_time = gf_term_get_time_in_ms(gpac->m_term);

                                        if (evt->key.key_code==GF_KEY_LEFT) {
                                                current_time -= 5*duration/100;
                                                if (current_time<0) current_time=0;
                                                gf_term_play_from_time(gpac->m_term, (u64) current_time, 0);
                                        }
                                        else if (evt->key.key_code==GF_KEY_RIGHT) {
                                                current_time += 5*duration/100;
                                                if ((u32) current_time < duration) {
                                                        gf_term_play_from_time(gpac->m_term, (u64) current_time, 0);
                                                }
                                        }
                                }
                        }
                        break;
                }
                break;
        case GF_EVENT_NAVIGATE:
                /*fixme - a proper browser would require checking mime type & co*/
                /*store URL since it may be destroyed, and post message*/
                gpac->m_navigate_url = evt->navigate.to_url;
                pFrame->PostMessage(WM_NAVIGATE, NULL, NULL);
                return GF_TRUE;
        case GF_EVENT_VIEWPOINTS:
                pFrame->BuildViewList();
                return GF_FALSE;
        case GF_EVENT_STREAMLIST:
                pFrame->BuildStreamList(GF_FALSE);
                return GF_FALSE;
        case GF_EVENT_SET_CAPTION:
                pFrame->SetWindowText(evt->caption.caption);
                break;
        case GF_EVENT_DBLCLICK:
                pFrame->PostMessage(WM_COMMAND, ID_VIEW_FULLSCREEN);
                return GF_FALSE;
        case GF_EVENT_AUTHORIZATION:
        {
                UserPassDialog passdlg;
                return passdlg.GetPassword(evt->auth.site_url, evt->auth.user, evt->auth.password);
        }
        }
        return GF_FALSE;
}


/*here's the trick: use a storage section shared among all processes for the wnd handle and for the command line
NOTE: this has to be static memory of course, don't try to alloc anything there...*/
#pragma comment(linker, "/SECTION:.shr,RWS")
#pragma data_seg(".shr")
HWND static_gpac_hwnd = NULL;
char static_szCmdLine[MAX_PATH] = "";
#pragma data_seg()

const char *static_gpac_get_url()
{
        return (const char *) static_szCmdLine;
}

static void osmo4_do_log(void *cbk, GF_LOG_Level level, GF_LOG_Tool tool, const char *fmt, va_list list)
{
        FILE *logs = (FILE *) cbk;
        vfprintf(logs, fmt, list);
        fflush(logs);
}

BOOL Osmo4::InitInstance()
{
        CCommandLineInfo cmdInfo;

        afxAmbientActCtx = FALSE;

        m_logs = NULL;

        m_term = NULL;

        memset(&m_user, 0, sizeof(GF_User));

        /*get Osmo4.exe path*/
        strcpy((char *) szApplicationPath, AfxGetApp()->m_pszHelpFilePath);
        while (szApplicationPath[strlen((char *) szApplicationPath)-1] != '\\') szApplicationPath[strlen((char *) szApplicationPath)-1] = 0;
        if (szApplicationPath[strlen((char *) szApplicationPath)-1] != '\\') strcat(szApplicationPath, "\\");

        gf_sys_init(GF_MemTrackerNone);

        /*setup user*/
        memset(&m_user, 0, sizeof(GF_User));

        Bool first_launch = GF_FALSE;
        /*init config and modules*/
        m_user.config = gf_cfg_init(NULL, &first_launch);
        if (!m_user.config) {
                MessageBox(NULL, "GPAC Configuration file not found", "Fatal Error", MB_OK);
                m_pMainWnd->PostMessage(WM_CLOSE);
        }

        char *name = gf_cfg_get_filename(m_user.config);
        char *sep = strrchr(name, '\\');
        if (sep) sep[0] = 0;
        strcpy(szUserPath, name);
        if (sep) sep[0] = '\\';
        gf_free(name);

        const char *opt = gf_cfg_get_key(m_user.config, "General", "SingleInstance");
        m_SingleInstance = (opt && !stricmp(opt, "yes")) ? GF_TRUE : GF_FALSE;

        m_hMutex = NULL;
        if (m_SingleInstance) {
                m_hMutex = CreateMutex(NULL, FALSE, "Osmo4_GPAC_INSTANCE");
                if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
                        char szDIR[1024];
                        if (m_hMutex) CloseHandle(m_hMutex);
                        m_hMutex = NULL;

                        if (!static_gpac_hwnd || !IsWindow(static_gpac_hwnd) ) {
                                ::MessageBox(NULL, "Osmo4 ghost process detected", "Error at last shutdown" , MB_OK);
                        } else {
                                ::SetForegroundWindow(static_gpac_hwnd);

                                if (m_lpCmdLine && strlen(m_lpCmdLine)) {
                                        DWORD_PTR res;
                                        size_t len;
                                        char *the_url, *cmd;
                                        GetCurrentDirectory(1024, szDIR);
                                        if (szDIR[strlen(szDIR)-1] != '\\') strcat(szDIR, "\\");
                                        cmd = (char *)(const char *) m_lpCmdLine;
                                        strcpy(static_szCmdLine, "");
                                        if (cmd[0]=='"') cmd+=1;

                                        if (!strnicmp(cmd, "-queue ", 7)) {
                                                strcat(static_szCmdLine, "-queue ");
                                                cmd += 7;
                                        }
                                        the_url = gf_url_concatenate(szDIR, cmd);
                                        if (!the_url) {
                                                strcat(static_szCmdLine, cmd);
                                        } else {
                                                strcat(static_szCmdLine, the_url);
                                                gf_free(the_url);
                                        }
                                        while ( (len = strlen(static_szCmdLine)) ) {
                                                char s = static_szCmdLine[len-1];
                                                if ((s==' ') || (s=='"')) static_szCmdLine[len-1]=0;
                                                else break;
                                        }
                                        ::SendMessageTimeout(static_gpac_hwnd, WM_NEWINSTANCE, 0, 0, 0, 1000, &res);
                                }
                        }

                        return FALSE;
                }
        }

#if 0
        // Standard initialization
#ifdef _AFXDLL
        Enable3dControls();                     // Call this when using MFC in a shared DLL
#else
        Enable3dControlsStatic();       // Call this when linking to MFC statically
#endif

#endif

        SetRegistryKey(_T("GPAC"));
        CMainFrame* pFrame = new CMainFrame;
        m_pMainWnd = pFrame;
        pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL);
        pFrame->LoadAccelTable( MAKEINTRESOURCE(IDR_MAINACCEL));

        m_pMainWnd->DragAcceptFiles();

        if (m_SingleInstance) static_gpac_hwnd = m_pMainWnd->m_hWnd;

        m_user.modules = gf_modules_new(NULL, m_user.config);
        if (!m_user.modules || ! gf_modules_get_count(m_user.modules) ) {
                MessageBox(NULL, "No modules available - system cannot work", "Fatal Error", MB_OK);
                m_pMainWnd->PostMessage(WM_CLOSE);
        }
        else if (first_launch) {
                /*first launch, register all files ext*/
                u32 i;
                for (i=0; i<gf_modules_get_count(m_user.modules); i++) {
                        GF_InputService *ifce = (GF_InputService *) gf_modules_load_interface(m_user.modules, i, GF_NET_CLIENT_INTERFACE);
                        if (!ifce) continue;
                        if (ifce) {
                                ifce->CanHandleURL(ifce, "test.test");
                                gf_modules_close_interface((GF_BaseInterface *)ifce);
                        }
                }
                /*set some shortcuts*/
                gf_cfg_set_key(m_user.config, "Shortcuts", "VolumeUp", "ctrl+Up");
                gf_cfg_set_key(m_user.config, "Shortcuts", "VolumeDown", "ctrl+Down");
                gf_cfg_set_key(m_user.config, "Shortcuts", "FastRewind", "ctrl+Left");
                gf_cfg_set_key(m_user.config, "Shortcuts", "FastForward", "ctrl+Right");
                gf_cfg_set_key(m_user.config, "Shortcuts", "Play", "ctrl+ ");
        }

        /*check log file*/
        const char *str = gf_cfg_get_key(m_user.config, "General", "LogFile");
        if (str) {
                m_logs = gf_fopen(str, "wt");
                gf_log_set_callback(m_logs, osmo4_do_log);
        }
        else m_logs = NULL;

        /*set log level*/
        if (gf_log_set_tools_levels(gf_cfg_get_key(m_user.config, "General", "Logs")) != GF_OK)
                fprintf(stdout, "osmo4: invalid log level specified\n");

        m_user.opaque = this;
        m_user.os_window_handler = pFrame->m_pWndView->m_hWnd;
        m_user.EventProc = Osmo4_EventProc;

        m_reset = GF_FALSE;
        orig_width = 320;
        orig_height = 240;

        gf_set_progress_callback(this, Osmo4_progress_cbk);

        m_term = gf_term_new(&m_user);
        if (! m_term) {
                MessageBox(NULL, "Cannot load GPAC Terminal", "Fatal Error", MB_OK);
                m_pMainWnd->PostMessage(WM_CLOSE);
                return TRUE;
        }
        SetOptions();
        UpdateRenderSwitch();

        pFrame->SendMessage(WM_SETSIZE, orig_width, orig_height);
        pFrame->m_Address.ReloadURLs();

        pFrame->m_Sliders.SetVolume();

        m_reconnect_time = 0;


        ParseCommandLine(cmdInfo);

        start_mode = 0;

        if (! cmdInfo.m_strFileName.IsEmpty()) {
                pFrame->m_pPlayList->QueueURL(cmdInfo.m_strFileName);
                pFrame->m_pPlayList->RefreshList();
                pFrame->m_pPlayList->PlayNext();
        } else {
                char sPL[MAX_PATH];
                strcpy((char *) sPL, szUserPath);
                strcat(sPL, "gpac_pl.m3u");
                pFrame->m_pPlayList->OpenPlayList(sPL);
                const char *sOpt = gf_cfg_get_key(GetApp()->m_user.config, "General", "PLEntry");
                if (sOpt) {
                        s32 count = (s32)gf_list_count(pFrame->m_pPlayList->m_entries);
                        pFrame->m_pPlayList->m_cur_entry = atoi(sOpt);
                        if (pFrame->m_pPlayList->m_cur_entry>=count)
                                pFrame->m_pPlayList->m_cur_entry = count-1;
                } else {
                        pFrame->m_pPlayList->m_cur_entry = -1;
                }
#if 0
                if (pFrame->m_pPlayList->m_cur_entry>=0) {
                        start_mode = 1;
                        pFrame->m_pPlayList->Play();
                }
#endif

                sOpt = gf_cfg_get_key(m_user.config, "General", "StartupFile");
                if (sOpt && !strstr(sOpt, "gui") ) gf_term_connect(m_term, sOpt);

                sOpt = gf_cfg_get_key(m_user.config, "General", "PlaylistLoop");
                m_Loop = (sOpt && !strcmp(sOpt, "yes")) ? GF_TRUE : GF_FALSE;
        }
        pFrame->SetFocus();
        pFrame->SetForegroundWindow();
        return TRUE;
}

int Osmo4::ExitInstance()
{
        if (m_term) gf_term_del(m_term);
        if (m_user.modules) gf_modules_del(m_user.modules);
        if (m_user.config) gf_cfg_del(m_user.config);
        gf_sys_close();
        /*last instance*/
        if (m_hMutex) {
                CloseHandle(m_hMutex);
                static_gpac_hwnd = NULL;
        }
        if (m_logs) gf_fclose(m_logs);
        return CWinApp::ExitInstance();
}



/////////////////////////////////////////////////////////////////////////////
// Osmo4 message handlers





/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
        CAboutDlg();

// Dialog Data
        //{{AFX_DATA(CAboutDlg)
        enum { IDD = IDD_ABOUTBOX };
        //}}AFX_DATA

        // ClassWizard generated virtual function overrides
        //{{AFX_VIRTUAL(CAboutDlg)
protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
        //}}AFX_VIRTUAL

// Implementation
protected:
        //{{AFX_MSG(CAboutDlg)
        virtual BOOL OnInitDialog();
        afx_msg void OnGogpac();
        //}}AFX_MSG
        DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
        //{{AFX_DATA_INIT(CAboutDlg)
        //}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CAboutDlg)
        //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
        //{{AFX_MSG_MAP(CAboutDlg)
        ON_BN_CLICKED(IDC_GOGPAC, OnGogpac)
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

void Osmo4::OnAbout()
{
        CAboutDlg aboutDlg;
        aboutDlg.DoModal();
}

BOOL CAboutDlg::OnInitDialog()
{
        CDialog::OnInitDialog();
        CString str = "GPAC/Osmo4 - version " GPAC_FULL_VERSION;
        SetWindowText(str);
        return TRUE;
}

void CAboutDlg::OnGogpac()
{
        ShellExecute(NULL, "open", "http://gpac.sourceforge.net", NULL, NULL, SW_SHOWNORMAL);
}

/////////////////////////////////////////////////////////////////////////////
// Osmo4 message handlers


void Osmo4::SetOptions()
{
        const char *sOpt = gf_cfg_get_key(m_user.config, "General", "Loop");
        m_Loop = (sOpt && !stricmp(sOpt, "yes")) ? GF_TRUE : GF_FALSE;
        sOpt = gf_cfg_get_key(m_user.config, "General", "LookForSubtitles");
        m_LookForSubtitles = (sOpt && !stricmp(sOpt, "yes")) ? GF_TRUE : GF_FALSE;
        sOpt = gf_cfg_get_key(m_user.config, "General", "ConsoleOff");
        m_NoConsole = (sOpt && !stricmp(sOpt, "yes")) ? GF_TRUE : GF_FALSE;
        sOpt = gf_cfg_get_key(m_user.config, "General", "ViewXMT");
        m_ViewXMTA  = (sOpt && !stricmp(sOpt, "yes")) ? GF_TRUE : GF_FALSE;
        sOpt = gf_cfg_get_key(m_user.config, "General", "NoMIMETypeFetch");
        m_NoMimeFetch = (!sOpt || !stricmp(sOpt, "yes")) ? GF_TRUE : GF_FALSE;
}


void Osmo4::OnOpenUrl()
{
        COpenUrl url;
        if (url.DoModal() != IDOK) return;

        CMainFrame *pFrame = (CMainFrame *) m_pMainWnd;
        pFrame->m_pPlayList->Truncate();
        pFrame->m_pPlayList->QueueURL(url.m_url);
        pFrame->m_pPlayList->RefreshList();
        pFrame->m_pPlayList->PlayNext();
}


CString Osmo4::GetFileFilter()
{
        u32 keyCount, i;
        CString sFiles;
        CString sExts;
        CString supportedFiles;

        /*force MP4 and 3GP files at beginning to make sure they are selected (Win32 bug with too large filters)*/
        supportedFiles = "All Known Files|*.m3u;*.pls;*.mp4;*.3gp;*.3g2";

        sExts = "";
        sFiles = "";
        keyCount = gf_cfg_get_key_count(m_user.config, "MimeTypes");
        for (i=0; i<keyCount; i++) {
                const char *sMime;
                Bool first;
                char *sKey;
                const char *opt;
                char szKeyList[1000], sDesc[1000];
                sMime = gf_cfg_get_key_name(m_user.config, "MimeTypes", i);
                if (!sMime) continue;
                CString sOpt;
                opt = gf_cfg_get_key(m_user.config, "MimeTypes", sMime);
                /*remove module name*/
                strcpy(szKeyList, opt+1);
                sKey = strrchr(szKeyList, '\"');
                if (!sKey) continue;
                sKey[0] = 0;
                /*get description*/
                sKey = strrchr(szKeyList, '\"');
                if (!sKey) continue;
                strcpy(sDesc, sKey+1);
                sKey[0] = 0;
                sKey = strrchr(szKeyList, '\"');
                if (!sKey) continue;
                sKey[0] = 0;

                /*if same description for # mime types skip (means an old mime syntax)*/
                if (sFiles.Find(sDesc)>=0) continue;
                /*if same extensions for # mime types skip (don't polluate the file list)*/
                if (sExts.Find(szKeyList)>=0) continue;

                sExts += szKeyList;
                sExts += " ";
                sFiles += sDesc;
                sFiles += "|";

                first = GF_TRUE;

                sOpt = CString(szKeyList);
                while (1) {

                        int pos = sOpt.Find(' ');
                        CString ext = (pos==-1) ? sOpt : sOpt.Left(pos);
                        /*WATCHOUT: we do have some "double" ext , eg .wrl.gz - these are NOT supported by windows*/
                        if (ext.Find(".")<0) {
                                if (!first) {
                                        sFiles += ";";
                                } else {
                                        first = GF_FALSE;
                                }
                                sFiles += "*.";
                                sFiles += ext;

                                CString sext = ext;
                                sext += ";";
                                if (supportedFiles.Find(sext)<0) {
                                        supportedFiles += ";*.";
                                        supportedFiles += ext;
                                }
                        }

                        if (sOpt==ext) break;
                        CString rem;
                        rem.Format("%s ", (LPCTSTR) ext);
                        sOpt.Replace((LPCTSTR) rem, "");
                }
                sFiles += "|";
        }
        supportedFiles += "|";
        supportedFiles += sFiles;
        supportedFiles += "M3U Playlists|*.m3u|ShoutCast Playlists|*.pls|All Files |*.*|";
        return supportedFiles;
}

void Osmo4::OnOpenFile()
{
        CString sFiles = GetFileFilter();
        u32 nb_items;

        /*looks like there's a bug here, main filter isn't used correctly while the others are*/
        CFileDialog fd(TRUE,NULL,NULL, OFN_ALLOWMULTISELECT | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST , sFiles);
        fd.m_ofn.nMaxFile = 25000;
        fd.m_ofn.lpstrFile = (char *) gf_malloc(sizeof(char) * fd.m_ofn.nMaxFile);
        fd.m_ofn.lpstrFile[0] = 0;

        if (fd.DoModal()!=IDOK) {
                gf_free(fd.m_ofn.lpstrFile);
                return;
        }

        CMainFrame *pFrame = (CMainFrame *) m_pMainWnd;

        nb_items = 0;
        POSITION pos = fd.GetStartPosition();
        while (pos) {
                CString file = fd.GetNextPathName(pos);
                nb_items++;
        }
        /*if several items, act as playlist (replace playlist), otherwise as browser (lost all "next" context)*/
        if (nb_items==1)
                pFrame->m_pPlayList->Truncate();
        else
                pFrame->m_pPlayList->Clear();

        pos = fd.GetStartPosition();
        while (pos) {
                CString file = fd.GetNextPathName(pos);
                pFrame->m_pPlayList->QueueURL(file);
        }
        gf_free(fd.m_ofn.lpstrFile);
        pFrame->m_pPlayList->RefreshList();
        pFrame->m_pPlayList->PlayNext();
}


void Osmo4::Pause()
{
        if (!m_isopen) return;
        gf_term_set_option(m_term, GF_OPT_PLAY_STATE, (gf_term_get_option(m_term, GF_OPT_PLAY_STATE)==GF_STATE_PLAYING) ? GF_STATE_PAUSED : GF_STATE_PLAYING);
}

void Osmo4::OnMainPause()
{
        Pause();
}

void Osmo4::OnFileStep()
{
        gf_term_set_option(m_term, GF_OPT_PLAY_STATE, GF_STATE_STEP_PAUSE);
        ((CMainFrame *) m_pMainWnd)->m_wndToolBar.SetButtonInfo(5, ID_FILE_PLAY, TBBS_BUTTON, 3);
}
void Osmo4::OnUpdateFileStep(CCmdUI* pCmdUI)
{
        pCmdUI->Enable(m_isopen && !m_reset);
}

void Osmo4::PlayFromTime(u32 time)
{
        Bool do_pause;
        if (start_mode==1) do_pause = GF_TRUE;
        else if (start_mode==2) do_pause = GF_FALSE;
        else do_pause = /*!m_AutoPlay*/GF_FALSE;
        gf_term_play_from_time(m_term, time, do_pause);
        m_reset = GF_FALSE;
}


void Osmo4::OnFileReload()
{
        gf_term_disconnect(m_term);
        m_pMainWnd->PostMessage(WM_OPENURL);
}

void Osmo4::OnFileMigrate()
{
}

void Osmo4::OnConfigReload()
{
        gf_term_set_option(m_term, GF_OPT_RELOAD_CONFIG, 1);
}

void Osmo4::UpdatePlayButton(Bool force_play)
{
        if (!force_play && gf_term_get_option(m_term, GF_OPT_PLAY_STATE)==GF_STATE_PLAYING) {
                ((CMainFrame *) m_pMainWnd)->m_wndToolBar.SetButtonInfo(5, ID_FILE_PLAY, TBBS_BUTTON, 4);
        } else {
                ((CMainFrame *) m_pMainWnd)->m_wndToolBar.SetButtonInfo(5, ID_FILE_PLAY, TBBS_BUTTON, 3);
        }
}

void Osmo4::OnFilePlay()
{
        if (m_isopen) {
                if (m_reset) {
                        m_reset = GF_FALSE;
                        PlayFromTime(0);
                        ((CMainFrame *)m_pMainWnd)->SetProgTimer(GF_TRUE);
                } else {
                        Pause();
                }
                UpdatePlayButton();
        } else {
                ((CMainFrame *) m_pMainWnd)->m_pPlayList->Play();
        }
}

void Osmo4::OnUpdateFilePlay(CCmdUI* pCmdUI)
{
        if (m_isopen) {
                pCmdUI->Enable(TRUE);
                if (pCmdUI->m_nID==ID_FILE_PLAY) {
                        if (!m_isopen) {
                                pCmdUI->SetText("Play/Pause\tCtrl+P");
                        } else if (gf_term_get_option(m_term, GF_OPT_PLAY_STATE)==GF_STATE_PLAYING) {
                                pCmdUI->SetText("Pause\tCtrl+P");
                        } else {
                                pCmdUI->SetText("Resume\tCtrl+P");
                        }
                }
        } else {
                pCmdUI->Enable(((CMainFrame *)m_pMainWnd)->m_pPlayList->HasValidEntries() );
                pCmdUI->SetText("Play\tCtrl+P");
        }
}

void Osmo4::OnFileStop()
{
        CMainFrame *pFrame = (CMainFrame *) m_pMainWnd;
        if (m_reset) return;
        if (gf_term_get_option(m_term, GF_OPT_PLAY_STATE)==GF_STATE_PLAYING) Pause();
        m_reset = GF_TRUE;
        pFrame->m_Sliders.m_PosSlider.SetPos(0);
        pFrame->SetProgTimer(GF_FALSE);
        pFrame->m_wndToolBar.SetButtonInfo(5, ID_FILE_PLAY, TBBS_BUTTON, 3);
        start_mode = 2;
}

void Osmo4::OnUpdateFileStop(CCmdUI* pCmdUI)
{
//      pCmdUI->Enable(m_isopen);
}

void Osmo4::OnSwitchRender()
{
        const char *opt = gf_cfg_get_key(m_user.config, "Compositor", "OpenGLMode");
        Bool use_gl = (opt && !stricmp(opt, "always")) ? GF_TRUE : GF_FALSE;
        gf_cfg_set_key(m_user.config, "Compositor", "OpenGLMode", use_gl ? "disable" : "always");

        gf_term_set_option(m_term, GF_OPT_USE_OPENGL, !use_gl);

        UpdateRenderSwitch();
}

void Osmo4::UpdateRenderSwitch()
{
        const char *opt = gf_cfg_get_key(m_user.config, "Compositor", "OpenGLMode");
        if (opt && !stricmp(opt, "disable"))
                ((CMainFrame *) m_pMainWnd)->m_wndToolBar.SetButtonInfo(12, ID_SWITCH_RENDER, TBBS_BUTTON, 10);
        else
                ((CMainFrame *) m_pMainWnd)->m_wndToolBar.SetButtonInfo(12, ID_SWITCH_RENDER, TBBS_BUTTON, 9);
}

/* [<][>][^][v][top][bottom][index][help] */