/* * setup_menu.c: Setup Menu * * See the main source file 'xineliboutput.c' for copyright information and * how to reach the author. * * $Id: setup_menu.c,v 1.78 2010-11-17 13:49:28 phintuka Exp $ * */ #include "features.h" #include #include #include #include #include "config.h" #include "device.h" #include "menuitems.h" #include "osd.h" // cXinelibOsdProvider::RefreshOsd() #include "setup_menu.h" #define indent(x) Label_Ident(x) #define inden2(x) Label_Ident(Label_Ident(x)) namespace XinelibOutputSetupMenu { //#define INTEGER_CONFIG_VIDEO_CONTROLS //#define LINEAR_VIDEO_CONTROLS //#define LOGARITHM_SCALING #define ISNUMBERKEY(k) (RAWKEY(k) >= k0 && RAWKEY(k) <= k9) //--- Setup Menu ------------------------------------------------------------- const char *ModeLineChars = " 0123456789+-hvsync."; const char *DriverNameChars = " abcdefghijklmnopqrstuvwxyz0123456789-.,#~:;"; const char *OptionsChars = "=.,abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; const char *LangNameChars = "abcdefghijklmnopqrstuvwxyz"; const char *controls[] = { "Off", "[|---------------]","[|---------------]", "[-|--------------]","[-|--------------]", "[--|-------------]","[--|-------------]", "[---|------------]","[---|------------]", "[----|-----------]","[----|-----------]", "[-----|----------]","[-----|----------]", "[------|---------]","[------|---------]", "[-------|--------]","[-------|--------]", "[--------|-------]","[--------|-------]", "[---------|------]","[---------|------]", "[----------|-----]","[----------|-----]", "[-----------|----]","[-----------|----]", "[------------|---]","[------------|---]", "[-------------|--]","[-------------|--]", "[--------------|-]","[--------------|-]", "[---------------|]","[---------------|]", NULL }; #ifdef LINEAR_VIDEO_CONTROLS # define CONTROL_TO_INDEX(val) ((val)>=0 ? ((val)>>11)+1 : 0) # define INDEX_TO_CONTROL(ind) ((ind)==0 ? -1 : ((ind)-1)<<11) #else #ifdef LOGARITHM_SCALING const int ind2ctrl_tbl[33] = { -1, 0, 0x0001, 0x0002, 0x0003, 0x0004, 0x0007, 0x000a, 0x000f, 0x0014, 0x001f, 42, 0x003f, 80, 0x007f, 170, 0x00ff, 336, 0x01ff, 682, 0x03ff, 1630, 0x07ff, 2730, 0x0fff, 5726, 0x1fff, 10858, 0x3fff, 22110, 0x7fff, 43224, 0xffff }; #else const int ind2ctrl_tbl[33] = { -1, 0x0000, 0x0843, 0x1085, 0x18c7, 0x2109, 0x294b, 0x318d, 0x39cf, 0x4211, 0x4a53, 0x5295, 0x5ad7, 0x6319, 0x6b5b, 0x739d, 0x7bdf, 0x8421, 0x8c63, 0x94a5, 0x9ce7, 0xa529, 0xad6b, 0xb5ad, 0xbdef, 0xc631, 0xce73, 0xd6b5, 0xdef7, 0xe739, 0xef7b, 0xf7bd, 0xffff }; #endif static int CONTROL_TO_INDEX(int val) { for(int i=0; i<33;i++) if(val<=ind2ctrl_tbl[i]) return i; return 32; } static int INDEX_TO_CONTROL(int ind) { if(ind<0) ind=0; if(ind>32) ind=32; return ind2ctrl_tbl[ind]; } #endif //--- cMenuSetupAudio -------------------------------------------------------- class cMenuSetupAudio : public cMenuSetupPage { private: config_t newconfig; int visualization; int goom_width, goom_height, goom_fps; cOsdItem *audio_ctrl_speakers; cOsdItem *audio_ctrl_volume; cOsdItem *audio_ctrl_delay; cOsdItem *audio_ctrl_compression; cOsdItem *audio_ctrl_upmix; cOsdItem *audio_ctrl_surround; cOsdItem *audio_ctrl_headphone; cOsdItem *audio_ctrl_vis; protected: virtual void Store(void); void Set(void); public: cMenuSetupAudio(void); ~cMenuSetupAudio(void); virtual eOSState ProcessKey(eKeys Key); }; cMenuSetupAudio::cMenuSetupAudio(void) { memcpy(&newconfig, &xc, sizeof(config_t)); visualization = strstra(xc.audio_visualization, xc.s_audioVisualizations, 0); goom_width = 720; goom_height = 576; goom_fps = 25; char *pt; if(NULL != (pt=strstr(xc.audio_vis_goom_opts, "width="))) goom_width = max(320, min(1920, atoi(pt+6))); if(NULL != (pt=strstr(xc.audio_vis_goom_opts, "height="))) goom_height = max(240, min(1280, atoi(pt+7))); if(NULL != (pt=strstr(xc.audio_vis_goom_opts, "fps="))) goom_fps = max(1, min(100, atoi(pt+4))); Set(); } cMenuSetupAudio::~cMenuSetupAudio(void) { cXinelibDevice::Instance().ConfigurePostprocessing( xc.deinterlace_method, xc.audio_delay, xc.audio_compression, xc.audio_equalizer, xc.audio_surround, xc.speaker_type); cXinelibDevice::Instance().ConfigurePostprocessing( "upmix", xc.audio_upmix ? true : false, NULL); #ifdef ENABLE_TEST_POSTPLUGINS cXinelibDevice::Instance().ConfigurePostprocessing( "headphone", xc.headphone ? true : false, NULL); #endif } void cMenuSetupAudio::Set(void) { SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); int current = Current(); Clear(); Add(SeparatorItem(tr("Audio"))); Add(audio_ctrl_speakers = new cMenuEditStraI18nItem(tr("Speakers"), &newconfig.speaker_type, SPEAKERS_count, xc.s_speakerArrangements)); Add(audio_ctrl_volume = new cMenuEditBoolItem(tr("Volume control"), &newconfig.sw_volume_control, tr("Hardware"), tr("Software"))); Add(audio_ctrl_delay = new cMenuEditTypedIntItem(tr("Delay"), tr("ms"), &newconfig.audio_delay, -3000, 3000, tr("Off"))); Add(audio_ctrl_compression = new cMenuEditTypedIntItem(tr("Audio Compression"), "%", &newconfig.audio_compression, 100, 500, NULL, tr("Off"))); Add(audio_ctrl_upmix = new cMenuEditBoolItem(tr("Upmix stereo to 5.1"), &newconfig.audio_upmix)); Add(audio_ctrl_surround = new cMenuEditBoolItem(tr("Downmix AC3 to surround"), &newconfig.audio_surround)); #ifdef ENABLE_TEST_POSTPLUGINS Add(audio_ctrl_headphone = new cMenuEditBoolItem(tr("Mix to headphones"), &newconfig.headphone)); #else audio_ctrl_headphone = NULL; #endif Add(audio_ctrl_vis = new cMenuEditStraI18nItem(tr("Visualization"), &visualization, AUDIO_VIS_count, xc.s_audioVisualizationNames)); if(visualization == AUDIO_VIS_GOOM) { Add(new cMenuEditTypedIntItem(indent(tr("Width")), tr("px"), &goom_width, 320, 1920)); Add(new cMenuEditTypedIntItem(indent(tr("Height")),tr("px"), &goom_height, 240, 1280)); Add(new cMenuEditTypedIntItem(indent(tr("Speed")), tr("fps"), &goom_fps, 1, 100)); } else if(visualization == AUDIO_VIS_IMAGE) { Add(new cMenuEditStrItem(indent(tr("Background image")), newconfig.audio_vis_image_opts, sizeof(newconfig.audio_vis_image_opts))); } if(current<1) current=1; /* first item is not selectable */ SetCurrent(Get(current)); Display(); } eOSState cMenuSetupAudio::ProcessKey(eKeys Key) { cOsdItem *item = Get(Current()); eOSState state = cMenuSetupPage::ProcessKey(Key); Key = NORMALKEY(Key); if(Key!=kLeft && Key!=kRight) return state; if(item == audio_ctrl_delay || item == audio_ctrl_compression) { cXinelibDevice::Instance().ConfigurePostprocessing( xc.deinterlace_method, newconfig.audio_delay, newconfig.audio_compression, newconfig.audio_equalizer, newconfig.audio_surround, newconfig.speaker_type); } else if(item == audio_ctrl_vis) { Set(); } else if(item == audio_ctrl_speakers) { cXinelibDevice::Instance().ConfigurePostprocessing( xc.deinterlace_method, newconfig.audio_delay, newconfig.audio_compression, newconfig.audio_equalizer, newconfig.audio_surround, newconfig.speaker_type); if(newconfig.speaker_type <= SPEAKERS_STEREO && newconfig.audio_upmix) { newconfig.audio_upmix = false; Set(); } } else if(item == audio_ctrl_surround) { cXinelibDevice::Instance().ConfigurePostprocessing( xc.deinterlace_method, newconfig.audio_delay, newconfig.audio_compression, newconfig.audio_equalizer, newconfig.audio_surround, newconfig.speaker_type); if(newconfig.audio_surround && newconfig.audio_upmix) { newconfig.audio_upmix = 0; Set(); } } else if(item == audio_ctrl_volume) { // trigger volume control message by toggling mute cRemote::Put(kMute); cRemote::Put(kMute); } else if(item == audio_ctrl_upmix) { cXinelibDevice::Instance().ConfigurePostprocessing( "upmix", newconfig.audio_upmix ? true : false, NULL); if(newconfig.audio_upmix && newconfig.audio_surround) { newconfig.audio_surround = 0; Set(); } } #ifdef ENABLE_TEST_POSTPLUGINS else if(item == audio_ctrl_headphone) { cXinelibDevice::Instance().ConfigurePostprocessing( "headphone", newconfig.headphone ? true : false, NULL); } #endif return state; } void cMenuSetupAudio::Store(void) { memcpy(&xc, &newconfig, sizeof(config_t)); strn0cpy(xc.audio_visualization, xc.s_audioVisualizations[visualization], sizeof(xc.audio_visualization)); snprintf(xc.audio_vis_goom_opts, sizeof(xc.audio_vis_goom_opts), "width=%d,height=%d,fps=%d", goom_width, goom_height, goom_fps); xc.audio_vis_goom_opts[sizeof(xc.audio_vis_goom_opts)-1] = 0; SetupStore("Audio.Speakers", xc.s_speakerArrangements[xc.speaker_type]); SetupStore("Audio.Delay", xc.audio_delay); SetupStore("Audio.Compression", xc.audio_compression); SetupStore("Audio.Surround", xc.audio_surround); SetupStore("Audio.Upmix", xc.audio_upmix); SetupStore("Audio.Headphone", xc.headphone); SetupStore("Audio.Visualization",xc.audio_visualization); SetupStore("Audio.Visualization.GoomOpts",xc.audio_vis_goom_opts); SetupStore("Audio.Visualization.ImageOpts",xc.audio_vis_image_opts); SetupStore("Audio.SoftwareVolumeControl", xc.sw_volume_control); Setup.Save(); } //--- cMenuSetupAudioEq ------------------------------------------------------ class cMenuSetupAudioEq : public cMenuSetupPage { private: config_t newconfig; protected: virtual void Store(void); void Set(void); public: cMenuSetupAudioEq(void); ~cMenuSetupAudioEq(void); virtual eOSState ProcessKey(eKeys Key); }; cMenuSetupAudioEq::cMenuSetupAudioEq(void) { memcpy(&newconfig, &xc, sizeof(config_t)); Set(); } cMenuSetupAudioEq::~cMenuSetupAudioEq(void) { cXinelibDevice::Instance().ConfigurePostprocessing( xc.deinterlace_method, xc.audio_delay, xc.audio_compression, xc.audio_equalizer, xc.audio_surround, xc.speaker_type); } void cMenuSetupAudioEq::Set(void) { SetPlugin(cPluginManager::GetPlugin(PLUGIN_NAME_I18N)); int current = Current(); Clear(); Add(SeparatorItem(tr("Audio Equalizer"))); for(int i=0; i #define OSD_W (720-2) #define OSD_H (576-2) #define OSD_X (1) #define OSD_Y (1) // // cTestGrayscale // class cTestGrayscale : public cOsdObject { private: cOsd *m_Osd; public: cTestGrayscale() { m_Osd = NULL; } virtual ~cTestGrayscale() { delete m_Osd; } virtual void Show(); virtual eOSState ProcessKey(eKeys Key); }; void cTestGrayscale::Show() { tArea areas [] = { { 0, 0, OSD_W/2 - 1, OSD_H - 1, 8}, {OSD_W/2, 0, OSD_W - 1, OSD_H - 1, 8}}; int i; if(!m_Osd) m_Osd = cOsdProvider::NewOsd(OSD_X, OSD_Y, 0); if(m_Osd) { if (m_Osd->CanHandleAreas(areas, sizeof(areas) / sizeof(tArea) ) == oeOk) { m_Osd->SetAreas(areas, sizeof(areas) / sizeof(tArea)); m_Osd->Flush(); // border m_Osd->DrawRectangle(0, 0, OSD_W - 1, OSD_H - 1, 0xff000000); m_Osd->DrawRectangle(1, 1, OSD_W - 2, OSD_H - 2, 0xff000000); // background m_Osd->DrawRectangle(2, 2, 2+103, OSD_H - 3, 0xffffffff); m_Osd->DrawRectangle(OSD_W-2-103, 2, OSD_W-2, OSD_H - 3, 0xff000000); for(i=0; i<0xff; i++) m_Osd->DrawRectangle(2+103+2*i, 2, 2+103+2*(i+1), OSD_H - 3, 0xff000000|(i*0x00010101)/*=(i<<16)|(i<<8)|(i)*/); // line m_Osd->DrawRectangle(1, OSD_H/2-20, OSD_W - 2, OSD_H/2, 0xffffffff); m_Osd->DrawRectangle(1, OSD_H/2+1, OSD_W - 2, OSD_H/2+21, 0xff000000); // Cross for(int x=0; xDrawPixel(x, x*OSD_H/OSD_W, 0x00000000); m_Osd->DrawPixel(x, OSD_H - 1 - x*OSD_H/OSD_W, 0x00000000); } // commit m_Osd->Flush(); } } } eOSState cTestGrayscale::ProcessKey(eKeys key) { char s[32]; static int br = xc.brightness; static int co = xc.contrast; eOSState state = cOsdObject::ProcessKey(key); if (state == osUnknown) { switch (key & ~k_Repeat) { case kOk: case kBack: return osEnd; case kRight: br += 0xffff/1024*2; case kLeft: br -= 0xffff/1024; sprintf(s, "b %d", br); m_Osd->DrawText(400, 100, s, 0xff000000, 0xffffffff, cFont::GetFont(fontSml)); cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, br, xc.sharpness, xc.noise_reduction, co, xc.overscan, xc.vo_aspect_ratio); m_Osd->Flush(); return osContinue; case kUp: co += 0xffff/1024*2; case kDown: co -= 0xffff/1024; sprintf(s, "c %d", co); m_Osd->DrawText(400, 130, s, 0xff000000, 0xffffffff, cFont::GetFont(fontSml)); cXinelibDevice::Instance().ConfigureVideo(xc.hue, xc.saturation, br, xc.sharpness, xc.noise_reduction, co, xc.overscan, xc.vo_aspect_ratio); m_Osd->Flush(); return osContinue; default:; // all other keys - do nothing. } } return state; } // // cTestBitmap // class cTestBitmap : public cOsdObject { private: cOsd *m_Osd; int bpp; public: cTestBitmap(int _bpp = 1) { m_Osd = NULL; if(_bpp<1) _bpp = 1; if(_bpp>6) _bpp = 6; bpp = 1<<_bpp; } virtual ~cTestBitmap() { delete m_Osd; } virtual void Show(); virtual eOSState ProcessKey(eKeys Key); }; void cTestBitmap::Show() { tArea areas [] = {{ 0, 0, OSD_W - 1, OSD_H - 1, 8}}; int x, y, bit = 0; if(!m_Osd) { m_Osd = cOsdProvider::NewOsd(OSD_X, OSD_Y, 0); if(m_Osd) { if (m_Osd->CanHandleAreas(areas, sizeof(areas) / sizeof(tArea) ) == oeOk) { m_Osd->SetAreas(areas, sizeof(areas) / sizeof(tArea)); m_Osd->Flush(); } } } if(m_Osd) { for(x=0; xDrawRectangle(x, y, x+bpp, y+bpp, bit?0xffffffff:0xff000000); bit = !bit; } } // commit m_Osd->Flush(); } } eOSState cTestBitmap::ProcessKey(eKeys key) { eOSState state = cOsdObject::ProcessKey(key); if (state == osUnknown) { switch (key & ~k_Repeat) { case kOk: case kBack: return osEnd; case kRight: bpp = (bpp<64) ? (bpp<<1) : 1; Show(); return osContinue; case kLeft: bpp = (bpp>1) ? (bpp>>1) : 64; Show(); return osContinue; default: break; } } return state; } // // cMenuTestImages // #include // CallPlugin extern cOsdObject *g_PendingMenuAction; class cMenuTestImages : public cMenuSetupPage { protected: void Set(void); virtual void Store(void) {}; public: cMenuTestImages(); virtual eOSState ProcessKey(eKeys Key); }; cMenuTestImages::cMenuTestImages() { Set(); } void cMenuTestImages::Set(void) { char buf[128]; Clear(); SetHasHotkeys(); Add(new cOsdItem(tr("Grayscale"), osUser1)); snprintf(buf, sizeof(buf), "%s 1bit", tr("Bitmap")); buf[sizeof(buf)-1] = 0; Add(new cOsdItem(buf, osUser2)); snprintf(buf, sizeof(buf), "%s 4bit", tr("Bitmap")); buf[sizeof(buf)-1] = 0; Add(new cOsdItem(buf, osUser3)); Display(); } eOSState cMenuTestImages::ProcessKey(eKeys Key) { eOSState state = cMenuSetupPage::ProcessKey(Key); switch (state) { case osUser1: if(cRemote::CallPlugin("xineliboutput")) g_PendingMenuAction = new cTestGrayscale(); return osEnd; case osUser2: if(cRemote::CallPlugin("xineliboutput")) g_PendingMenuAction = new cTestBitmap(1); return osEnd; case osUser3: if(cRemote::CallPlugin("xineliboutput")) g_PendingMenuAction = new cTestBitmap(4); return osEnd; default: ; } return state; } //--- cMenuSetupXinelib ------------------------------------------------------ cMenuSetupXinelib::cMenuSetupXinelib(void) { XinelibOutputSetupMenu::controls[0] = tr("Off"); Set(); } void cMenuSetupXinelib::Set(void) { Clear(); SetHasHotkeys(); Add(new cOsdItem(hk(tr("Audio")), osUser1)); Add(new cOsdItem(hk(tr("Audio Equalizer")),osUser2)); Add(new cOsdItem(hk(tr("Video")), osUser3)); Add(new cOsdItem(hk(tr("OSD")), osUser4)); //Add(new cOsdItem(hk(tr("Decoder")), osUser5)); Add(new cOsdItem(hk(tr("Media Player")), osUser5)); Add(new cOsdItem(hk(tr("Local Frontend")), osUser6)); Add(new cOsdItem(hk(tr("Remote Clients")), osUser7)); Add(new cOsdItem(hk(tr("Test Images")), osUser8)); Display(); } eOSState cMenuSetupXinelib::ProcessKey(eKeys Key) { eOSState state = cMenuSetupPage::ProcessKey(Key); switch (state) { case osUser1: return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupAudio); case osUser2: return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupAudioEq); case osUser3: return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupVideo); case osUser4: return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupOSD); case osUser5: return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupMediaPlayer); case osUser6: return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupLocal); case osUser7: return AddSubMenu(new XinelibOutputSetupMenu::cMenuSetupRemote); case osUser8: return AddSubMenu(new cMenuTestImages); default: ; } return state; }