diff -Nru sview-13.10/Makefile sview-14.01/Makefile
--- sview-13.10/Makefile 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/Makefile 2014-01-30 10:45:04.000000000 +0000
@@ -72,9 +72,10 @@
rm -f $(DESTDIR)/usr/$(USR_LIB)/sView/*.a
pre_all:
- mkdir -p $(BUILD_ROOT)/lang/english
+ mkdir -p $(BUILD_ROOT)/lang/English
mkdir -p $(BUILD_ROOT)/lang/русский
mkdir -p $(BUILD_ROOT)/lang/français
+ mkdir -p $(BUILD_ROOT)/lang/Deutsch
mkdir -p $(BUILD_ROOT)/textures
mkdir -p $(BUILD_ROOT)/web
cp -f -r textures/*.png $(BUILD_ROOT)/textures/
@@ -131,9 +132,10 @@
pre_StOutAnaglyph:
mkdir -p $(BUILD_ROOT)/shaders/StOutAnaglyph/
cp -f -r StOutAnaglyph/shaders/* $(BUILD_ROOT)/shaders/StOutAnaglyph/
- cp -f -r StOutAnaglyph/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StOutAnaglyph/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StOutAnaglyph/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StOutAnaglyph/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StOutAnaglyph/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
clean_StOutAnaglyph:
rm -f $(aStOutAnaglyph)
rm -rf StOutAnaglyph/*.o
@@ -145,9 +147,10 @@
$(aStOutDual) : pre_StOutDual $(aStOutDual_OBJS)
$(LD) -shared -z defs $(LDFLAGS) $(LIBDIR) $(aStOutDual_OBJS) $(aStOutDual_LIB) -o $(aStOutDual)
pre_StOutDual:
- cp -f -r StOutDual/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StOutDual/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StOutDual/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StOutDual/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StOutDual/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
clean_StOutDual:
rm -f $(aStOutDual)
rm -rf StOutDual/*.o
@@ -161,9 +164,10 @@
pre_StOutIZ3D:
mkdir -p $(BUILD_ROOT)/shaders/StOutIZ3D/
cp -f -r StOutIZ3D/shaders/* $(BUILD_ROOT)/shaders/StOutIZ3D/
- cp -f -r StOutIZ3D/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StOutIZ3D/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StOutIZ3D/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StOutIZ3D/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StOutIZ3D/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
clean_StOutIZ3D:
rm -f $(aStOutIZ3D)
rm -rf StOutIZ3D/*.o
@@ -177,9 +181,10 @@
pre_StOutInterlace:
mkdir -p $(BUILD_ROOT)/shaders/StOutInterlace/
cp -f -r StOutInterlace/shaders/* $(BUILD_ROOT)/shaders/StOutInterlace/
- cp -f -r StOutInterlace/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StOutInterlace/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StOutInterlace/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StOutInterlace/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StOutInterlace/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
clean_StOutInterlace:
rm -f $(aStOutInterlace)
rm -rf StOutInterlace/*.o
@@ -191,9 +196,10 @@
$(aStOutPageFlip) : pre_StOutPageFlip $(aStOutPageFlip_OBJS)
$(LD) -shared -z defs $(LDFLAGS) $(LIBDIR) $(aStOutPageFlip_OBJS) $(aStOutPageFlip_LIB) -o $(aStOutPageFlip)
pre_StOutPageFlip:
- cp -f -r StOutPageFlip/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StOutPageFlip/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StOutPageFlip/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StOutPageFlip/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StOutPageFlip/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
clean_StOutPageFlip:
rm -f $(aStOutPageFlip)
rm -rf StOutPageFlip/*.o
@@ -205,9 +211,10 @@
$(aStOutDistorted) : pre_StOutDistorted $(aStOutDistorted_OBJS)
$(LD) -shared -z defs $(LDFLAGS) $(LIBDIR) $(aStOutDistorted_OBJS) $(aStOutDistorted_LIB) -o $(aStOutDistorted)
pre_StOutDistorted:
- cp -f -r StOutDistorted/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StOutDistorted/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StOutDistorted/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StOutDistorted/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StOutDistorted/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
clean_StOutDistorted:
rm -f $(aStOutDistorted)
rm -rf StOutDistorted/*.o
@@ -219,9 +226,10 @@
$(aStImageViewer) : pre_StImageViewer $(aStImageViewer_OBJS)
$(LD) -shared -z defs $(LDFLAGS) $(LIBDIR) $(aStImageViewer_OBJS) $(aStImageViewer_LIB) -o $(aStImageViewer)
pre_StImageViewer:
- cp -f -r StImageViewer/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StImageViewer/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StImageViewer/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StImageViewer/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StImageViewer/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
clean_StImageViewer:
rm -f $(aStImageViewer)
rm -rf StImageViewer/*.o
@@ -237,9 +245,10 @@
$(aStMoviePlayer) : pre_StMoviePlayer $(aStMoviePlayer_OBJS1) $(aStMoviePlayer_OBJS2) $(aStMoviePlayer_OBJS3)
$(LD) -shared -z defs $(LDFLAGS) $(LIBDIR) $(aStMoviePlayer_OBJS1) $(aStMoviePlayer_OBJS2) $(aStMoviePlayer_OBJS3) $(aStMoviePlayer_LIB) -o $(aStMoviePlayer)
pre_StMoviePlayer:
- cp -f -r StMoviePlayer/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StMoviePlayer/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StMoviePlayer/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StMoviePlayer/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StMoviePlayer/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
cp -f -r StMoviePlayer/web/* $(BUILD_ROOT)/web/
clean_StMoviePlayer:
rm -f $(aStMoviePlayer)
@@ -252,9 +261,10 @@
$(aStDiagnostics) : pre_StDiagnostics $(aStDiagnostics_OBJS)
$(LD) -shared -z defs $(LDFLAGS) $(LIBDIR) $(aStDiagnostics_OBJS) $(aStDiagnostics_LIB) -o $(aStDiagnostics)
pre_StDiagnostics:
- cp -f -r StDiagnostics/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StDiagnostics/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StDiagnostics/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StDiagnostics/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StDiagnostics/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
clean_StDiagnostics:
rm -f $(aStDiagnostics)
rm -rf StDiagnostics/*.o
@@ -269,9 +279,10 @@
$(aStCADViewer) : pre_StCADViewer $(aStCADViewer_OBJS)
$(LD) -shared -z defs $(LDFLAGS) $(LIBDIR) $(aStCADViewer_OBJS) $(aStCADViewer_LIB) -o $(aStCADViewer)
pre_StCADViewer:
- cp -f -r StCADViewer/lang/english/* $(BUILD_ROOT)/lang/english/
+ cp -f -r StCADViewer/lang/english/* $(BUILD_ROOT)/lang/English/
cp -f -r StCADViewer/lang/russian/* $(BUILD_ROOT)/lang/русский/
cp -f -r StCADViewer/lang/french/* $(BUILD_ROOT)/lang/français/
+ cp -f -r StCADViewer/lang/german/* $(BUILD_ROOT)/lang/Deutsch/
clean_StCADViewer:
rm -f $(aStCADViewer)
rm -rf StCADViewer/*.o
diff -Nru sview-13.10/StCADViewer/StCADViewer.cbp sview-14.01/StCADViewer/StCADViewer.cbp
--- sview-13.10/StCADViewer/StCADViewer.cbp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCADViewer/StCADViewer.cbp 2014-01-30 10:45:03.000000000 +0000
@@ -38,12 +38,7 @@
-
-
-
-
-
-
+
@@ -78,12 +73,7 @@
-
-
-
-
-
-
+
@@ -125,12 +115,7 @@
-
-
-
-
-
-
+
@@ -166,12 +151,7 @@
-
-
-
-
-
-
+
@@ -201,12 +181,7 @@
-
-
-
-
-
-
+
@@ -235,12 +210,7 @@
-
-
-
-
-
-
+
@@ -266,12 +236,7 @@
-
-
-
-
-
-
+
@@ -299,12 +264,7 @@
-
-
-
-
-
-
+
@@ -373,6 +333,9 @@
+
+
+
diff -Nru sview-13.10/StCADViewer/StCADViewer.rc sview-14.01/StCADViewer/StCADViewer.rc
--- sview-13.10/StCADViewer/StCADViewer.rc 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCADViewer/StCADViewer.rc 2014-01-30 10:45:03.000000000 +0000
@@ -15,7 +15,7 @@
BEGIN
VALUE "FileDescription", "Stereoscopic CAD Viewer\000"
VALUE "FileVersion", SVIEW_SDK_VER_STRING "\000"
- VALUE "LegalCopyright", "\251 2011-2013 Kirill Gavrilov\000"
+ VALUE "LegalCopyright", "\251 2011-2014 Kirill Gavrilov\000"
VALUE "ProductName", "StCADViewer\000"
VALUE "ProductVersion", SVIEW_SDK_VER_STRING "\000"
VALUE "OfficialSite", "www.sview.ru\000"
diff -Nru sview-13.10/StCADViewer/StCADViewerGUI.cpp sview-14.01/StCADViewer/StCADViewerGUI.cpp
--- sview-13.10/StCADViewer/StCADViewerGUI.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCADViewer/StCADViewerGUI.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -207,8 +207,8 @@
const StString& aVerString = myLangMap->changeValueId(ABOUT_VERSION, "version");
const StString& aDescr = myLangMap->changeValueId(ABOUT_DESCRIPTION,
"CAD viewer allows you to view CAD files in formats IGES, STEP, BREP using OCCT.\n"
- "(C) 2011-2013 Kirill Gavrilov (kirill@sview.ru).\nOfficial site: www.sview.ru");
- StGLMessageBox* anAboutDialog = new StGLMessageBox(this, aTitle + '\n'
+ "(C) 2011-2014 Kirill Gavrilov (kirill@sview.ru).\nOfficial site: www.sview.ru");
+ StGLMessageBox* anAboutDialog = new StGLMessageBox(this, "", aTitle + '\n'
+ aVerString + ": " + StVersionInfo::getSDKVersionString() + "\n \n" + aDescr,
512, 300);
anAboutDialog->addButton("Close");
diff -Nru sview-13.10/StCADViewer/lang/english/StCADViewer.lng sview-14.01/StCADViewer/lang/english/StCADViewer.lng
--- sview-13.10/StCADViewer/lang/english/StCADViewer.lng 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCADViewer/lang/english/StCADViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -23,4 +23,4 @@
1504="Language"
3000="sView - Tiny CAD Viewer"
3001="version"
-3002="CAD viewer allows you to view CAD files in formats IGES, STEP, BREP using OpenCASCADE Technology.\n © 2011-2013 Kirill Gavrilov (kirill@sview.ru).\nOfficial site: www.sview.ru"
+3002="CAD viewer allows you to view CAD files in formats IGES, STEP, BREP using OpenCASCADE Technology.\n © 2011-2014 Kirill Gavrilov (kirill@sview.ru).\nOfficial site: www.sview.ru"
diff -Nru sview-13.10/StCADViewer/lang/french/StCADViewer.lng sview-14.01/StCADViewer/lang/french/StCADViewer.lng
--- sview-13.10/StCADViewer/lang/french/StCADViewer.lng 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCADViewer/lang/french/StCADViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -23,4 +23,4 @@
1504="Language"
3000="sView - Tiny CAD Viewer"
3001="version"
-3002="CAD viewer allows you to view CAD files in formats IGES, STEP, BREP using OpenCASCADE Technology.\n © 2011-2013 Kirill Gavrilov (kirill@sview.ru).\nOfficial site: www.sview.ru"
+3002="CAD viewer allows you to view CAD files in formats IGES, STEP, BREP using OpenCASCADE Technology.\n © 2011-2014 Kirill Gavrilov (kirill@sview.ru).\nOfficial site: www.sview.ru"
diff -Nru sview-13.10/StCADViewer/lang/german/StCADViewer.lng sview-14.01/StCADViewer/lang/german/StCADViewer.lng
--- sview-13.10/StCADViewer/lang/german/StCADViewer.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StCADViewer/lang/german/StCADViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1,26 @@
+German translation file for StCADViewer
+@author Kirill Gavrilov
+
+--------
+1200="Ansicht"
+1201="Projection type"
+1202="Vollbild"
+1203="Normalen anzeigen"
+1204="Dreibein anzeigen"
+1205="Zwei einseitige Beleuchtung"
+1206="Projektion"
+1207="Füllmodus"
+1208="Fit ALL"
+1240="Orthogonal"
+1241="Perspektive"
+1242="Stereo"
+1250="Mesh"
+1251="Beschattet"
+1252="Beschattet + Mesh"
+1500="Hilfe"
+1501="Über..."
+1503="Lizenztext"
+1504="Language"
+3000="sView - winzig CAD Viewer"
+3001="Version"
+3002="CAD viewer allows you to view CAD files in formats IGES, STEP, BREP using OpenCASCADE Technology.\n © 2011-2014 Kirill Gavrilov (kirill@sview.ru).\nOfficial site: www.sview.ru"
diff -Nru sview-13.10/StCADViewer/lang/korean/StCADViewer.lng sview-14.01/StCADViewer/lang/korean/StCADViewer.lng
--- sview-13.10/StCADViewer/lang/korean/StCADViewer.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StCADViewer/lang/korean/StCADViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1,26 @@
+English translation file for StCADViewer
+@author Kirill Gavrilov
+
+--------
+1200="View"
+1201="Projection type"
+1202="Fullscreen"
+1203="Show normals"
+1204="Show trihedron"
+1205="Two sides lighting"
+1206="Projection"
+1207="Fill Mode"
+1208="Fit ALL"
+1240="Orthogonal"
+1241="Perspective"
+1242="Stereo"
+1250="Mesh"
+1251="Shaded"
+1252="Shaded + Mesh"
+1500="Help"
+1501="About..."
+1503="License text"
+1504="Language"
+3000="sView - Tiny CAD Viewer"
+3001="version"
+3002="CAD viewer allows you to view CAD files in formats IGES, STEP, BREP using OpenCASCADE Technology.\n © 2011-2014 Kirill Gavrilov (kirill@sview.ru).\nOfficial site: www.sview.ru"
diff -Nru sview-13.10/StCADViewer/lang/russian/StCADViewer.lng sview-14.01/StCADViewer/lang/russian/StCADViewer.lng
--- sview-13.10/StCADViewer/lang/russian/StCADViewer.lng 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCADViewer/lang/russian/StCADViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -23,4 +23,4 @@
1504="Language"
3000="sView - приложение для просмотра CAD моделей"
3001="версия"
-3002="Программа открывает CAD модели в форматах IGES, STEP, BREP с помощью OpenCASCADE Technology.\n © 2011-2013 Гаврилов Кирилл (kirill@sview.ru).\nОфициальный сайт: www.sview.ru"
+3002="Программа открывает CAD модели в форматах IGES, STEP, BREP с помощью OpenCASCADE Technology.\n © 2011-2014 Гаврилов Кирилл (kirill@sview.ru).\nОфициальный сайт: www.sview.ru"
diff -Nru sview-13.10/StCore/StCore.rc sview-14.01/StCore/StCore.rc
--- sview-13.10/StCore/StCore.rc 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StCore.rc 2014-01-30 10:45:03.000000000 +0000
@@ -15,7 +15,7 @@
BEGIN
VALUE "FileDescription", "sView core library\000"
VALUE "FileVersion", SVIEW_SDK_VER_STRING "\000"
- VALUE "LegalCopyright", "\251 2007-2013 Kirill Gavrilov\000"
+ VALUE "LegalCopyright", "\251 2007-2014 Kirill Gavrilov\000"
VALUE "ProductName", "StCore\000"
VALUE "ProductVersion", SVIEW_SDK_VER_STRING "\000"
VALUE "OfficialSite", "www.sview.ru\000"
diff -Nru sview-13.10/StCore/StSearchMonitors.cpp sview-14.01/StCore/StSearchMonitors.cpp
--- sview-13.10/StCore/StSearchMonitors.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StSearchMonitors.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -587,10 +587,8 @@
void StSearchMonitors::initGlobal() {
clear();
+ initFromSystem();
initFromConfig();
- if(isEmpty()) {
- initFromSystem();
- }
}
void StSearchMonitors::init(const bool theForced) {
@@ -607,46 +605,70 @@
}
}
-void StSearchMonitors::initFromConfig() {
- clear();
- const StString ST_GLOBAL_SETTINGS_GROUP("sview");
- const StString ST_GLOBAL_SETTINGS_MON_MASTER("monMaster");
- const StString ST_GLOBAL_SETTINGS_MON_SLAVE("monSlave");
-
- StSearchMonitors sysMons;
- sysMons.initFromSystem();
- if(sysMons.isEmpty()) {
- return;
+static void readMonitor(const StString& thePrefix,
+ StSettings& theConfig,
+ StMonitor& theMon) {
+ // read/override monitor properties
+ const StString aRectKey = thePrefix + stCString(".rect");
+ const StString aScaleKey = thePrefix + stCString(".scale");
+ theConfig.loadInt32Rect(aRectKey, theMon.changeVRect());
+
+ float aScale = 1.0f;
+ if(theConfig.loadFloat(aScaleKey, aScale)) {
+ theMon.setScale(aScale);
}
+}
- StMonitor aMonMaster;
- StMonitor aMonSlave;
+void StSearchMonitors::initFromConfig() {
+ const StString ST_GLOBAL_SETTINGS_GROUP("sview");
+ const StString ST_GLOBAL_SETTINGS_MONITORS("monitors");
StSettings aGlobalSettings(ST_GLOBAL_SETTINGS_GROUP);
- aGlobalSettings.loadInt32Rect(ST_GLOBAL_SETTINGS_MON_MASTER, aMonMaster.changeVRect());
- aGlobalSettings.loadInt32Rect(ST_GLOBAL_SETTINGS_MON_SLAVE, aMonSlave.changeVRect());
+ StMonitor aMonDummy;
+ for(size_t aParamIter = 0; aParamIter < 256; ++aParamIter) {
+ const StString aPrefix = ST_GLOBAL_SETTINGS_MONITORS + stCString(".") + aParamIter;
+ const StString anActiveKey = aPrefix + stCString(".active");
+ bool isActive = false;
+ aGlobalSettings.loadBool(anActiveKey, isActive);
+ if(!isActive) {
+ break;
+ }
- // save settings (to simple change them)
- aGlobalSettings.saveInt32Rect(ST_GLOBAL_SETTINGS_MON_MASTER, aMonMaster.changeVRect());
- aGlobalSettings.saveInt32Rect(ST_GLOBAL_SETTINGS_MON_SLAVE, aMonSlave.changeVRect());
-
- if(aMonMaster.isValid()) {
- StRectI_t aRectCopy = aMonMaster.getVRect();
- // copy setting from some real display
- aMonMaster = sysMons[aRectCopy.center()];
- aMonMaster.setVRect(aRectCopy);
- aMonMaster.setId(0);
- aMonMaster.setName("StMasterDisplay");
- add(aMonMaster);
- if(aMonSlave.isValid()) {
- aRectCopy = aMonSlave.getVRect();
- aMonSlave = sysMons[aRectCopy.center()];
- aMonSlave.setVRect(aRectCopy);
- aMonSlave.setId(1);
- aMonSlave.setName("StSlaveDisplay");
- add(aMonSlave);
+ // read monitor(s) identifier
+ const StString anIdKey = aPrefix + stCString(".id");
+ const StString aPnpIdKey = aPrefix + stCString(".pnpid");
+ int32_t aMonId = -1;
+ StString aPnpId;
+ aGlobalSettings.loadInt32 (anIdKey, aMonId);
+ aGlobalSettings.loadString(aPnpIdKey, aPnpId);
+ if(aPnpId.getLength() == 7) {
+ for(size_t aMonIter = 0; aMonIter < size(); ++aMonIter) {
+ StMonitor& aMon = changeValue(aMonIter);
+ if(aMon.getPnPId() == aPnpId) {
+ readMonitor(aPrefix, aGlobalSettings, aMon);
+ }
+ }
+ } else if(aMonId >= 0) {
+ for(int aMonAddIter = (int )size(); aMonAddIter <= aMonId; ++aMonAddIter) {
+ aMonDummy.setId(aMonAddIter);
+ add(aMonDummy);
+ }
+ readMonitor(aPrefix, aGlobalSettings, changeValue((size_t )aMonId));
}
}
+
+ // save sample configuration to simplify manual edition
+ const StString anActiveKey = ST_GLOBAL_SETTINGS_MONITORS + stCString(".999.active");
+ bool isActive = false;
+ if(aGlobalSettings.loadBool(anActiveKey, isActive)) {
+ return;
+ }
+
+ aGlobalSettings.saveBool (anActiveKey, false);
+ aGlobalSettings.saveInt32 (ST_GLOBAL_SETTINGS_MONITORS + stCString(".999.id"), 999);
+ aGlobalSettings.saveString (ST_GLOBAL_SETTINGS_MONITORS + stCString(".999.pnpid"), "PNP0000");
+ aGlobalSettings.saveInt32Rect(ST_GLOBAL_SETTINGS_MONITORS + stCString(".999.rect"), StRect(0, 1080, 0, 1920));
+ aGlobalSettings.saveFloat (ST_GLOBAL_SETTINGS_MONITORS + stCString(".999.scale"), 1.2f);
}
void StSearchMonitors::initFromSystem() {
diff -Nru sview-13.10/StCore/StWindow.cpp sview-14.01/StCore/StWindow.cpp
--- sview-13.10/StCore/StWindow.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StWindow.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StCore library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -43,6 +43,7 @@
StWindow::StWindow()
: myWin(new StWindowImpl((StNativeWin_t )NULL)),
myTargetFps(0.0),
+ myWasUsed(false),
myIsForcedStereo(false) {
copySignals();
}
@@ -50,6 +51,7 @@
StWindow::StWindow(const StNativeWin_t theParentWindow)
: myWin(new StWindowImpl(theParentWindow)),
myTargetFps(0.0),
+ myWasUsed(false),
myIsForcedStereo(false) {
copySignals();
}
@@ -180,6 +182,7 @@
}
bool StWindow::create() {
+ myWasUsed = true;
return myWin->create();
}
@@ -273,3 +276,7 @@
GLfloat StWindow::getLensDist() const {
return 0.0f;
}
+
+void StWindow::toClipboard(const StString& theText) {
+ myWin->toClipboard(theText);
+}
diff -Nru sview-13.10/StCore/StWindowImpl.cpp sview-14.01/StCore/StWindowImpl.cpp
--- sview-13.10/StCore/StWindowImpl.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StWindowImpl.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StCore library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -59,6 +59,7 @@
myMonMasterFull(-1),
mySyncCounter(0),
myWinOnMonitorId(0),
+ myWinMonScaleId(0),
myTiledCfg(TiledCfg_Separate),
#ifdef _WIN32
myEventInitWin(false),
@@ -94,6 +95,7 @@
attribs.Slave = StWinSlave_slaveOff;
attribs.SlaveMonId = 1;
attribs.Split = StWinSlave_splitOff;
+ attribs.ToAlignEven = false;
myMonSlave.idMaster = 0;
myMonSlave.idSlave = 1; // second by default
@@ -340,6 +342,9 @@
case StWinAttr_SplitCfg:
anIter[1] = (StWinAttr )attribs.Split;
break;
+ case StWinAttr_ToAlignEven:
+ anIter[1] = (StWinAttr )attribs.ToAlignEven;
+ break;
default:
ST_DEBUG_LOG("UNKNOWN window attribute #" + anIter[0] + " requested");
break;
@@ -406,6 +411,9 @@
}
attribs.Split = (StWinSplit )anIter[1];
break;
+ case StWinAttr_ToAlignEven:
+ attribs.ToAlignEven = (anIter[1] == 1);
+ break;
default:
ST_DEBUG_LOG("UNKNOWN window attribute #" + anIter[0] + " requested");
break;
diff -Nru sview-13.10/StCore/StWindowImpl.h sview-14.01/StCore/StWindowImpl.h
--- sview-13.10/StCore/StWindowImpl.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StWindowImpl.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StCore library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -33,7 +33,12 @@
#include
#endif
-class NSOpenGLContext;
+#ifdef __OBJC__
+ @class NSOpenGLContext;
+#else
+ class NSOpenGLContext;
+#endif
+
class StGLContext;
class StThread;
@@ -79,6 +84,14 @@
ST_LOCAL bool isParentOnScreen() const;
+ public: //! @name clipboard
+
+ ST_LOCAL bool toClipboard(const StString& theText);
+
+#if defined(__linux__)
+ StString myTextToCopy;
+#endif
+
public: //! @name additional
ST_LOCAL void updateChildRect();
@@ -262,6 +275,7 @@
StSlaveWindowCfg_t myMonSlave; //!< slave window options
size_t mySyncCounter;
int myWinOnMonitorId; //!< monitor id where window is placed
+ int myWinMonScaleId; //!< monitor id from which scale factor is applied
TiledCfg myTiledCfg; //!< tiles configuration (multiple viewports within the same window)
#ifdef _WIN32
@@ -289,7 +303,7 @@
/**
* Window attributes structure for internal use.
- * Notice that some options couln't be changed after window was created!
+ * Notice that some options could not be changed after window was created!
*/
struct {
bool IsNoDecor; //!< to decorate master window or not (will be ignored in case of embedded and fullscreen)
@@ -308,6 +322,7 @@
StWinSlave Slave; //!< slave configuration
int8_t SlaveMonId; //!< on which monitor show slave window (1 by default)
StWinSplit Split; //!< split window configuration
+ bool ToAlignEven; //!< align window position to even numbers
} attribs;
struct {
diff -Nru sview-13.10/StCore/StWindowImplLin.cpp sview-14.01/StCore/StWindowImplLin.cpp
--- sview-13.10/StCore/StWindowImplLin.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StWindowImplLin.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -795,6 +795,42 @@
parseXDNDSelectionMsg();
break;
}
+ case SelectionRequest: {
+ const XSelectionRequestEvent& aRequest = myXEvent.xselectionrequest;
+ if(aRequest.selection != aDisplay->XA_CLIPBOARD) {
+ break;
+ }
+
+ XSelectionEvent aReply;
+ stMemZero(&aReply, sizeof(aReply));
+ aReply.type = SelectionNotify;
+ aReply.serial = myXEvent.xany.send_event;
+ aReply.display = aRequest.display;
+ aReply.requestor = aRequest.requestor;
+ aReply.selection = aRequest.selection;
+ aReply.property = aRequest.property;
+ aReply.target = None;
+ aReply.time = aRequest.time;
+ if(aRequest.target == aDisplay->XA_TARGETS) {
+ //ST_DEBUG_LOG("SelectionRequest(XA_TARGETS)");
+ Atom aTargets[] = { XA_STRING, aDisplay->XA_UTF8_STRING, aDisplay->XA_COMPOUND_TEXT };
+ XChangeProperty(aDisplay->hDisplay, aRequest.requestor, aRequest.property,
+ XA_ATOM, 32, PropModeReplace, (unsigned char* )aTargets, 3);
+
+ } else if(aRequest.target == XA_STRING
+ || aRequest.target == aDisplay->XA_UTF8_STRING
+ || aRequest.target == aDisplay->XA_COMPOUND_TEXT) {
+ //ST_DEBUG_LOG("SelectionRequest(XA_STRING)= " + myTextToCopy);
+ XChangeProperty(aDisplay->hDisplay, aRequest.requestor, aRequest.property,
+ aRequest.target, 8, PropModeReplace, (unsigned char* )myTextToCopy.toCString(), myTextToCopy.getSize());
+ } else {
+ aReply.property = None;
+ }
+
+ XSendEvent(aDisplay->hDisplay, aRequest.requestor, False, NoEventMask, (XEvent* )&aReply);
+ XFlush(aDisplay->hDisplay);
+ break;
+ }
case DestroyNotify: {
// something else...
break;
@@ -955,4 +991,19 @@
swapEventsBuffers();
}
+bool StWindowImpl::toClipboard(const StString& theText) {
+ const StXDisplayH& aDisplay = myMaster.stXDisplay;
+ if(aDisplay.isNull() || myMaster.hWindowGl == 0) {
+ // window is closed!
+ return false;
+ }
+
+ myTextToCopy = theText;
+
+ // setup owner of the XA_CLIPBOARD atom
+ XSetSelectionOwner(aDisplay->hDisplay, aDisplay->XA_CLIPBOARD,
+ myMaster.hWindowGl, CurrentTime);
+ return true;
+}
+
#endif
diff -Nru sview-13.10/StCore/StWindowImplMac.mm sview-14.01/StCore/StWindowImplMac.mm
--- sview-13.10/StCore/StWindowImplMac.mm 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StWindowImplMac.mm 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2011-2013 Kirill Gavrilov
+ * Copyright © 2011-2014 Kirill Gavrilov
*
* StCore library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -514,4 +514,13 @@
swapEventsBuffers();
}
+bool StWindowImpl::toClipboard(const StString& theText) {
+ StCocoaLocalPool aLocalPool;
+ NSPasteboard* aPasteBoard = [NSPasteboard generalPasteboard];
+ [aPasteBoard clearContents];
+ StCocoaString aStringMy(theText);
+ NSArray* anObjects = [NSArray arrayWithObject: aStringMy.toStringNs()];
+ return [aPasteBoard writeObjects: anObjects] == YES;
+}
+
#endif // __APPLE__
diff -Nru sview-13.10/StCore/StWindowImplWin.cpp sview-14.01/StCore/StWindowImplWin.cpp
--- sview-13.10/StCore/StWindowImplWin.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StWindowImplWin.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StCore library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -138,7 +138,10 @@
myIsUpdated = true;
}
- // use WS_EX_NOPARENTNOTIFY style to prevent to send notify on destroing our child window (NPAPI plugin -> deadlock)
+ myWinOnMonitorId = myMonitors[myRectNorm.center()].getId();
+ myWinMonScaleId = myWinOnMonitorId;
+
+ // use WS_EX_NOPARENTNOTIFY style to prevent to send notify on destroying our child window (NPAPI plugin -> deadlock)
DWORD masterWindowGl_dwExStyle = (myParentWin == NULL) ? WS_EX_NOACTIVATE : (WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY);
myMaster.hWindowGl = CreateWindowExW(masterWindowGl_dwExStyle,
myMaster.ClassGL.toCString(),
@@ -375,6 +378,16 @@
}
}
+/**
+ * @return normalized delta (-1 or 0 or +1)
+ */
+inline int getDirNorm(const int theFrom,
+ const int theTo) {
+ return theFrom > theTo
+ ? -1
+ : (theFrom < theTo ? 1 : 0);
+}
+
LRESULT StWindowImpl::stWndProc(HWND theWin, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch(uMsg) { // Check For Windows Messages
case WM_ACTIVATE: { // Watch For Window Activate Message
@@ -478,10 +491,67 @@
break;
} else if(theWin == myMaster.hWindow) {
RECT* aRect = (RECT* )(LPARAM )lParam;
+ const StRectI_t aPrevRect = myRectNorm;
myRectNorm.left() = aRect->left + GetSystemMetrics(SM_CXSIZEFRAME);
myRectNorm.right() = aRect->right - GetSystemMetrics(SM_CXSIZEFRAME);
myRectNorm.top() = aRect->top + GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYCAPTION);
myRectNorm.bottom() = aRect->bottom - GetSystemMetrics(SM_CYSIZEFRAME);
+ if(attribs.ToAlignEven)
+ {
+ // adjust window position to ensure alignment
+ const int aDL = getDirNorm(aPrevRect.left(), myRectNorm.left());
+ const int aDR = getDirNorm(aPrevRect.right(), myRectNorm.right());
+ const int aDT = getDirNorm(aPrevRect.top(), myRectNorm.top());
+ const int aDB = getDirNorm(aPrevRect.bottom(), myRectNorm.bottom());
+ if(isOddNumber(myRectNorm.left())) {
+ myRectNorm.left() += aDL;
+ aRect->left += aDL;
+ }
+ if(isEvenNumber(myRectNorm.right())) {
+ myRectNorm.right() += aDR;
+ aRect->right += aDR;
+ }
+ if(isOddNumber(myRectNorm.top())) {
+ myRectNorm.top() += aDT;
+ aRect->top += aDT;
+ }
+ if(isEvenNumber(myRectNorm.bottom())) {
+ aRect->bottom += aDB;
+ myRectNorm.bottom() += aDB;
+ }
+ }
+
+ // determine monitor scale factor change
+ const StMonitor& aMonTo = myMonitors[myRectNorm.center()];
+ const int aNewMonId = aMonTo.getId();
+ if(myWinMonScaleId != aNewMonId) {
+ const StMonitor& aMonFrom = myMonitors[myWinMonScaleId];
+ if(!stAreEqual(aMonTo.getScale(), aMonFrom.getScale(), 0.1f)) {
+ StRectI_t aRectScaled = myRectNorm;
+ const double aCoeff = double(aMonTo.getScale()) / double(aMonFrom.getScale());
+ const int aWidth = int(double(myRectNorm.width()) * aCoeff);
+ const int aHeight = int(double(myRectNorm.height()) * aCoeff);
+ aRectScaled.right() = aRectScaled.left() + aWidth;
+ aRectScaled.bottom() = aRectScaled.top() + aHeight;
+ const StMonitor& aMonMon = myMonitors[aRectScaled.center()];
+ if(aMonMon.getId() == aNewMonId) {
+ // process only if resized window is still on the same monitor (protect against cascade scaling)
+ myRectNorm = aRectScaled;
+ aRect->top = myRectNorm.top();
+ aRect->bottom = myRectNorm.bottom();
+ aRect->left = myRectNorm.left();
+ aRect->right = myRectNorm.right();
+ // take into account decorations
+ const DWORD aWinStyle = (!attribs.IsNoDecor ? WS_OVERLAPPEDWINDOW : WS_POPUP) | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
+ const DWORD aWinStyleEx = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE | WS_EX_ACCEPTFILES;
+ AdjustWindowRectEx(aRect, aWinStyle, FALSE, aWinStyleEx);
+ myWinMonScaleId = aNewMonId;
+ }
+ } else {
+ myWinMonScaleId = aNewMonId;
+ }
+ }
+
myIsUpdated = true;
myStEvent.Type = stEvent_Size;
@@ -800,9 +870,10 @@
// detect when window moved to another monitor
if(!attribs.IsFullScreen && myMonitors.size() > 1) {
- int aNewMonId = myMonitors[myRectNorm.center()].getId();
+ const StMonitor& aMonTo = myMonitors[myRectNorm.center()];
+ const int aNewMonId = aMonTo.getId();
if(myWinOnMonitorId != aNewMonId) {
- myStEventAux.Type = stEvent_NewMonitor;
+ myStEventAux.Type = stEvent_NewMonitor;
myStEventAux.Size.Time = getEventTime();
myStEventAux.Size.SizeX = myRectNorm.width();
myStEventAux.Size.SizeY = myRectNorm.height();
@@ -863,4 +934,26 @@
swapEventsBuffers();
}
+bool StWindowImpl::toClipboard(const StString& theText) {
+ const StStringUtfWide aWideText = theText.toUtfWide();
+ HGLOBAL aMem = GlobalAlloc(GMEM_MOVEABLE, aWideText.Size + sizeof(wchar_t));
+ if(aMem == NULL) {
+ return false;
+ }
+
+ stMemCpy(GlobalLock(aMem), aWideText.String, aWideText.Size + sizeof(wchar_t));
+ GlobalUnlock(aMem);
+ if(!OpenClipboard(NULL)) {
+ return false;
+ }
+
+ EmptyClipboard();
+ if(!SetClipboardData(CF_UNICODETEXT, aMem)) {
+ CloseClipboard();
+ return false;
+ }
+ CloseClipboard();
+ return true;
+}
+
#endif
diff -Nru sview-13.10/StCore/StXDisplay.cpp sview-14.01/StCore/StXDisplay.cpp
--- sview-13.10/StCore/StXDisplay.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StXDisplay.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StCore library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -41,7 +41,10 @@
xDNDAware(None),
xDNDPlainText(None),
xDNDPrimary(None),
- XA_TARGETS(None) {
+ XA_TARGETS(None),
+ XA_COMPOUND_TEXT(None),
+ XA_UTF8_STRING(None),
+ XA_CLIPBOARD(None) {
stMemZero(&FBCfg, sizeof(GLXFBConfig)); // should be just a pointer
open();
}
@@ -119,12 +122,15 @@
xDNDSelection = XInternAtom(hDisplay, "XdndSelection", False);
xDNDProxy = XInternAtom(hDisplay, "XdndProxy", False);
xDNDAware = XInternAtom(hDisplay, "XdndAware", False);
- xDNDPlainText = XInternAtom(hDisplay, "text/plain", False); //"UTF8_STRING", "COMPOUND_TEXT"
+ xDNDPlainText = XInternAtom(hDisplay, "text/plain", False);
xDNDPrimary = XInternAtom(hDisplay, "PRIMARY", False);
// This is a meta-format for data to be "pasted" in to.
// Requesting this format acquires a list of possible
// formats from the application which copied the data.
- XA_TARGETS = XInternAtom(hDisplay, "TARGETS", False);
+ XA_TARGETS = XInternAtom(hDisplay, "TARGETS", True);
+ XA_COMPOUND_TEXT = XInternAtom(hDisplay, "COMPOUND_TEXT", True);
+ XA_UTF8_STRING = XInternAtom(hDisplay, "UTF8_STRING", True);
+ XA_CLIPBOARD = XInternAtom(hDisplay, "CLIPBOARD", True);
}
diff -Nru sview-13.10/StCore/StXDisplay.h sview-14.01/StCore/StXDisplay.h
--- sview-13.10/StCore/StXDisplay.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StCore/StXDisplay.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StCore library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -42,28 +42,32 @@
Display* hDisplay; // connection to the X-server
XVisualInfo* hVisInfo; // visual info
- GLXFBConfig FBCfg;
+ GLXFBConfig FBCfg;
- XIM hInputMethod;
- XIC hInputCtx;
+ XIM hInputMethod;
+ XIC hInputCtx;
- Atom wndProtocols;
- Atom wndDestroyAtom; // Atom for close message
+ Atom wndProtocols;
+ Atom wndDestroyAtom; // Atom for close message
- Atom xDNDEnter; // Atoms for X drag&drop protocol
- Atom xDNDPosition;
- Atom xDNDStatus;
- Atom xDNDTypeList;
- Atom xDNDActionCopy;
+ Atom xDNDEnter; // Atoms for X drag&drop protocol
+ Atom xDNDPosition;
+ Atom xDNDStatus;
+ Atom xDNDTypeList;
+ Atom xDNDActionCopy;
Atom xDNDDrop;
- Atom xDNDLeave;
- Atom xDNDFinished;
- Atom xDNDSelection;
- Atom xDNDProxy;
- Atom xDNDAware;
- Atom xDNDPlainText;
- Atom xDNDPrimary;
- Atom XA_TARGETS;
+ Atom xDNDLeave;
+ Atom xDNDFinished;
+ Atom xDNDSelection;
+ Atom xDNDProxy;
+ Atom xDNDAware;
+ Atom xDNDPlainText;
+ Atom xDNDPrimary;
+
+ Atom XA_TARGETS;
+ Atom XA_COMPOUND_TEXT;
+ Atom XA_UTF8_STRING;
+ Atom XA_CLIPBOARD;
private:
diff -Nru sview-13.10/StDiagnostics/StDiagnostics.cbp sview-14.01/StDiagnostics/StDiagnostics.cbp
--- sview-13.10/StDiagnostics/StDiagnostics.cbp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StDiagnostics/StDiagnostics.cbp 2014-01-30 10:45:03.000000000 +0000
@@ -33,12 +33,7 @@
-
-
-
-
-
-
+
@@ -69,12 +64,7 @@
-
-
-
-
-
-
+
@@ -111,12 +101,7 @@
-
-
-
-
-
-
+
@@ -148,12 +133,7 @@
-
-
-
-
-
-
+
@@ -181,12 +161,7 @@
-
-
-
-
-
-
+
@@ -213,12 +188,7 @@
-
-
-
-
-
-
+
@@ -240,12 +210,7 @@
-
-
-
-
-
-
+
@@ -269,12 +234,7 @@
-
-
-
-
-
-
+
@@ -329,6 +289,9 @@
+
+
+
diff -Nru sview-13.10/StDiagnostics/StDiagnostics.cpp sview-14.01/StDiagnostics/StDiagnostics.cpp
--- sview-13.10/StDiagnostics/StDiagnostics.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StDiagnostics/StDiagnostics.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -35,8 +35,7 @@
StDiagnostics::StDiagnostics(const StNativeWin_t theParentWin,
const StHandle& theOpenInfo)
-: StApplication(theParentWin, theOpenInfo),
- myToQuit(false) {
+: StApplication(theParentWin, theOpenInfo) {
myTitle = "sView - Stereoscopic Device Diagnostics";
params.IsFullscreen = new StBoolParam(false);
params.IsFullscreen->signals.onChanged.connect(this, &StDiagnostics::doFullscreen);
diff -Nru sview-13.10/StDiagnostics/StDiagnostics.h sview-14.01/StDiagnostics/StDiagnostics.h
--- sview-13.10/StDiagnostics/StDiagnostics.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StDiagnostics/StDiagnostics.h 2014-01-30 10:45:03.000000000 +0000
@@ -79,7 +79,6 @@
StHandle myContext;
StHandle mySettings; //!< settings manager for Diagnostics plugin
StHandle myGUI; //!< GUI root widget
- bool myToQuit;
};
diff -Nru sview-13.10/StDiagnostics/StDiagnostics.rc sview-14.01/StDiagnostics/StDiagnostics.rc
--- sview-13.10/StDiagnostics/StDiagnostics.rc 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StDiagnostics/StDiagnostics.rc 2014-01-30 10:45:03.000000000 +0000
@@ -15,7 +15,7 @@
BEGIN
VALUE "FileDescription", "Stereoscopic Device Diagnostics\000"
VALUE "FileVersion", SVIEW_SDK_VER_STRING "\000"
- VALUE "LegalCopyright", "\251 2010-2013 Kirill Gavrilov\000"
+ VALUE "LegalCopyright", "\251 2010-2014 Kirill Gavrilov\000"
VALUE "ProductName", "StDiagnostics\000"
VALUE "ProductVersion", SVIEW_SDK_VER_STRING "\000"
VALUE "OfficialSite", "www.sview.ru\000"
diff -Nru sview-13.10/StDiagnostics/lang/german/StDiagnostics.lng sview-14.01/StDiagnostics/lang/german/StDiagnostics.lng
--- sview-13.10/StDiagnostics/lang/german/StDiagnostics.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StDiagnostics/lang/german/StDiagnostics.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1,4 @@
+German translation file for StDiagnostics plugin
+@author Kirill Gavrilov
+
+--------
diff -Nru sview-13.10/StDiagnostics/lang/korean/StDiagnostics.lng sview-14.01/StDiagnostics/lang/korean/StDiagnostics.lng
--- sview-13.10/StDiagnostics/lang/korean/StDiagnostics.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StDiagnostics/lang/korean/StDiagnostics.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1,4 @@
+English translation file for StDiagnostics plugin
+@author Kirill Gavrilov
+
+--------
diff -Nru sview-13.10/StGLWidgets/StGLMenuItem.cpp sview-14.01/StGLWidgets/StGLMenuItem.cpp
--- sview-13.10/StGLWidgets/StGLMenuItem.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLMenuItem.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* Distributed under the Boost Software License, Version 1.0.
* See accompanying file license-boost.txt or copy at
@@ -98,35 +98,6 @@
myToHilightText = true;
}
-const int StGLMenuItem::computeTextWidth() {
- StHandle& aFont = myFont->getFont();
- if(aFont.isNull() || !aFont->isValid()) {
- return myRoot->scale(int(10 * (myText.getLength() + 2)));
- }
-
- GLfloat aWidth = 0.0f;
- GLfloat aWidthMax = 0.0f;
- for(StUtf8Iter anIter = myText.iterator(); *anIter != 0;) {
- const stUtf32_t aCharThis = *anIter;
- const stUtf32_t aCharNext = *++anIter;
-
- if(aCharThis == '\x0D') {
- continue; // ignore CR
- } else if(aCharThis == '\x0A') {
- aWidthMax = stMax(aWidthMax, aWidth);
- aWidth = 0.0f;
- continue; // will be processed on second pass
- } else if(aCharThis == ' ') {
- aWidth += aFont->getAdvanceX(aCharThis, aCharNext);
- continue;
- }
-
- aWidth += aFont->getAdvanceX(aCharThis, aCharNext);
- }
- aWidthMax = stMax(aWidthMax, aWidth);
- return int(aWidthMax + 0.5f);
-}
-
void StGLMenuItem::stglResize() {
StGLContext& aCtx = getContext();
diff -Nru sview-13.10/StGLWidgets/StGLMessageBox.cpp sview-14.01/StGLWidgets/StGLMessageBox.cpp
--- sview-13.10/StGLWidgets/StGLMessageBox.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLMessageBox.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+namespace {
+ static const int OFFSET_PIXELS = 32;
+};
+
StGLMessageBox::StGLMessageBox(StGLWidget* theParent,
+ const StString& theTitle,
const StString& theText,
const int theWidth,
const int theHeight)
: StGLWidget(theParent, 0, 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_CENTER), theWidth, theHeight),
myContent(NULL),
+ myTitle(NULL),
myBtnPanel(NULL),
myDefaultBtn(NULL),
- myButtonsNb(0) {
- create(theText, theWidth, theHeight);
+ myButtonsNb(0),
+ myMarginLeft(0),
+ myMarginRight(0),
+ myMarginTop(0),
+ myMarginBottom(0),
+ myMinSizeY(0),
+ myToAdjustY(true) {
+ create(theTitle, theText, theWidth, theHeight);
}
StGLMessageBox::StGLMessageBox(StGLWidget* theParent,
+ const StString& theTitle,
const StString& theText)
: StGLWidget(theParent, 0, 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_CENTER),
theParent->getRoot()->scale(384),
theParent->getRoot()->scale(200)),
myContent(NULL),
+ myTitle(NULL),
myBtnPanel(NULL),
myDefaultBtn(NULL),
- myButtonsNb(0) {
- create(theText, myRoot->scale(384), myRoot->scale(200));
+ myButtonsNb(0),
+ myMarginLeft(0),
+ myMarginRight(0),
+ myMarginTop(0),
+ myMarginBottom(0),
+ myMinSizeY(0),
+ myToAdjustY(true) {
+ create(theTitle, theText, myRoot->scale(384), myRoot->scale(200));
}
-void StGLMessageBox::create(const StString& theText,
+void StGLMessageBox::create(const StString& theTitle,
+ const StString& theText,
const int theWidth,
const int theHeight) {
StGLWidget::signals.onMouseUnclick.connect(this, &StGLMessageBox::doMouseUnclick);
- const int OFFSET_PIXELS = myRoot->scale(32);
- int anOffsetX = theWidth > 2 * OFFSET_PIXELS ? OFFSET_PIXELS : 0;
- int anOffsetY = theHeight > 2 * OFFSET_PIXELS ? OFFSET_PIXELS : 0;
- myContent = new StGLScrollArea(this, anOffsetX, anOffsetY,
+ myMarginLeft = myRoot->scale(OFFSET_PIXELS);
+ myMarginRight = myRoot->scale(OFFSET_PIXELS);
+ myMarginTop = myRoot->scale(OFFSET_PIXELS);
+ myMarginBottom = myRoot->scale(24 * 3);
+ myMinSizeY = myRoot->scale(200);
+
+ int aTitleHeight = 0;
+ if(!theTitle.isEmpty()) {
+ myTitle = new StGLTextArea(this, 0, myMarginTop,
+ StGLCorner(ST_VCORNER_TOP, ST_HCORNER_CENTER),
+ theWidth - myMarginLeft - myMarginRight, theHeight - myMarginTop - myMarginBottom);
+ myTitle->setupAlignment(StGLTextFormatter::ST_ALIGN_X_CENTER,
+ StGLTextFormatter::ST_ALIGN_Y_TOP);
+ myTitle->setupStyle(StFTFont::Style_Bold);
+ myTitle->setText(theTitle);
+ myTitle->setTextColor(StGLVec3(1.0f, 1.0f, 1.0f));
+ myTitle->setVisibility(true, true);
+ int aWidth = 0;
+ myTitle->computeTextWidth(GLfloat(myTitle->getRectPx().width()), aWidth, aTitleHeight);
+ myTitle->changeRectPx().bottom() = myTitle->getRectPx().top() + aTitleHeight;
+ //myTitle->stglInitAutoHeight();
+ }
+
+ const int aTitleOffset = aTitleHeight > 0 ? (aTitleHeight + myRoot->scale(24)) : 0;
+ myMarginTop += aTitleOffset;
+ myContent = new StGLScrollArea(this, myMarginLeft, myMarginTop,
StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT),
- theWidth - 2 * anOffsetX, theHeight - myRoot->scale(24 * 3) - anOffsetY);
+ theWidth - myMarginLeft - myMarginRight, theHeight - myMarginTop - myMarginBottom);
setText(theText);
myIsTopWidget = true;
@@ -66,6 +109,12 @@
myProgram.release(aCtx);
}
+void StGLMessageBox::setTitle(const StString& theTitle) {
+ if(myTitle != NULL) {
+ myTitle->setText(theTitle);
+ }
+}
+
void StGLMessageBox::setText(const StString& theText) {
myContent->destroyChildren();
if(theText.isEmpty()) {
@@ -199,6 +248,18 @@
}
void StGLMessageBox::stglResize() {
+ if(myContent != NULL) {
+ const StGLWidget* aContent = myContent->getChildren()->getStart();
+ if(aContent != NULL
+ && myToAdjustY) {
+ // adjust message box to fit content
+ const int aSizeYToFit = aContent->getRectPx().height() + myMarginTop + myMarginBottom;
+ const int aNewSizeY = stMax(myMinSizeY, stMin(aSizeYToFit, myParent->getRectPx().height() - myRoot->scale(120)));
+ changeRectPx().bottom() = aNewSizeY;
+ myContent->changeRectPx().bottom() = myContent->getRectPx().top() + aNewSizeY - myMarginTop - myMarginBottom;
+ }
+ }
+
StGLWidget::stglResize();
GLfloat toZScreen = -getCamera()->getZScreen();
@@ -226,7 +287,7 @@
aCtx.core20fwd->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
aCtx.core20fwd->glEnable(GL_BLEND);
- myProgram.use(aCtx);
+ myProgram.use(aCtx, getRoot()->getScreenDispX());
myProgram.setProjMat(aCtx, getCamera()->getProjMatrix());
myProgram.setColor(aCtx, StGLVec4(0.06f, 0.06f, 0.06f, 1.0f), GLfloat(opacityValue) * 0.8f);
diff -Nru sview-13.10/StGLWidgets/StGLMsgStack.cpp sview-14.01/StGLWidgets/StGLMsgStack.cpp
--- sview-13.10/StGLWidgets/StGLMsgStack.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLMsgStack.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -32,7 +32,7 @@
// check messages stack
while(myMsgQueue->pop(myMsgTmp)) {
- StGLMessageBox* aMsgBox = new StGLMessageBox(this, *myMsgTmp.Text);
+ StGLMessageBox* aMsgBox = new StGLMessageBox(this, "", *myMsgTmp.Text);
aMsgBox->addButton("Close");
aMsgBox->setVisibility(true, true);
aMsgBox->stglInit();
diff -Nru sview-13.10/StGLWidgets/StGLRootWidget.cpp sview-14.01/StGLWidgets/StGLRootWidget.cpp
--- sview-13.10/StGLWidgets/StGLRootWidget.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLRootWidget.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -42,6 +42,7 @@
myShareSize(10),
myScrDispX(0.0f),
myLensDist(0.0f),
+ myScrDispXPx(0),
myScaleGlX(1.0),
myScaleGlY(1.0),
myScaleGUI(1.0f),
@@ -64,6 +65,7 @@
for(size_t aResId = 0; aResId < myShareSize; ++aResId) {
myShareArray[aResId] = new StGLSharePointer();
}
+ myGlFontMgr = new StGLFontManager(myResolution);
}
StGLRootWidget::~StGLRootWidget() {
@@ -75,13 +77,17 @@
delete myShareArray[aResId];
}
delete[] myShareArray;
+ if(!myGlCtx.isNull()) {
+ myGlFontMgr->release(*myGlCtx);
+ myGlFontMgr.nullify();
+ }
}
StGLContext& StGLRootWidget::getContext() {
return *myGlCtx;
}
-const StHandle& StGLRootWidget::getContextHandle() {
+const StHandle& StGLRootWidget::getContextHandle() const {
return myGlCtx;
}
@@ -142,6 +148,7 @@
}
myScaleGUI = aScale;
myResolution = (unsigned int )(72.0f * aScale + 0.1f);
+ myGlFontMgr->setResolution(myResolution);
}
bool StGLRootWidget::stglInit() {
@@ -160,14 +167,17 @@
switch(theView) {
case ST_DRAW_LEFT:
- myScrDispX = myLensDist * GLfloat(0.5 * myRectGl.width());
+ myScrDispX = myLensDist * GLfloat(0.5 * myRectGl.width());
+ myScrDispXPx = int(double(myLensDist) * 0.5 * double(rectPx.width()));
break;
case ST_DRAW_RIGHT:
- myScrDispX = -myLensDist * GLfloat(0.5 * myRectGl.width());
+ myScrDispX = -myLensDist * GLfloat(0.5 * myRectGl.width());
+ myScrDispXPx = -int(double(myLensDist) * 0.5 * double(rectPx.width()));
break;
case ST_DRAW_MONO:
default:
- myScrDispX = 0.0f;
+ myScrDispX = 0.0f;
+ myScrDispXPx = 0;
break;
}
@@ -214,7 +224,7 @@
const GLdouble aWidthFactor = GLdouble(aVPortWidth) / GLdouble(aRootWidth);
const GLdouble aHeightFactor = GLdouble(aVPortHeight) / GLdouble(aRootHeight);
- theScissorRect.x() = myViewport[0] + GLint(aWidthFactor * GLdouble(theRect.left()));
+ theScissorRect.x() = myViewport[0] + GLint(aWidthFactor * GLdouble(theRect.left())) + myScrDispXPx;
theScissorRect.y() = myViewport[1] + GLint(aHeightFactor * GLdouble(aRootHeight - theRect.bottom()));
theScissorRect.width() = GLint(aWidthFactor * GLdouble(theRect.width()));
diff -Nru sview-13.10/StGLWidgets/StGLScrollArea.cpp sview-14.01/StGLWidgets/StGLScrollArea.cpp
--- sview-13.10/StGLWidgets/StGLScrollArea.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLScrollArea.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -44,6 +44,16 @@
}
void StGLScrollArea::stglResize() {
+ StGLWidget* aContent = myChildren.getStart();
+ if(!isScrollable()
+ && aContent != NULL
+ && aContent->getRectPx().top() < 0
+ && aContent->getCorner().v == ST_VCORNER_TOP) {
+ const int aDelta = -aContent->getRectPx().top();
+ aContent->changeRectPx().top() += aDelta;
+ aContent->changeRectPx().bottom() += aDelta;
+ }
+
StGLWidget::stglResize();
}
diff -Nru sview-13.10/StGLWidgets/StGLSubtitles.cpp sview-14.01/StGLWidgets/StGLSubtitles.cpp
--- sview-13.10/StGLWidgets/StGLSubtitles.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLSubtitles.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2010-2013 Kirill Gavrilov
+ * Copyright © 2010-2014 Kirill Gavrilov
*
* Distributed under the Boost Software License, Version 1.0.
* See accompanying file license-boost.txt or copy at
@@ -7,11 +7,83 @@
*/
#include
+
+#include
+#include
#include
namespace {
static const StString CLASS_NAME("StGLSubtitles");
- static const size_t SHARE_SUBS_FONT_ID = StGLRootWidget::generateShareId();
+ static const size_t SHARE_IMAGE_PROGRAM_ID = StGLRootWidget::generateShareId();
+};
+
+class StGLSubtitles::StImgProgram : public StGLProgram {
+
+ public:
+
+ StImgProgram() : StGLProgram("StGLSubtitles") {}
+
+ StGLVarLocation getVVertexLoc() const { return StGLVarLocation(0); }
+ StGLVarLocation getVTexCoordLoc() const { return StGLVarLocation(1); }
+
+ void setProjMat(StGLContext& theCtx,
+ const StGLMatrix& theProjMat) {
+ theCtx.core20fwd->glUniformMatrix4fv(uniProjMatLoc, 1, GL_FALSE, theProjMat);
+ }
+
+ virtual bool init(StGLContext& theCtx) {
+ const char VERTEX_SHADER[] =
+ "uniform mat4 uProjMat;\n"
+ "uniform vec4 uDisp;\n"
+ "attribute vec4 vVertex;\n"
+ "attribute vec2 vTexCoord;\n"
+ "varying vec2 fTexCoord;\n"
+ "void main(void) {\n"
+ " fTexCoord = vTexCoord;\n"
+ " gl_Position = uProjMat * (vVertex + uDisp);\n"
+ "}\n";
+
+ const char FRAGMENT_SHADER[] =
+ "uniform sampler2D uTexture;\n"
+ "varying vec2 fTexCoord;\n"
+ "void main(void) {\n"
+ " gl_FragColor = texture2D(uTexture, fTexCoord);\n"
+ "}\n";
+
+ StGLVertexShader aVertexShader(StGLProgram::getTitle());
+ aVertexShader.init(theCtx, VERTEX_SHADER);
+ StGLAutoRelease aTmp1(theCtx, aVertexShader);
+
+ StGLFragmentShader aFragmentShader(StGLProgram::getTitle());
+ aFragmentShader.init(theCtx, FRAGMENT_SHADER);
+ StGLAutoRelease aTmp2(theCtx, aFragmentShader);
+ if(!StGLProgram::create(theCtx)
+ .attachShader(theCtx, aVertexShader)
+ .attachShader(theCtx, aFragmentShader)
+ .bindAttribLocation(theCtx, "vVertex", getVVertexLoc())
+ .bindAttribLocation(theCtx, "vTexCoord", getVTexCoordLoc())
+ .link(theCtx)) {
+ return false;
+ }
+
+ StGLVarLocation uniTextureLoc = StGLProgram::getUniformLocation(theCtx, "uTexture");
+ if(uniTextureLoc.isValid()) {
+ StGLProgram::use(theCtx);
+ theCtx.core20fwd->glUniform1i(uniTextureLoc, StGLProgram::TEXTURE_SAMPLE_0);
+ StGLProgram::unuse(theCtx);
+ }
+
+ uniProjMatLoc = StGLProgram::getUniformLocation(theCtx, "uProjMat");
+ uniDispLoc = StGLProgram::getUniformLocation(theCtx, "uDisp");
+ return uniProjMatLoc.isValid()
+ && uniTextureLoc.isValid();
+ }
+
+ private:
+
+ StGLVarLocation uniProjMatLoc;
+ StGLVarLocation uniDispLoc;
+
};
StGLSubtitles::StSubShowItems::StSubShowItems()
@@ -24,33 +96,49 @@
for(size_t anId = size() - 1; anId < size_t(-1); --anId) {
// filter outdated and forward items
const StHandle& anItem = getValue(anId);
- if(anItem->myTimeEnd < thePTS || anItem->myTimeStart > thePTS) {
+ if(anItem->TimeEnd < thePTS || anItem->TimeStart > thePTS) {
remove(anId);
isChanged = true;
}
}
if(!isChanged) {
- return isChanged;
+ return false;
} else if(isEmpty()) {
- myText.clear();
- return isChanged;
+ Text.clear();
+ Image.nullify();
+ return true;
}
// update active text
- myText = getFirst()->myText;
+ Text = getFirst()->Text;
for(size_t anId = 1; anId < size(); ++anId) {
const StHandle& anItem = getValue(anId);
- myText += StString('\n');
- myText += anItem->myText;
+ Text += StString('\n');
+ Text += anItem->Text;
}
+
+ // update active image
+ const StImagePlane& anImage = getFirst()->Image;
+ if(!anImage.isNull()) {
+ Image.initCopy(anImage);
+ } else {
+ Image.nullify();
+ }
+
return isChanged;
}
void StGLSubtitles::StSubShowItems::add(const StHandle& theItem) {
- if(!myText.isEmpty()) {
- myText += StString('\n');
+ if(!Text.isEmpty()) {
+ Text += StString('\n');
}
- myText += theItem->myText;
+ Text += theItem->Text;
+
+ const StImagePlane& anImage = theItem->Image;
+ if(!anImage.isNull()) {
+ Image.initCopy(anImage);
+ }
+
StArrayList >::add(theItem);
}
@@ -61,18 +149,18 @@
StGLSubtitles::StGLSubtitles(StGLWidget* theParent,
const StHandle& theSubQueue,
const StHandle& theFontSize,
- const StHandle& theParallax)
+ const StHandle& theParallax,
+ const StHandle& theParser)
: StGLTextArea(theParent,
0, -theParent->getRoot()->scale(100),
StGLCorner(ST_VCORNER_BOTTOM, ST_HCORNER_CENTER),
- theParent->getRoot()->scale(800), theParent->getRoot()->scale(160),
- (FontSize )(int )theFontSize->getValue(),
- SHARE_SUBS_FONT_ID),
+ theParent->getRoot()->scale(800), theParent->getRoot()->scale(160)),
myFontSize(theFontSize),
myParallax(theParallax),
+ myParser(theParser),
myQueue(theSubQueue),
- myShowItems(),
- myPTS(0.0) {
+ myPTS(0.0),
+ myImgProgram(getRoot()->getShare(SHARE_IMAGE_PROGRAM_ID)) {
if(myQueue.isNull()) {
myQueue = new StSubQueue();
}
@@ -83,10 +171,56 @@
myFormatter.setupAlignment(StGLTextFormatter::ST_ALIGN_X_CENTER,
StGLTextFormatter::ST_ALIGN_Y_BOTTOM);
+
+ StHandle aFontNew = new StGLFont();
+ StHandle aLib = getRoot()->getFontManager()->getLibraty();
+ const FontSize aSize = (FontSize )(int )myFontSize->getValue();
+ const unsigned int aResolution = getRoot()->getFontManager()->getResolution();
+ for(size_t anIter = 0; anIter < StFTFont::SubsetsNB; ++anIter) {
+ StHandle& aFontGlSrc = myFont->changeFont((StFTFont::Subset )anIter);
+ if(aFontGlSrc.isNull()) {
+ continue;
+ }
+
+ StHandle aFontFt = new StFTFont(aLib);
+ for(int aStyleIt = 0; aStyleIt < StFTFont::StylesNB; ++aStyleIt) {
+ aFontFt->load(aFontGlSrc->getFont()->getFilePath((StFTFont::Style )aStyleIt), (StFTFont::Style )aStyleIt);
+ }
+ aFontFt->init(aSize, aResolution);
+ aFontNew->changeFont((StFTFont::Subset )anIter) = new StGLFontEntry(aFontFt);
+ }
+ mySize = aSize;
+ myFont = aFontNew;
}
StGLSubtitles::~StGLSubtitles() {
- //
+ StGLContext& aCtx = getContext();
+ myFont->release(aCtx);
+ myFont.nullify();
+ myTexture.release(aCtx);
+ myVertBuf.release(aCtx);
+ myTCrdBuf.release(aCtx);
+}
+
+bool StGLSubtitles::stglInit() {
+ if(!myVertBuf.isValid()) {
+ StArray aDummyVert(4);
+ StArray aTexCoords(4);
+ aTexCoords[0] = StGLVec2(1.0f, 0.0f);
+ aTexCoords[1] = StGLVec2(1.0f, 1.0f);
+ aTexCoords[2] = StGLVec2(0.0f, 0.0f);
+ aTexCoords[3] = StGLVec2(0.0f, 1.0f);
+
+ StGLContext& aCtx = getContext();
+ myVertBuf.init(aCtx, aDummyVert);
+ myTCrdBuf.init(aCtx, aTexCoords);
+
+ if(myImgProgram.isNull()) {
+ myImgProgram.create(getRoot()->getContextHandle(), new StImgProgram());
+ myImgProgram->init(aCtx);
+ }
+ }
+ return StGLTextArea::stglInit();
}
void StGLSubtitles::stglUpdate(const StPointD_t& ) {
@@ -96,8 +230,16 @@
myShowItems.add(aNewSubItem);
}
+ StGLContext& aCtx = getContext();
if(isChanged) {
- setText(myShowItems.myText);
+ setText(myShowItems.Text);
+
+ if(!myShowItems.Image.isNull()) {
+ myTexture.init(aCtx, myShowItems.Image);
+ } else {
+ myTexture.release(aCtx);
+ }
+
StString aLog;
/**for(size_t anId = 0; anId < myShowItems.size(); ++anId) {
aLog += ST_STRING(" from ") + myShowItems[anId]->myTimeStart + " to " + myShowItems[anId]->myTimeEnd + "\n";
@@ -108,31 +250,73 @@
const FontSize aNewSize = (FontSize )(int )myFontSize->getValue();
if(!myText.isEmpty()
&& aNewSize != mySize) {
- stglSetTextSize(aNewSize);
+ mySize = aNewSize;
+ myToRecompute = true;
+
+ myFont->stglInit(aCtx, getFontSize(), myRoot->getResolution());
}
}
void StGLSubtitles::stglDraw(unsigned int theView) {
- if(!myIsInitialized || !isVisible() || myText.isEmpty()) {
+ if(!myIsInitialized || !isVisible()) {
return;
}
StGLContext& aCtx = getContext();
- formatText(aCtx);
+ if(myFormatter.getParser() != (StGLTextFormatter::Parser )myParser->getValue()) {
+ myFormatter.setupParser((StGLTextFormatter::Parser )myParser->getValue());
+ myToRecompute = true;
+ }
+ if(!myText.isEmpty()) {
+ formatText(aCtx);
- switch(theView) {
- case ST_DRAW_LEFT:
- myTextDX = -myParallax->getValue() * GLfloat(0.5 * 0.001 * myRoot->getRootRectGl().width());
- break;
- case ST_DRAW_RIGHT:
- myTextDX = myParallax->getValue() * GLfloat(0.5 * 0.001 * myRoot->getRootRectGl().width());
- break;
- case ST_DRAW_MONO:
- default:
- myTextDX = 0.0f;
- break;
+ switch(theView) {
+ case ST_DRAW_LEFT:
+ myTextDX = -myParallax->getValue() * GLfloat(0.5 * 0.001 * myRoot->getRootRectGl().width());
+ break;
+ case ST_DRAW_RIGHT:
+ myTextDX = myParallax->getValue() * GLfloat(0.5 * 0.001 * myRoot->getRootRectGl().width());
+ break;
+ case ST_DRAW_MONO:
+ default:
+ myTextDX = 0.0f;
+ break;
+ }
+ StGLTextArea::stglDraw(theView);
}
- StGLTextArea::stglDraw(theView);
+
+ if(!myTexture.isValid()
+ || !myImgProgram->isValid()) {
+ return;
+ }
+
+ aCtx.core20fwd->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ aCtx.core20fwd->glEnable(GL_BLEND);
+ myTexture.bind(aCtx);
+
+ // update vertices
+ StRectI_t aRect = getRectPxAbsolute();
+ aRect.top() = aRect.bottom() - myTexture.getSizeY();
+ aRect.left() = aRect.left() + aRect.width() / 2 - myTexture.getSizeX() / 2;
+ aRect.right() = aRect.left() + myTexture.getSizeX();
+
+ StArray aVertices(4);
+ myRoot->getRectGl(aRect, aVertices);
+ myVertBuf.init(aCtx, aVertices);
+
+ myImgProgram->use(aCtx);
+
+ myVertBuf.bindVertexAttrib(aCtx, myImgProgram->getVVertexLoc());
+ myTCrdBuf.bindVertexAttrib(aCtx, myImgProgram->getVTexCoordLoc());
+
+ aCtx.core20fwd->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+ myTCrdBuf.unBindVertexAttrib(aCtx, myImgProgram->getVTexCoordLoc());
+ myVertBuf.unBindVertexAttrib(aCtx, myImgProgram->getVVertexLoc());
+
+ myImgProgram->unuse(aCtx);
+ myTexture.unbind(aCtx);
+ aCtx.core20fwd->glDisable(GL_BLEND);
}
void StGLSubtitles::stglResize() {
@@ -140,6 +324,14 @@
myTextWidth = (GLfloat )getRectPx().width();
myToRecompute = true;
StGLTextArea::stglResize();
+
+ // update projection matrix
+ if(!myImgProgram.isNull()) {
+ StGLContext& aCtx = getContext();
+ myImgProgram->use(aCtx);
+ myImgProgram->setProjMat(aCtx, getRoot()->getScreenProjection());
+ myImgProgram->unuse(aCtx);
+ }
}
const StHandle& StGLSubtitles::getQueue() const {
diff -Nru sview-13.10/StGLWidgets/StGLTable.cpp sview-14.01/StGLWidgets/StGLTable.cpp
--- sview-13.10/StGLWidgets/StGLTable.cpp 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLTable.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1,251 @@
+/**
+ * Copyright © 2014 Kirill Gavrilov
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * See accompanying file license-boost.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt
+ */
+
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include
+
+namespace {
+ static const StString CLASS_NAME("StGLTable");
+};
+
+StGLTableItem::StGLTableItem(StGLTable* theParent)
+: StGLWidget(theParent,
+ theParent->getMarginLeft(), theParent->getMarginTop(),
+ StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT),
+ theParent->getRoot()->scale(32),
+ theParent->getRoot()->scale(32)),
+ myColSpan(1),
+ myRowSpan(1) {
+ setVisibility(true, true);
+}
+
+StGLTableItem::~StGLTableItem() {
+ //
+}
+
+StGLTable::StGLTable(StGLWidget* theParent,
+ const int theLeft,
+ const int theTop,
+ StGLCorner theCorner)
+: StGLWidget(theParent,
+ theLeft, theTop,
+ theCorner,
+ theParent->getRoot()->scale(32),
+ theParent->getRoot()->scale(32)),
+ myMarginLeft (theParent->getRoot()->scale(5)),
+ myMarginRight (theParent->getRoot()->scale(5)),
+ myMarginTop (theParent->getRoot()->scale(2)),
+ myMarginBottom (theParent->getRoot()->scale(2)),
+ myIsInitialized(false) {
+ //
+}
+
+StGLTable::~StGLTable() {
+ //
+}
+
+const StString& StGLTable::getClassName() {
+ return CLASS_NAME;
+}
+
+void StGLTable::setupTable(const int theNbRows,
+ const int theNbColumns) {
+ // destroy old content
+ for(size_t aRowIter = 0; aRowIter < myTable.size(); ++aRowIter) {
+ StArrayList& aRow = myTable.changeValue(aRowIter);
+ for(size_t aColIter = 0; aColIter < aRow.size(); ++aColIter) {
+ StGLTableItem* anItem = aRow.changeValue(aColIter);
+ delete anItem;
+ }
+ }
+ myTable.clear();
+
+ // initialize new empty content
+ for(int aRowIter = 0; aRowIter < theNbRows; ++aRowIter) {
+ myTable.add(StArrayList());
+ StArrayList& aRow = myTable.changeLast();
+ aRow.initArray(theNbColumns);
+ for(size_t aColIter = 0; aColIter < aRow.size(); ++aColIter) {
+ aRow.changeValue(aColIter) = new StGLTableItem(this);
+ }
+ }
+ myRowBottoms.initArray(theNbRows);
+ myColRights .initArray(theNbColumns);
+ stMemZero(&myRowBottoms.changeFirst(), sizeof(int) * myRowBottoms.size());
+ stMemZero(&myColRights .changeFirst(), sizeof(int) * myColRights .size());
+}
+
+void StGLTable::fillFromMap(const StDictionary& theMap,
+ const StGLVec3& theTextColor,
+ const int theMaxWidth,
+ const int theCol1MaxWidth,
+ const int theRowId,
+ const int theColId) {
+ ST_ASSERT_SLIP(theRowId >= 0 && theColId >= 0,
+ "StGLTable::fillFromMap() out of range",
+ return);
+ const int aRowsNb = theRowId + (int )theMap.size();
+ const int aColsNb = theColId + 2;
+ if(aRowsNb > (int )myRowBottoms.size()
+ || aColsNb > (int )myColRights.size()) {
+ setupTable(aRowsNb, aColsNb);
+ }
+
+ // fill first column with keys
+ const int aCol1MaxWidth = theCol1MaxWidth - (myMarginLeft + myMarginRight);
+ int aCol1Width = 0;
+ for(size_t anIter = 0; anIter < theMap.size(); ++anIter) {
+ const StDictEntry& aPair = theMap.getValue(anIter);
+ StGLTableItem& anItem = changeElement(theRowId + (int )anIter, theColId);
+ anItem.setRowSpan(1);
+ anItem.setColSpan(1);
+
+ StGLTextArea* aText = new StGLTextArea(&anItem, 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT));
+ aText->setupAlignment(StGLTextFormatter::ST_ALIGN_X_RIGHT,
+ StGLTextFormatter::ST_ALIGN_Y_TOP);
+ aText->setText(aPair.getName().isEmpty() ? aPair.getKey() : aPair.getName());
+ aText->setTextColor(theTextColor);
+ aText->setupStyle(StFTFont::Style_Bold);
+ aText->setVisibility(true, true);
+ aText->stglInitAutoHeightWidth(aCol1MaxWidth);
+ aCol1Width = stMax(aCol1Width, aText->getRectPx().width());
+ }
+
+ // adjust width of all elements in first column
+ // (alternatively we might adjust right corner)
+ for(size_t anIter = 0; anIter < theMap.size(); ++anIter) {
+ StGLTableItem& anItem = changeElement(theRowId + (int )anIter, theColId);
+ anItem.getItem()->changeRectPx().right() = anItem.getItem()->getRectPx().left() + aCol1Width;
+ ((StGLTextArea* )anItem.getItem())->setTextWidth(aCol1Width);
+ }
+
+ // fill second column with values
+ int aCol2MaxWidth = theMaxWidth - aCol1Width - 2 * (myMarginLeft + myMarginRight);
+ for(size_t anIter = 0; anIter < theMap.size(); ++anIter) {
+ const StDictEntry& aPair = theMap.getValue(anIter);
+ StGLTableItem& anItem = changeElement(theRowId + (int )anIter, theColId + 1);
+ anItem.setRowSpan(1);
+ anItem.setColSpan(1);
+
+ StGLTextArea* aText = new StGLTextArea(&anItem, 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT));
+ aText->setupAlignment(StGLTextFormatter::ST_ALIGN_X_LEFT,
+ StGLTextFormatter::ST_ALIGN_Y_TOP);
+ aText->setText(aPair.getValue());
+ aText->setTextColor(theTextColor);
+ aText->setVisibility(true, true);
+ aText->stglInitAutoHeightWidth(aCol2MaxWidth);
+ }
+
+ updateLayout();
+}
+
+void StGLTable::stglResize() {
+ StGLWidget::stglResize();
+}
+
+bool StGLTable::stglInit() {
+ myIsInitialized = StGLWidget::stglInit();
+ if(!myIsInitialized) {
+ return false;
+ }
+
+ updateLayout();
+ return true;
+}
+
+void StGLTable::updateLayout() {
+ if(myRowBottoms.isEmpty()
+ || myColRights .isEmpty()) {
+ return;
+ }
+
+ // determine rows heights
+ int aBottomPrev = 0;
+ for(size_t aRowIter = 0; aRowIter < myRowBottoms.size(); ++aRowIter) {
+ StArrayList& aRow = myTable.changeValue(aRowIter);
+ for(size_t aColIter = 0; aColIter < myColRights.size(); ++aColIter) {
+ StGLTableItem* anItem = aRow.changeValue(aColIter);
+ if(anItem->getItem() == NULL) {
+ continue;
+ }
+
+ const int aBefore = aRowIter != 0
+ ? myRowBottoms.changeValue(aRowIter - 1)
+ : 0;
+ size_t aBotRowId = aRowIter + anItem->getRowSpan() - 1;
+ int& aBottom = myRowBottoms.changeValue(aBotRowId);
+ aBottom = stMax(aBottom,
+ aBefore + anItem->getItem()->getRectPx().height()
+ + myMarginTop + myMarginBottom);
+ }
+ int& aBottom = myRowBottoms.changeValue(aRowIter);
+ aBottom = stMax(aBottom, aBottomPrev);
+ aBottomPrev = aBottom;
+ }
+
+ // determine columns widths
+ int aRightPrev = 0;
+ for(size_t aColIter = 0; aColIter < myColRights.size(); ++aColIter) {
+ for(size_t aRowIter = 0; aRowIter < myRowBottoms.size(); ++aRowIter) {
+ StGLTableItem* anItem = myTable.changeValue(aRowIter).changeValue(aColIter);
+ if(anItem->getItem() == NULL) {
+ continue;
+ }
+
+ const int aBefore = aColIter != 0
+ ? myColRights.changeValue(aColIter - 1)
+ : 0;
+ size_t aRightColId = aColIter + anItem->getColSpan() - 1;
+ int& aRight = myColRights.changeValue(aRightColId);
+ aRight = stMax(aRight,
+ aBefore + anItem->getItem()->getRectPx().width()
+ + myMarginLeft + myMarginRight);
+ }
+ int& aRight = myColRights.changeValue(aColIter);
+ aRight = stMax(aRight, aRightPrev);
+ aRightPrev = aRight;
+ }
+ changeRectPx().right() = getRectPx().left() + myColRights.getLast();
+ changeRectPx().bottom() = getRectPx().top() + myRowBottoms.getLast();
+
+ // adjust table elements positions
+ int aTop = 0;
+ for(size_t aRowIter = 0; aRowIter < myRowBottoms.size(); aTop = myRowBottoms.getValue(aRowIter++)) {
+ StArrayList& aRow = myTable.changeValue(aRowIter);
+ int aLeft = 0;
+ for(size_t aColIter = 0; aColIter < myColRights.size(); aLeft = myColRights.getValue(aColIter++)) {
+ StGLTableItem* anItem = aRow.changeValue(aColIter);
+ const size_t aBotRowId = aRowIter + anItem->getRowSpan() - 1;
+ const size_t aRightColId = aColIter + anItem->getColSpan() - 1;
+ anItem->changeRectPx().top() = aTop + myMarginTop;
+ anItem->changeRectPx().left() = aLeft + myMarginLeft;
+ anItem->changeRectPx().bottom() = myRowBottoms.changeValue(aBotRowId) - myMarginBottom;
+ anItem->changeRectPx().right() = myColRights .changeValue(aRightColId) - myMarginRight;
+ }
+ }
+}
+
+void StGLTable::stglDraw(unsigned int theView) {
+ if(!myIsInitialized || !isVisible()) {
+ return;
+ }
+
+ if(isResized) {
+ stglResize();
+ isResized = false;
+ }
+
+ StGLWidget::stglDraw(theView);
+}
diff -Nru sview-13.10/StGLWidgets/StGLTextArea.cpp sview-14.01/StGLWidgets/StGLTextArea.cpp
--- sview-13.10/StGLWidgets/StGLTextArea.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLTextArea.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* Distributed under the Boost Software License, Version 1.0.
* See accompanying file license-boost.txt or copy at
@@ -206,87 +206,16 @@
static const StString CLASS_NAME("StGLTextArea");
static const size_t SHARE_TEXT_PROGRAM_ID = StGLRootWidget::generateShareId();
static const size_t SHARE_BORDER_PROGRAM_ID = StGLRootWidget::generateShareId();
- static const size_t SHARE_FONT_NORMAL_ID = StGLRootWidget::generateShareId();
- static const size_t SHARE_FONT_SMALLEST_ID = StGLRootWidget::generateShareId();
- static const size_t SHARE_FONT_SMALL_ID = StGLRootWidget::generateShareId();
- static const size_t SHARE_FONT_BIG_ID = StGLRootWidget::generateShareId();
- static const size_t SHARE_FONT_BIGGEST_ID = StGLRootWidget::generateShareId();
- static const size_t SHARE_FONT_DOUBLE_ID = StGLRootWidget::generateShareId();
-
- enum {
- ST_FONT_SERIF,
- ST_FONT_SANS,
- ST_FONT_MONO,
- };
-
- static StString getFont(const int theFontType) {
- #ifdef _WIN32
- switch(theFontType) {
- case ST_FONT_SERIF:
- return "times.ttf";
- case ST_FONT_SANS:
- return "micross.ttf";
- case ST_FONT_MONO:
- default:
- return "tahoma.ttf";
- }
- #elif defined(__APPLE__)
- switch(theFontType) {
- case ST_FONT_SERIF:
- return "Times.dfont";
- case ST_FONT_SANS:
- return "Trebuchet MS.ttf";
- //return "LucidaGrande.ttc";
- //return "Geneva.dfont";
- //return "HelveticaNeue.dfont";
- //return "Helvetica.dfont";
- case ST_FONT_MONO:
- default:
- return "Monaco.dfont";
- }
- #elif defined(__linux__)
- switch(theFontType) {
- case ST_FONT_SERIF:
- return "DejaVuSerif.ttf";
- case ST_FONT_SANS:
- return "DejaVuSans.ttf";
- case ST_FONT_MONO:
- default:
- return "DejaVuSansMono.ttf";
- }
- #else
- #error undefined fonts
- #endif
- }
-
- inline size_t getFontShareId(const StGLTextArea::FontSize theSize,
- const size_t theShareId) {
- if(theShareId != size_t(-1)) {
- return theShareId;
- }
-
- switch(theSize) {
- case StGLTextArea::SIZE_SMALLEST: return SHARE_FONT_SMALLEST_ID;
- case StGLTextArea::SIZE_SMALL: return SHARE_FONT_SMALL_ID;
- case StGLTextArea::SIZE_NORMAL: return SHARE_FONT_NORMAL_ID;
- case StGLTextArea::SIZE_BIGGEST: return SHARE_FONT_BIGGEST_ID;
- case StGLTextArea::SIZE_DOUBLE: return SHARE_FONT_DOUBLE_ID;
- case StGLTextArea::SIZE_BIG:
- default: return SHARE_FONT_BIG_ID;
- }
- }
};
StGLTextArea::StGLTextArea(StGLWidget* theParent,
const int theLeft, const int theTop,
const StGLCorner theCorner,
const int theWidth, const int theHeight,
- const FontSize theSize,
- const size_t theShareId)
+ const FontSize theSize)
: StGLWidget(theParent, theLeft, theTop, theCorner, theWidth, theHeight),
myTextProgram(getRoot()->getShare(SHARE_TEXT_PROGRAM_ID)),
myBorderProgram(getRoot()->getShare(SHARE_BORDER_PROGRAM_ID)),
- myFont(getRoot()->getShare(getFontShareId(theSize, theShareId))),
mySize(theSize),
myTextColor(0.0f, 0.0f, 0.0f, 1.0f),
myShadowColor(0.0f, 0.0f, 0.0f, 1.0f),
@@ -302,17 +231,7 @@
myToShowBorder(false),
myToDrawShadow(false),
myIsInitialized(false) {
- // initialize FreeType font without GL resources
- if(myFont.isNull()) {
- const StString ST_FONT_SANS_PATH = StProcess::getFontsRoot() + getFont(ST_FONT_SANS);
- StStringUtf8 aFontPath = StFileNode::getCompatibleName(ST_FONT_SANS_PATH);
-
- StHandle aFont = new StFTFont();
- if(!aFont->init(aFontPath, getFontSize(), myRoot->getResolution())) {
- ST_ERROR_LOG("Could not load font '" + ST_FONT_SANS_PATH + '\'');
- }
- myFont.create(getRoot()->getContextHandle(), new StGLFont(aFont));
- }
+ myFont = getRoot()->getFontManager()->findCreate(StFTFont::Typeface_SansSerif, getFontSize());
}
StGLTextArea::~StGLTextArea() {
@@ -342,22 +261,80 @@
}
}
-void StGLTextArea::stglSetTextSize(const FontSize theSize) {
- if(mySize == theSize
- || myFont.isNull()) {
+void StGLTextArea::setTextWidth(const int theWidth) {
+ myTextWidth = (GLfloat )theWidth;
+ myToRecompute = true;
+}
+
+void StGLTextArea::computeTextWidth(const GLfloat theWidthMax,
+ int& theWidth,
+ int& theHeight) {
+ StHandle& aFontGen = myFont->changeFont()->getFont();
+ if(aFontGen.isNull() || !aFontGen->isValid()) {
+ theWidth = myRoot->scale(int(10 * (myText.getLength() + 2)));
+ theHeight = myRoot->scale(16);
return;
}
- mySize = theSize;
- myToRecompute = true;
-
- StGLContext& aCtx = getContext();
- myFont->stglInit(aCtx, getFontSize(), myRoot->getResolution());
-}
+ GLfloat aWidth = 0.0f;
+ GLfloat aWidthMax = 0.0f;
+ size_t aCharsInLine = 0;
+ size_t aNbLines = 1;
+ aFontGen->setActiveStyle(myFormatter.getDefaultStyle());
+ for(StUtf8Iter anIter = myText.iterator(); *anIter != 0;) {
+ const stUtf32_t aCharThis = *anIter;
+ const stUtf32_t aCharNext = *++anIter;
+
+ if(aCharThis == '\x0D') {
+ continue; // ignore CR
+ } else if(aCharThis == '\x0A') {
+ aWidthMax = stMax(aWidthMax, aWidth);
+ aWidth = 0.0f;
+ ++aNbLines;
+ aCharsInLine = 0;
+ continue; // will be processed on second pass
+ } else if(aCharThis == ' ') {
+ aWidth += aFontGen->getAdvanceX(aCharThis, aCharNext);
+ continue;
+ }
-void StGLTextArea::setTextWidth(const int theWidth) {
- myTextWidth = (GLfloat )theWidth;
- myToRecompute = true;
+ const StFTFont::Subset aSubset = StFTFont::subset(aCharThis);
+ StHandle& aFont = myFont->changeFont(aSubset)->getFont();
+ GLfloat anAdvance = (!aFont.isNull() && aFont->hasSymbol(aCharThis))
+ ? aFont->getAdvanceX(aCharThis, aCharNext)
+ : aFontGen->getAdvanceX(aCharThis, aCharNext);
+ aWidth += anAdvance;
+ if(theWidthMax > 0.0f
+ && aWidth > theWidthMax) {
+ if(aCharsInLine != 0) {
+ aWidthMax = stMax(aWidthMax, aWidth - anAdvance);
+ aWidth = anAdvance;
+ } else {
+ aWidthMax = stMax(aWidthMax, aWidth);
+ aWidth = 0.0f;
+ }
+ ++aNbLines;
+ }
+ }
+ aWidthMax = stMax(aWidthMax, aWidth);
+ theWidth = int(aWidthMax + 1.5f);
+ theHeight = int(GLfloat(aNbLines) * aFontGen->getLineSpacing() + 0.5f);
+}
+
+bool StGLTextArea::stglInitAutoHeightWidth(const int theMaxWidth) {
+ changeRectPx().right() = getRectPx().left() + theMaxWidth; // compute width from text
+ if(!stglInit()) {
+ return false;
+ }
+ changeRectPx().bottom() = getRectPx().top() + getTextHeight();
+ if(theMaxWidth > 0) {
+ changeRectPx().right() = getRectPx().left() + GLint(myFormatter.getMaxLineWidth() + 2.5f);
+ myTextWidth = (GLfloat )getRectPx().width();
+ myToRecompute = true;
+ } else {
+ changeRectPx().right() = getRectPx().left() + getTextWidth();
+ }
+ return true;
}
bool StGLTextArea::stglInit() {
@@ -368,14 +345,15 @@
// initialize GL resources for the font
StGLContext& aCtx = getContext();
if(!myFont->wasInitialized()) {
- myFont.setContext(getRoot()->getContextHandle());
- if(!myFont->getFont()->isValid()) {
+ if( myFont->changeFont().isNull()
+ || myFont->changeFont()->getFont().isNull()
+ || !myFont->changeFont()->getFont()->isValid()) {
return false; // critical error
} else if(!myFont->stglInit(aCtx)) {
ST_ERROR_LOG("Could not initialize OpenGL resources for font");
return false;
}
- } else if(!myFont->isValid()) {
+ } else if(!myFont->changeFont()->isValid()) {
return false;
}
diff -Nru sview-13.10/StGLWidgets/StGLWidget.cpp sview-14.01/StGLWidgets/StGLWidget.cpp
--- sview-13.10/StGLWidgets/StGLWidget.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLWidget.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -67,14 +67,6 @@
}
}
-StGLCorner StGLWidget::getCorner() const {
- return myCorner;
-}
-
-void StGLWidget::setCorner(const StGLCorner theCorner) {
- myCorner = theCorner;
-}
-
bool StGLWidget::isChild(StGLWidget* theWidget,
const bool theIsRecursive) {
for(StGLWidget* aChild = myChildren.getStart(); aChild != NULL; aChild = aChild->getNext()) {
diff -Nru sview-13.10/StGLWidgets/StGLWidgets.cbp sview-14.01/StGLWidgets/StGLWidgets.cbp
--- sview-13.10/StGLWidgets/StGLWidgets.cbp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLWidgets.cbp 2014-01-30 10:45:03.000000000 +0000
@@ -26,6 +26,7 @@
+
@@ -51,6 +52,7 @@
+
@@ -79,6 +81,7 @@
+
@@ -104,6 +107,7 @@
+
@@ -257,6 +261,7 @@
+
@@ -304,6 +309,7 @@
+
diff -Nru sview-13.10/StGLWidgets/StGLWidgets.rc sview-14.01/StGLWidgets/StGLWidgets.rc
--- sview-13.10/StGLWidgets/StGLWidgets.rc 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StGLWidgets.rc 2014-01-30 10:45:03.000000000 +0000
@@ -15,7 +15,7 @@
BEGIN
VALUE "FileDescription", "OpenGL Widgets library\000"
VALUE "FileVersion", SVIEW_SDK_VER_STRING "\000"
- VALUE "LegalCopyright", "\251 2009-2013 Kirill Gavrilov\000"
+ VALUE "LegalCopyright", "\251 2009-2014 Kirill Gavrilov\000"
VALUE "ProductName", "StGLWidgets\000"
VALUE "ProductVersion", SVIEW_SDK_VER_STRING "\000"
VALUE "OfficialSite", "www.sview.ru\000"
diff -Nru sview-13.10/StGLWidgets/StSubQueue.cpp sview-14.01/StGLWidgets/StSubQueue.cpp
--- sview-13.10/StGLWidgets/StSubQueue.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StGLWidgets/StSubQueue.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2010-2011 Kirill Gavrilov
+ * Copyright © 2010-2014 Kirill Gavrilov
*
* Distributed under the Boost Software License, Version 1.0.
* See accompanying file license-boost.txt or copy at
@@ -42,12 +42,12 @@
myMutex.lock();
for(QueueItem* anItem = myFront; anItem != NULL;) {
StHandle aSubItem = anItem->myItem;
- if(anItem->myItem->myTimeEnd < thePTS) {
+ if(anItem->myItem->TimeEnd < thePTS) {
// remove outdated items
myFront = myFront->myNext;
delete anItem;
anItem = myFront;
- } else if(anItem->myItem->myTimeStart <= thePTS) {
+ } else if(anItem->myItem->TimeStart <= thePTS) {
// pop the item
StHandle aSubItem = anItem->myItem;
myFront = myFront->myNext;
diff -Nru sview-13.10/StImageViewer/StImageLoader.cpp sview-14.01/StImageViewer/StImageLoader.cpp
--- sview-13.10/StImageViewer/StImageLoader.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageLoader.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StImageViewer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,17 +19,30 @@
#include "StImageLoader.h"
#include "StImagePluginInfo.h"
#include "StImageViewerStrings.h"
+#include "StImageViewerGUI.h"
-#include
-#include
#include
+using namespace StImageViewerStrings;
+
const char* StImageLoader::ST_IMAGES_MIME_STRING = ST_IMAGE_PLUGIN_MIME_CHAR;
-static SV_THREAD_FUNCTION threadFunction(void* inStImageLoader) {
- StImageLoader* stImageLoader = (StImageLoader* )inStImageLoader;
- stImageLoader->mainLoop();
- return SV_THREAD_RETURN 0;
+namespace {
+
+ static StString formatError(const StString& theFilePath,
+ const StString& theImgLibDescr) {
+ StString aFileName, aFolderName;
+ StFileNode::getFolderAndFile(theFilePath, aFolderName, aFileName);
+ ST_ERROR_LOG("Can not load image file \"" + theFilePath + "\" (" + theImgLibDescr + ')');
+ return StString("Can not load image file:\n\"") + aFileName + "\"\n" + theImgLibDescr;
+ }
+
+ static SV_THREAD_FUNCTION threadFunction(void* theImageLoader) {
+ StImageLoader* anImageLoader = (StImageLoader* )theImageLoader;
+ anImageLoader->mainLoop();
+ return SV_THREAD_RETURN 0;
+ }
+
}
StImageLoader::StImageLoader(const StImageFile::ImageClass theImageLib,
@@ -44,124 +57,231 @@
myTextureQueue(theTextureQueue),
myMsgQueue(theMsgQueue),
myImageLib(theImageLib),
- myToSave(StImageFile::ST_TYPE_NONE),
- myToQuit(false) {
+ myAction(Action_NONE) {
myPlayList.setExtensions(myMimeList.getExtensionsList());
myThread = new StThread(threadFunction, (void* )this);
}
StImageLoader::~StImageLoader() {
- myToQuit = true;
+ myAction = Action_Quit;
myLoadNextEvent.set(); // stop the thread
myThread->wait();
myThread.nullify();
- ///ST_DEBUG_LOG_AT("Destructor done");
}
void StImageLoader::setCompressMemory(const bool theToCompress) {
myTextureQueue->setCompressMemory(theToCompress);
}
-static StString formatError(const StString& theFilePath, const StString& theImgLibDescr) {
- StString aFileName, aFolderName;
- StFileNode::getFolderAndFile(theFilePath, aFolderName, aFileName);
- ST_ERROR_LOG("Can not load image file \"" + theFilePath + "\" (" + theImgLibDescr + ')');
- return StString("Can not load image file:\n\"") + aFileName + "\"\n" + theImgLibDescr;
-}
-
void StImageLoader::processLoadFail(const StString& theErrorDesc) {
myMsgQueue->pushError(theErrorDesc);
myTextureQueue->setConnectedStream(false);
myTextureQueue->clear();
}
+void StImageLoader::metadataFromExif(const StHandle& theDir,
+ StHandle& theInfo) {
+ if(theDir.isNull()) {
+ return;
+ }
+
+ if(!theDir->CameraMaker.isEmpty()) {
+ StDictEntry& anEntry = theInfo->Info.addChange("Exif.Image.Make");
+ anEntry.changeValue() = theDir->CameraMaker;
+ }
+ if(!theDir->CameraModel.isEmpty()) {
+ StDictEntry& anEntry = theInfo->Info.addChange("Exif.Image.Model");
+ anEntry.changeValue() = theDir->CameraModel;
+ }
+ if(!theDir->UserComment.isEmpty()) {
+ StDictEntry& anEntry = theInfo->Info.addChange("Exif.UserComment");
+ anEntry.changeValue() = theDir->UserComment;
+ }
+
+ for(size_t anExifId = 0; anExifId < theDir->SubDirs.size(); ++anExifId) {
+ metadataFromExif(theDir->SubDirs[anExifId], theInfo);
+ }
+}
+
bool StImageLoader::loadImage(const StHandle& theSource,
StHandle& theParams) {
- StString fileToLoadPath = theSource->getPath();
- StImageFile::ImageType anImgType = StImageFile::guessImageType(fileToLoadPath, theSource->getMIME());
+ const StString aFilePath = theSource->getPath();
+ const StImageFile::ImageType anImgType = StImageFile::guessImageType(aFilePath, theSource->getMIME());
- StHandle stImageL = StImageFile::create(myImageLib, anImgType);
- StHandle stImageR = StImageFile::create(myImageLib, anImgType);
- if(stImageL.isNull() || stImageR.isNull()) {
+ StHandle anImageL = StImageFile::create(myImageLib, anImgType);
+ StHandle anImageR = StImageFile::create(myImageLib, anImgType);
+ if(anImageL.isNull()
+ || anImageR.isNull()) {
processLoadFail("No any image library was found!");
return false;
}
+ StHandle anImgInfo = new StImageInfo();
+ anImgInfo->Id = theParams;
+ anImgInfo->Path = aFilePath;
+ anImgInfo->ImageType = anImgType;
+ anImgInfo->IsSavable = false;
+
+ StString aTitleString, aFolder;
+ if(theSource->size() >= 2) {
+ StString aTitleString2;
+ StFileNode::getFolderAndFile(theSource->getValue(0)->getPath(), aFolder, aTitleString);
+ StFileNode::getFolderAndFile(theSource->getValue(1)->getPath(), aFolder, aTitleString2);
+ anImgInfo->Info.add(StArgument(tr(INFO_FILE_NAME),
+ aTitleString + " " + tr(INFO_LEFT) + "\n"
+ + aTitleString2 + " " + tr(INFO_RIGHT)));
+ } else {
+ StFileNode::getFolderAndFile(aFilePath, aFolder, aTitleString);
+ anImgInfo->Info.add(StArgument(tr(INFO_FILE_NAME), aTitleString));
+ }
+
StTimer aLoadTimer(true);
StFormatEnum aSrcFormatCurr = mySrcFormat;
if(anImgType == StImageFile::ST_TYPE_MPO
- || anImgType == StImageFile::ST_TYPE_JPEG) {
+ || anImgType == StImageFile::ST_TYPE_JPEG
+ || anImgType == StImageFile::ST_TYPE_JPS) {
// special procedure to divide MPO (Multi Picture Object)
- StJpegParser aJpegParser;
+ StJpegParser aParser;
double anHParallax = 0.0; // parallax in percents
- if(!aJpegParser.read(fileToLoadPath)) {
- processLoadFail(StString("Can not read the file \"") + fileToLoadPath + '\"');
+ const bool isParsed = aParser.readFile(aFilePath);
+
+ StHandle anImg1, anImg2;
+ size_t aMaxSizeX = 0;
+ size_t aMaxSizeY = 0;
+ for(StHandle anImgIter = aParser.getImage(0); !anImgIter.isNull();
+ anImgIter = anImgIter->Next) {
+ aMaxSizeX = stMax(aMaxSizeX, anImgIter->SizeX);
+ aMaxSizeY = stMax(aMaxSizeY, anImgIter->SizeY);
+ }
+
+ int anImgCounter = 1;
+ for(StHandle anImgIter = aParser.getImage(0); !anImgIter.isNull();
+ anImgIter = anImgIter->Next, ++anImgCounter) {
+ if(anImgIter->SizeX == aMaxSizeX
+ && anImgIter->SizeY == aMaxSizeY) {
+ if(anImg1.isNull()) {
+ anImg1 = anImgIter;
+ continue;
+ } else if(anImg2.isNull()) {
+ anImg2 = anImgIter;
+ continue;
+ }
+ }
+ anImgInfo->Info.add(StArgument(tr(INFO_DIMENSIONS) + (" (") + anImgCounter + ")",
+ StString() + anImgIter->SizeX + " x " + anImgIter->SizeY));
+ }
+
+ // copy metadata
+ if(!aParser.getComment().isEmpty()) {
+ StDictEntry& anEntry = anImgInfo->Info.addChange("Jpeg.Comment");
+ anEntry.changeValue() = aParser.getComment();
+ }
+ if(!aParser.getJpsComment().isEmpty()) {
+ StDictEntry& anEntry = anImgInfo->Info.addChange("Jpeg.JpsComment");
+ anEntry.changeValue() = aParser.getJpsComment();
+ }
+ if(!anImg1.isNull()) {
+ for(size_t anExifId = 0; anExifId < anImg1->Exif.size(); ++anExifId) {
+ metadataFromExif(anImg1->Exif[anExifId], anImgInfo);
+ }
+ const StString aTime = anImg1->getDateTime();
+ if(!aTime.isEmpty()) {
+ StDictEntry& anEntry = anImgInfo->Info.addChange("Exif.Image.DateTime");
+ anEntry.changeValue() = aTime;
+ }
+ }
+ if(mySrcFormat == ST_V_SRC_AUTODETECT) {
+ if(aParser.getSrcFormat() != ST_V_SRC_AUTODETECT) {
+ aSrcFormatCurr = aParser.getSrcFormat();
+ } else if(anImgType == StImageFile::ST_TYPE_JPS) {
+ aSrcFormatCurr = ST_V_SRC_SIDE_BY_SIDE;
+ }
+ }
+
+ //aParser.fillDictionary(anImgInfo->Info, true);
+ if(!isParsed) {
+ processLoadFail(StString("Can not read the file \"") + aFilePath + '\"');
return false;
}
- // read image from memory
- StHandle anImg1 = aJpegParser.getImage(0);
+ anImgInfo->IsSavable = anImg2.isNull();
+ anImgInfo->SrcFormat = aParser.getSrcFormat();
+ if(anImgInfo->SrcFormat != ST_V_SRC_AUTODETECT) {
+ StDictEntry& anEntry = anImgInfo->Info.addChange("Jpeg.JpsStereo");
+ anEntry.changeValue() = tr(StImageViewerGUI::trSrcFormatId(anImgInfo->SrcFormat));
+ }
- StJpegParser::Orient anOrient = anImg1->getOrientation();
+ // read image from memory
+ const StJpegParser::Orient anOrient = anImg1->getOrientation();
theParams->setZRotateZero((GLfloat )StJpegParser::getRotationAngle(anOrient));
anImg1->getParallax(anHParallax);
- if(!stImageL->load(fileToLoadPath, StImageFile::ST_TYPE_JPEG,
- (uint8_t* )anImg1->myData, (int )anImg1->myLength)
- && !stImageL->load(fileToLoadPath, StImageFile::ST_TYPE_JPEG,
- (uint8_t* )aJpegParser.getData(), (int )aJpegParser.getDataSize())) {
- processLoadFail(formatError(fileToLoadPath, stImageL->getState()));
+ if(!anImageL->load(aFilePath, StImageFile::ST_TYPE_JPEG,
+ (uint8_t* )anImg1->Data, (int )anImg1->Length)
+ && !anImageL->load(aFilePath, StImageFile::ST_TYPE_JPEG,
+ (uint8_t* )aParser.getBuffer(), (int )aParser.getSize())) {
+ processLoadFail(formatError(aFilePath, anImageL->getState()));
return false;
}
- StHandle anImg2 = aJpegParser.getImage(1);
- if(!anImg2.isNull() && anImgType == StImageFile::ST_TYPE_MPO) {
+ if(!anImg2.isNull()) {
// read image from memory
anImg2->getParallax(anHParallax); // in MPO parallax generally stored ONLY in second frame
- if(!stImageR->load(fileToLoadPath, StImageFile::ST_TYPE_JPEG,
- (uint8_t* )anImg2->myData, (int )anImg2->myLength)) {
- processLoadFail(formatError(fileToLoadPath, stImageR->getState()));
- stImageL->close();
- stImageL->nullify();
+ if(!anImageR->load(aFilePath, StImageFile::ST_TYPE_JPEG,
+ (uint8_t* )anImg2->Data, (int )anImg2->Length)) {
+ processLoadFail(formatError(aFilePath, anImageR->getState()));
+ anImageL->close();
+ anImageL->nullify();
return false;
}
// convert percents to pixels
- theParams->setSeparationNeutral(GLint(anHParallax * stImageR->getSizeX() * 0.01));
+ const GLint aParallaxPx = GLint(anHParallax * anImageR->getSizeX() * 0.01);
+ if(aParallaxPx != 0) {
+ StDictEntry& anEntry = anImgInfo->Info.addChange("Exif.Fujifilm.Parallax");
+ anEntry.changeValue() = StString(anHParallax);
+ }
+ theParams->setSeparationNeutral(aParallaxPx);
} else if(anImgType == StImageFile::ST_TYPE_MPO) {
- ST_DEBUG_LOG("MPO image \"" + fileToLoadPath + "\" is invalid!");
+ ST_DEBUG_LOG("MPO image \"" + aFilePath + "\" is invalid!");
}
} else if(theSource->size() >= 2) {
- StString fileToLoadPathLeft = theSource->getValue(0)->getPath();
- StString fileToLoadPathRight = theSource->getValue(1)->getPath();
+ const StString aFilePathLeft = theSource->getValue(0)->getPath();
+ const StString aFilePathRight = theSource->getValue(1)->getPath();
// loading image with format autodetection
- if(!stImageL->load(fileToLoadPathLeft)) {
- processLoadFail(formatError(fileToLoadPathLeft, stImageL->getState()));
+ if(!anImageL->load(aFilePathLeft)) {
+ processLoadFail(formatError(aFilePathLeft, anImageL->getState()));
return false;
}
- if(!stImageR->load(fileToLoadPathRight)) {
- processLoadFail(formatError(fileToLoadPathRight, stImageR->getState()));
- stImageL->close();
- stImageL->nullify();
+ if(!anImageR->load(aFilePathRight)) {
+ processLoadFail(formatError(aFilePathRight, anImageR->getState()));
+ anImageL->close();
+ anImageL->nullify();
return false;
}
} else {
- if(mySrcFormat == ST_V_SRC_AUTODETECT && (anImgType == StImageFile::ST_TYPE_JPS || anImgType == StImageFile::ST_TYPE_PNS)) {
- aSrcFormatCurr = ST_V_SRC_SIDE_BY_SIDE;
- }
- if(!stImageL->load(fileToLoadPath, anImgType)) {
- processLoadFail(formatError(fileToLoadPath, stImageL->getState()));
+ if(!anImageL->load(aFilePath, anImgType)) {
+ processLoadFail(formatError(aFilePath, anImageL->getState()));
return false;
}
+
+ anImgInfo->SrcFormat = anImageL->getFormat();
+ if(mySrcFormat == ST_V_SRC_AUTODETECT) {
+ aSrcFormatCurr = anImageL->getFormat();
+ }
+ if(aSrcFormatCurr == ST_V_SRC_AUTODETECT
+ && anImgType == StImageFile::ST_TYPE_PNS) {
+ aSrcFormatCurr = ST_V_SRC_SIDE_BY_SIDE;
+ }
}
const double aLoadTimeMSec = aLoadTimer.getElapsedTimeInMilliSec();
#ifdef __ST_DEBUG__
- if(!stImageL->isNull()) {
- ST_DEBUG_LOG(stImageL->getState());
+ if(!anImageL->isNull()) {
+ ST_DEBUG_LOG(anImageL->getState());
}
- if(!stImageR->isNull()) {
- ST_DEBUG_LOG(stImageR->getState());
+ if(!anImageR->isNull()) {
+ ST_DEBUG_LOG(anImageR->getState());
}
#endif
@@ -171,45 +291,45 @@
}
myTextureQueue->setConnectedStream(true);
- if(!stImageR->isNull()) {
- myTextureQueue->push(*stImageL, *stImageR, theParams, ST_V_SRC_SEPARATE_FRAMES, 0.0);
+ if(!anImageR->isNull()) {
+ myTextureQueue->push(*anImageL, *anImageR, theParams, ST_V_SRC_SEPARATE_FRAMES, 0.0);
} else {
- myTextureQueue->push(*stImageL, *stImageR, theParams, aSrcFormatCurr, 0.0);
+ myTextureQueue->push(*anImageL, *anImageR, theParams, aSrcFormatCurr, 0.0);
}
- StHandle anImgInfo = new StImageInfo();
- anImgInfo->myId = theParams;
-
- StString aTitleString, aFolder;
- if(theSource->size() >= 2) {
- StFileNode::getFolderAndFile(theSource->getValue(0)->getPath(), aFolder, aTitleString);
- anImgInfo->myInfo.add(StArgument("Name (L)", aTitleString));
- StFileNode::getFolderAndFile(theSource->getValue(1)->getPath(), aFolder, aTitleString);
- anImgInfo->myInfo.add(StArgument("Name (R)", aTitleString));
- } else {
- StFileNode::getFolderAndFile(fileToLoadPath, aFolder, aTitleString);
- anImgInfo->myInfo.add(StArgument("Name", aTitleString));
- }
- if(!stImageR->isNull()) {
- anImgInfo->myInfo.add(StArgument("Dimensions (L)", StString() + stImageL->getSizeX()
- + " x " + stImageL->getSizeY()));
- anImgInfo->myInfo.add(StArgument("Dimensions (R)", StString() + stImageR->getSizeX()
- + " x " + stImageR->getSizeY()));
- anImgInfo->myInfo.add(StArgument("Color Model (L)", stImageL->formatImgColorModel()));
- anImgInfo->myInfo.add(StArgument("Color Model (R)", stImageR->formatImgColorModel()));
+ if(!stAreEqual(anImageL->getPixelRatio(), 1.0f, 0.001f)) {
+ anImgInfo->Info.add(StArgument(tr(INFO_PIXEL_RATIO),
+ StString(anImageL->getPixelRatio())));
+ }
+ const StString aModelL = anImageL->formatImgColorModel();
+ if(!anImageR->isNull()) {
+ anImgInfo->Info.add(StArgument(tr(INFO_DIMENSIONS), StString()
+ + anImageL->getSizeX() + " x " + anImageL->getSizeY() + " " + tr(INFO_LEFT) + "\n"
+ + anImageR->getSizeX() + " x " + anImageR->getSizeY() + " " + tr(INFO_RIGHT)));
+ const StString aModelR = anImageR->formatImgColorModel();
+ if(aModelL == aModelR) {
+ anImgInfo->Info.add(StArgument(tr(INFO_COLOR_MODEL), aModelL));
+ } else {
+ anImgInfo->Info.add(StArgument(tr(INFO_COLOR_MODEL),
+ aModelL + " " + tr(INFO_LEFT) + "\n"
+ + aModelR + " " + tr(INFO_RIGHT)));
+ }
} else {
- anImgInfo->myInfo.add(StArgument("Dimensions", StString() + stImageL->getSizeX()
- + " x " + stImageL->getSizeY()));
- anImgInfo->myInfo.add(StArgument("Color Model", stImageL->formatImgColorModel()));
+ anImgInfo->Info.add(StArgument(tr(INFO_DIMENSIONS), StString()
+ + anImageL->getSizeX() + " x " + anImageL->getSizeY()));
+ anImgInfo->Info.add(StArgument(tr(INFO_COLOR_MODEL),
+ aModelL));
}
- anImgInfo->myInfo.add(StArgument("Load time", StString(aLoadTimeMSec) + " msec"));
+ anImgInfo->Info.add(StArgument(tr(INFO_LOAD_TIME), StString(aLoadTimeMSec) + " " + tr(INFO_TIME_MSEC)));
+ myLock.lock();
myImgInfo = anImgInfo;
+ myLock.unlock();
// clean up - close opened files and reset memory
- stImageL->close();
- stImageL->nullify();
- stImageR->close();
- stImageR->nullify();
+ anImageL->close();
+ anImageL->nullify();
+ anImageR->close();
+ anImageR->nullify();
myTextureQueue->stglSwapFB(0);
@@ -221,52 +341,54 @@
bool StImageLoader::saveImage(const StHandle& theSource,
const StHandle& theParams,
StImageFile::ImageType theImgType) {
- if(theParams.isNull() || theParams.isNull() || theImgType == StImageFile::ST_TYPE_NONE) {
- stInfo(myLangMap->getValue(StImageViewerStrings::DIALOG_NOTHING_TO_SAVE));
+ if(theParams.isNull()
+ || theImgType == StImageFile::ST_TYPE_NONE) {
+ myMsgQueue->pushError(tr(DIALOG_NOTHING_TO_SAVE));
return false;
}
- int result = StGLTextureQueue::SNAPSHOT_NO_NEW;
- StImage dataLeft;
- StImage dataRight;
+ int aResult = StGLTextureQueue::SNAPSHOT_NO_NEW;
+ StImage aDataLeft, aDataRight;
if(!theParams->isSwapLR()) {
- result = getSnapshot(&dataLeft, &dataRight, true);
+ aResult = getSnapshot(&aDataLeft, &aDataRight, true);
} else {
- result = getSnapshot(&dataRight, &dataLeft, true);
+ aResult = getSnapshot(&aDataRight, &aDataLeft, true);
}
- if(result == StGLTextureQueue::SNAPSHOT_NO_NEW || dataLeft.isNull()) {
- stInfo(myLangMap->getValue(StImageViewerStrings::DIALOG_NO_SNAPSHOT));
+ if(aResult == StGLTextureQueue::SNAPSHOT_NO_NEW
+ || aDataLeft.isNull()) {
+ myMsgQueue->pushInfo(tr(DIALOG_NO_SNAPSHOT));
return false;
}
- StHandle dataResult = StImageFile::create(myImageLib);
- if(dataResult.isNull()) {
+ StHandle aDataResult = StImageFile::create(myImageLib);
+ if(aDataResult.isNull()) {
myMsgQueue->pushError(stCString("No any image library was found!"));
return false;
}
- bool toSaveStereo = !dataRight.isNull();
- if(toSaveStereo && dataResult->initSideBySide(dataLeft, dataRight,
- theParams->getSeparationDx(),
- theParams->getSeparationDy())) {
- dataLeft.nullify();
- dataRight.nullify();
+ const bool toSaveStereo = !aDataRight.isNull();
+ if(toSaveStereo
+ && aDataResult->initSideBySide(aDataLeft, aDataRight,
+ theParams->getSeparationDx(),
+ theParams->getSeparationDy())) {
+ aDataLeft.nullify();
+ aDataRight.nullify();
} else {
- dataResult->initWrapper(dataLeft);
+ aDataResult->initWrapper(aDataLeft);
}
const StString& aTitle = myLangMap->getValue(StImageViewerStrings::DIALOG_SAVE_SNAPSHOT);
- StMIMEList filter;
- StString saveExt;
+ StMIMEList aFilter;
+ StString aSaveExt;
if(toSaveStereo) {
switch(theImgType) {
case StImageFile::ST_TYPE_PNG:
- saveExt = ST_PNS_EXT;
- filter.add(StMIME(ST_PNS_MIME, saveExt, ST_PNS_DESC));
+ aSaveExt = ST_PNS_EXT;
+ aFilter.add(StMIME(ST_PNS_MIME, aSaveExt, ST_PNS_DESC));
break;
case StImageFile::ST_TYPE_JPEG:
- saveExt = ST_JPS_EXT;
- filter.add(StMIME(ST_JPS_MIME, saveExt, ST_JPS_DESC));
+ aSaveExt = ST_JPS_EXT;
+ aFilter.add(StMIME(ST_JPS_MIME, aSaveExt, ST_JPS_DESC));
break;
default:
return false;
@@ -274,28 +396,28 @@
} else {
switch(theImgType) {
case StImageFile::ST_TYPE_PNG:
- saveExt = ST_PNG_EXT;
- filter.add(StMIME(ST_PNG_MIME, saveExt, ST_PNG_DESC));
+ aSaveExt = ST_PNG_EXT;
+ aFilter.add(StMIME(ST_PNG_MIME, aSaveExt, ST_PNG_DESC));
break;
case StImageFile::ST_TYPE_JPEG:
- saveExt = ST_JPG_EXT;
- filter.add(StMIME(ST_JPG_MIME, saveExt, ST_JPEG_DESC));
+ aSaveExt = ST_JPG_EXT;
+ aFilter.add(StMIME(ST_JPG_MIME, aSaveExt, ST_JPEG_DESC));
break;
default:
return false;
}
}
- StString fileToSave;
- if(StFileNode::openFileDialog(theSource->getFolderPath(), aTitle, filter, fileToSave, true)) {
- if(StFileNode::getExtension(fileToSave) != saveExt) {
- fileToSave += StString('.') + saveExt;
+ StString aFileToSave;
+ if(StFileNode::openFileDialog(theSource->getFolderPath(), aTitle, aFilter, aFileToSave, true)) {
+ if(StFileNode::getExtension(aFileToSave) != aSaveExt) {
+ aFileToSave += StString('.') + aSaveExt;
}
- bool toSave = !StFileNode::isFileExists(fileToSave);
+ bool toSave = !StFileNode::isFileExists(aFileToSave);
if(!toSave) {
if(stQuestion("File already exists!\nOverride the file?")) {
- toSave = StFileNode::removeFile(fileToSave);
+ toSave = StFileNode::removeFile(aFileToSave);
if(!toSave) {
myMsgQueue->pushError(stCString("Could not remove the file!"));
return false;
@@ -304,15 +426,16 @@
}
if(toSave) {
- ST_DEBUG_LOG("Save snapshot to the path '" + fileToSave + '\'');
+ ST_DEBUG_LOG("Save snapshot to the path '" + aFileToSave + '\'');
StString strSaveState;
- if(!dataResult->save(fileToSave, theImgType)) {
+ if(!aDataResult->save(aFileToSave, theImgType,
+ toSaveStereo ? ST_V_SRC_SIDE_BY_SIDE : ST_V_SRC_AUTODETECT)) {
// TODO (Kirill Gavrilov#7)
- myMsgQueue->pushError(dataResult->getState());
+ myMsgQueue->pushError(aDataResult->getState());
return false;
}
- if(!dataResult->getState().isEmpty()) {
- ST_DEBUG_LOG(dataResult->getState());
+ if(!aDataResult->getState().isEmpty()) {
+ ST_DEBUG_LOG(aDataResult->getState());
}
// TODO (Kirill Gavrilov#8) - update playlist (append new file)
}
@@ -320,27 +443,79 @@
return true;
}
+bool StImageLoader::saveImageInfo(const StHandle& theInfo) {
+ if(theInfo.isNull()
+ || theInfo->Path.isEmpty()) {
+ myMsgQueue->pushError(tr(DIALOG_NOTHING_TO_SAVE));
+ return false;
+ } else if(theInfo->ImageType != StImageFile::ST_TYPE_JPEG
+ && theInfo->ImageType != StImageFile::ST_TYPE_JPS) {
+ myMsgQueue->pushError(stCString("Operation is unavailable for this image type"));
+ return false;
+ }
+
+ StFormatEnum aSrcFormat = theInfo->Id->getSrcFormat();
+ if(theInfo->Id->isSwapLR()) {
+ aSrcFormat = st::formatReversed(aSrcFormat);
+ }
+
+ StJpegParser aParser;
+ if(!aParser.readFile(theInfo->Path)) {
+ myMsgQueue->pushError(tr(DIALOG_NOTHING_TO_SAVE));
+ return false;
+ }
+
+ aParser.setupJps(aSrcFormat);
+ if(!aParser.saveFile(theInfo->Path)) {
+ myMsgQueue->pushError(StString("File can not be saved at path '") + theInfo->Path + "'!");
+ return false;
+ }
+ return true;
+}
+
void StImageLoader::mainLoop() {
- StHandle aFileToLoad;
+ StHandle aFileToLoad;
StHandle aFileParams;
for(;;) {
myLoadNextEvent.wait();
- if(myToQuit) {
- // exit the loop
- return;
- } else if(myToSave != StImageFile::ST_TYPE_NONE) {
- StImageFile::ImageType anImgType = myToSave;
- myToSave = StImageFile::ST_TYPE_NONE;
- myLoadNextEvent.reset();
- // save current image (set as current in playlist)
- if(myPlayList.getCurrentFile(aFileToLoad, aFileParams)) {
- saveImage(aFileToLoad, aFileParams, anImgType);
+ switch(myAction) {
+ case Action_Quit: {
+ // exit the loop
+ return;
}
- } else {
- // load next image (set as current in playlist)
- myLoadNextEvent.reset();
- if(myPlayList.getCurrentFile(aFileToLoad, aFileParams)) {
- loadImage(aFileToLoad, aFileParams);
+ case Action_SaveJPEG:
+ case Action_SavePNG: {
+ StImageFile::ImageType anImgType = (myAction == Action_SaveJPEG)
+ ? StImageFile::ST_TYPE_JPEG
+ : StImageFile::ST_TYPE_PNG;
+ myAction = Action_NONE;
+ myLoadNextEvent.reset();
+ // save current image (set as current in playlist)
+ if(myPlayList.getCurrentFile(aFileToLoad, aFileParams)) {
+ saveImage(aFileToLoad, aFileParams, anImgType);
+ }
+ break;
+ }
+ case Action_SaveInfo: {
+ myLock.lock();
+ StHandle anInfo = myInfoToSave;
+ myInfoToSave.nullify();
+ myAction = Action_NONE;
+ myLock.unlock();
+ myLoadNextEvent.reset();
+ if(!saveImageInfo(anInfo)) {
+ break;
+ }
+ // re-load image file
+ }
+ case Action_NONE:
+ default: {
+ // load next image (set as current in playlist)
+ myLoadNextEvent.reset();
+ if(myPlayList.getCurrentFile(aFileToLoad, aFileParams)) {
+ loadImage(aFileToLoad, aFileParams);
+ }
+ break;
}
}
}
diff -Nru sview-13.10/StImageViewer/StImageLoader.h sview-14.01/StImageViewer/StImageLoader.h
--- sview-13.10/StImageViewer/StImageLoader.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageLoader.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StImageViewer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,16 +24,23 @@
#include
#include
#include
+#include
#include
+#include
#include
-class StLangMap;
class StThread;
struct StImageInfo {
- StHandle myId;
- StArgumentsMap myInfo;
+ StHandle Id;
+ StArgumentsMap Info;
+ StString Path; //!< file path
+ StImageFile::ImageType ImageType; //!< image type
+ StFormatEnum SrcFormat; //!< source format as stored in file metadata
+ bool IsSavable; //!< indicate that file can be saved without re-encoding
+
+ StImageInfo() : ImageType(StImageFile::ST_TYPE_NONE), SrcFormat(ST_V_SRC_AUTODETECT), IsSavable(false) {}
};
@@ -44,8 +51,20 @@
public:
+ enum Action {
+ Action_NONE,
+ Action_Quit,
+ Action_SaveJPEG,
+ Action_SavePNG,
+ Action_SaveInfo,
+ };
+
+ public:
+
static const char* ST_IMAGES_MIME_STRING;
+ public:
+
ST_LOCAL const StMIMEList& getMimeList() const {
return myMimeList;
}
@@ -67,13 +86,34 @@
}
ST_LOCAL void doSaveImageAs(const size_t theImgType) {
- myToSave = StImageFile::ImageType(theImgType);
+ if(myAction == Action_Quit) {
+ return;
+ }
+
+ if(theImgType == StImageFile::ST_TYPE_JPEG) {
+ myAction = Action_SaveJPEG;
+ } else if(theImgType == StImageFile::ST_TYPE_PNG) {
+ myAction = Action_SavePNG;
+ } else {
+ ST_ERROR_LOG("Attempt to save in unsupported image format " + theImgType);
+ return;
+ }
+ myLoadNextEvent.set();
+ }
+
+ ST_LOCAL void doSaveInfo(const StHandle& theInfo) {
+ myLock.lock();
+ myInfoToSave = theInfo;
+ myAction = Action_SaveInfo;
+ myLock.unlock();
myLoadNextEvent.set();
}
ST_LOCAL StHandle getFileInfo(const StHandle& theParams) const {
+ myLock.lock();
StHandle anInfo = myImgInfo;
- return (!anInfo.isNull() && anInfo->myId == theParams) ? anInfo : NULL;
+ myLock.unlock();
+ return (!anInfo.isNull() && anInfo->Id == theParams) ? anInfo : NULL;
}
ST_LOCAL StPlayList& getPlayList() {
@@ -97,7 +137,7 @@
*/
ST_LOCAL void setCompressMemory(const bool theToCompress);
- public: //!< Signals
+ public: //! @name Signals
struct {
/**
@@ -115,6 +155,8 @@
const StHandle& theParams,
StImageFile::ImageType theImgType);
+ ST_LOCAL bool saveImageInfo(const StHandle& theInfo);
+
ST_LOCAL int getSnapshot(StImage* outDataLeft, StImage* outDataRight, bool isForce = false) {
return myTextureQueue->getSnapshot(outDataLeft, outDataRight, isForce);
}
@@ -124,21 +166,32 @@
*/
ST_LOCAL void processLoadFail(const StString& theErrorDesc);
+ /**
+ * Fill metadata map from EXIF.
+ */
+ ST_LOCAL void metadataFromExif(const StHandle& theDir,
+ StHandle& theInfo);
+
+ ST_LOCAL const StString& tr(const size_t theId) const {
+ return myLangMap->getValue(theId);
+ }
+
private:
const StMIMEList myMimeList;
StHandle myThread; //!< main loop thread
StHandle myLangMap; //!< translations dictionary
StPlayList myPlayList; //!< play list
+ mutable StMutex myLock; //!< lock to access not thread-safe properties
StCondition myLoadNextEvent;
StFormatEnum mySrcFormat; //!< target source format (auto-detect by default)
StHandle myTextureQueue; //!< decoded frames queue
StHandle myImgInfo; //!< info about currently loaded image
+ StHandle myInfoToSave; //!< modified info to be saved
StHandle myMsgQueue; //!< messages queue
volatile StImageFile::ImageClass myImageLib;
- volatile StImageFile::ImageType myToSave;
- volatile bool myToQuit;
+ volatile Action myAction;
private: //! @name no copies, please
diff -Nru sview-13.10/StImageViewer/StImageViewer.cbp sview-14.01/StImageViewer/StImageViewer.cbp
--- sview-13.10/StImageViewer/StImageViewer.cbp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageViewer.cbp 2014-01-30 10:45:03.000000000 +0000
@@ -33,12 +33,7 @@
-
-
-
-
-
-
+
@@ -69,12 +64,7 @@
-
-
-
-
-
-
+
@@ -111,12 +101,7 @@
-
-
-
-
-
-
+
@@ -148,12 +133,7 @@
-
-
-
-
-
-
+
@@ -181,12 +161,7 @@
-
-
-
-
-
-
+
@@ -213,12 +188,7 @@
-
-
-
-
-
-
+
@@ -241,12 +211,7 @@
-
-
-
-
-
-
+
@@ -271,12 +236,7 @@
-
-
-
-
-
-
+
@@ -332,9 +292,18 @@
+
+
+
+
+
+
+
+
+
diff -Nru sview-13.10/StImageViewer/StImageViewer.cpp sview-14.01/StImageViewer/StImageViewer.cpp
--- sview-13.10/StImageViewer/StImageViewer.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageViewer.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StImageViewer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -164,6 +164,12 @@
anAction = new StActionIntValue(stCString("DoSrcSideBySide"), params.srcFormat, ST_V_SRC_SIDE_BY_SIDE);
addAction(Action_SrcSideBySideRL, anAction, ST_VK_S);
+ anAction = new StActionIntSlot(stCString("DoFileInfo"), stSlot(this, &StImageViewer::doAboutImage), 0);
+ addAction(Action_FileInfo, anAction, ST_VK_I);
+
+ anAction = new StActionIntSlot(stCString("DoSaveFileInfo"), stSlot(this, &StImageViewer::doSaveImageInfoBegin), 0);
+ addAction(Action_SaveFileInfo, anAction, ST_VK_I | ST_VF_SHIFT);
+
anAction = new StActionIntSlot(stCString("DoListFirst"), stSlot(this, &StImageViewer::doListFirst), 0);
addAction(Action_ListFirst, anAction, ST_VK_HOME);
@@ -462,6 +468,40 @@
myGUI->myImage->params.saturation->reset();
}
+void StImageViewer::doSaveImageInfoBegin(const size_t ) {
+ if(!myFileInfo.isNull()) {
+ return; // already opened
+ }
+
+ StHandle aFileNode;
+ StHandle aParams;
+ if(!getCurrentFile(aFileNode, aParams, myFileInfo)
+ || myFileInfo.isNull()) {
+ myMsgQueue->pushInfo(myLangMap->getValue(StImageViewerStrings::DIALOG_FILE_NOINFO));
+ myFileInfo.nullify();
+ return;
+ } else if(!myFileInfo->IsSavable) {
+ myMsgQueue->pushInfo(myLangMap->getValue(StImageViewerStrings::DIALOG_SAVE_INFO_UNSUPPORTED));
+ myFileInfo.nullify();
+ return;
+ }
+
+ const StString aText = myLangMap->getValue(StImageViewerStrings::DIALOG_SAVE_INFO_QUESTION)
+ + "\n" + myFileInfo->Path;
+
+ StInfoDialog* aDialog = new StInfoDialog(this, myGUI.access(), myLangMap->getValue(StImageViewerStrings::DIALOG_SAVE_INFO_TITLE),
+ myGUI->scale(512), myGUI->scale(256));
+ aDialog->setText(aText);
+
+ StGLButton* aSaveBtn = aDialog->addButton(myLangMap->getValue(StImageViewerStrings::BUTTON_SAVE_METADATA), true);
+ aSaveBtn->setUserData(1);
+ aSaveBtn->signals.onBtnClick += stSlot(this, &StImageViewer::doSaveImageInfo);
+
+ aDialog->addButton(myLangMap->getValue(StImageViewerStrings::BUTTON_CANCEL));
+ aDialog->setVisibility(true, true);
+ aDialog->stglInit();
+}
+
void StImageViewer::doDeleteFileBegin(const size_t ) {
//if(!myFileToDelete.isNull()) {
// return;
@@ -474,12 +514,13 @@
return;
}
- const StString aText = StString("Do you really want to completely remove this file?\n")
- + myFileToDelete->getPath() + "";
+ const StString aText = myLangMap->getValue(StImageViewerStrings::DIALOG_DELETE_FILE_QUESTION)
+ + "\n" + myFileToDelete->getPath();
- StGLMessageBox* aDialog = new StGLMessageBox(myGUI.access(), aText, 512, 256);
- aDialog->addButton("Delete", true, 96)->signals.onBtnClick += stSlot(this, &StImageViewer::doDeleteFileEnd);
- aDialog->addButton("Cancel", false, 96);
+ StGLMessageBox* aDialog = new StGLMessageBox(myGUI.access(), myLangMap->getValue(StImageViewerStrings::DIALOG_DELETE_FILE_TITLE),
+ aText, myGUI->scale(512), myGUI->scale(256));
+ aDialog->addButton(myLangMap->getValue(StImageViewerStrings::BUTTON_DELETE), true)->signals.onBtnClick += stSlot(this, &StImageViewer::doDeleteFileEnd);
+ aDialog->addButton(myLangMap->getValue(StImageViewerStrings::BUTTON_CANCEL), false);
aDialog->setVisibility(true, true);
aDialog->stglInit();
}
@@ -520,9 +561,6 @@
}
// file walk
- case ST_VK_I:
- myGUI->doAboutImage(0);
- return;
case ST_VK_MEDIA_PREV_TRACK:
case ST_VK_BROWSER_BACK:
doListPrev();
@@ -818,6 +856,21 @@
}
}
+void StImageViewer::doAboutImage(const size_t ) {
+ if(!myGUI.isNull()) {
+ myGUI->doAboutImage(0);
+ }
+}
+
+void StImageViewer::doSaveImageInfo(const size_t theToSave) {
+ if(!myGUI.isNull()
+ && !myFileInfo.isNull()
+ && theToSave == 1) {
+ myLoader->doSaveInfo(myFileInfo);
+ }
+ myFileInfo.nullify();
+}
+
void StImageViewer::doListFirst(const size_t ) {
if(myLoader->getPlayList().walkToFirst()) {
myLoader->doLoadNext();
diff -Nru sview-13.10/StImageViewer/StImageViewer.h sview-14.01/StImageViewer/StImageViewer.h
--- sview-13.10/StImageViewer/StImageViewer.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageViewer.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StImageViewer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -93,6 +93,9 @@
ST_LOCAL void doOpen2FilesDialog(const size_t dummy = 0);
ST_LOCAL void doSaveImageAs(const size_t theImgType) { myLoader->doSaveImageAs(theImgType); }
+ ST_LOCAL void doSaveImageInfo(const size_t theToSave);
+ ST_LOCAL void doSaveImageInfoBegin(const size_t dummy = 0);
+ ST_LOCAL void doAboutImage(const size_t dummy = 0);
ST_LOCAL void doListFirst(const size_t dummy = 0);
ST_LOCAL void doListPrev(const size_t dummy = 0);
ST_LOCAL void doListNext(const size_t dummy = 0);
@@ -159,6 +162,7 @@
Action_SrcMono,
Action_SrcOverUnderLR,
Action_SrcSideBySideRL,
+ Action_FileInfo,
Action_ListFirst,
Action_ListLast,
Action_ListPrev,
@@ -166,6 +170,7 @@
Action_SlideShow,
Action_SavePng,
Action_SaveJpeg,
+ Action_SaveFileInfo,
Action_DeleteFile,
Action_ImageAdjustReset,
Action_StereoParamsBegin,
@@ -200,6 +205,7 @@
StHandle myLoader; //!< main image loader class
StHandle myUpdates; //!< check updates utility
StHandle myFileToDelete; //!< file node for removal
+ StHandle myFileInfo; //!< file info for opened dialog
StCondition myEventDialog; //!< event to prevent showing multiple open/save file dialogs
StCondition myEventLoaded; //!< indicate that new file was open
diff -Nru sview-13.10/StImageViewer/StImageViewer.rc sview-14.01/StImageViewer/StImageViewer.rc
--- sview-13.10/StImageViewer/StImageViewer.rc 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageViewer.rc 2014-01-30 10:45:03.000000000 +0000
@@ -15,7 +15,7 @@
BEGIN
VALUE "FileDescription", "Stereoscopic Image Viewer\000"
VALUE "FileVersion", SVIEW_SDK_VER_STRING "\000"
- VALUE "LegalCopyright", "\251 2007-2013 Kirill Gavrilov\000"
+ VALUE "LegalCopyright", "\251 2007-2014 Kirill Gavrilov\000"
VALUE "ProductName", "StImageViewer\000"
VALUE "ProductVersion", SVIEW_SDK_VER_STRING "\000"
VALUE "OfficialSite", "www.sview.ru\000"
diff -Nru sview-13.10/StImageViewer/StImageViewerGUI.cpp sview-14.01/StImageViewer/StImageViewerGUI.cpp
--- sview-13.10/StImageViewer/StImageViewerGUI.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageViewerGUI.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StImageViewer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,15 +26,17 @@
#include
#include
+#include
#include
#include
#include
#include
#include
-#include
#include
#include
+#include
#include
+#include
#include
#include
@@ -54,6 +56,10 @@
static const int ICON_WIDTH = 64;
};
+StInfoDialog::~StInfoDialog() {
+ myPlugin->doSaveImageInfo(0);
+}
+
/**
* Create upper toolbar
*/
@@ -128,6 +134,7 @@
aMenuMedia->addItem(tr(MENU_MEDIA_OPEN_IMAGE), aMenuOpenImage);
aMenuMedia->addItem(tr(MENU_MEDIA_SAVE_IMAGE_AS), aMenuSaveImage);
aMenuMedia->addItem(tr(MENU_MEDIA_SRC_FORMAT), aMenuSrcFormat);
+ aMenuMedia->addItem(tr(MENU_MEDIA_FILE_INFO), myPlugin->getAction(StImageViewer::Action_FileInfo));
aMenuMedia->addItem("First File in folder")
->signals.onItemClick.connect(myPlugin, &StImageViewer::doListFirst);
@@ -372,13 +379,13 @@
}
void StImageViewerGUI::doAboutProgram(const size_t ) {
- StGLMessageBox* aDialog = new StGLMessageBox(this,
+ StGLMessageBox* aDialog = new StGLMessageBox(this, "",
tr(ABOUT_DPLUGIN_NAME) + '\n'
+ tr(ABOUT_VERSION) + ": " + StVersionInfo::getSDKVersionString()
+ " " + StThread::getArchString()
+ "\n \n" + tr(ABOUT_DESCRIPTION),
scale(512), scale(300));
- aDialog->addButton("Close");
+ aDialog->addButton(tr(BUTTON_CLOSE));
aDialog->setVisibility(true, true);
aDialog->stglInit();
}
@@ -388,38 +395,102 @@
}
void StImageViewerGUI::doAboutSystem(const size_t ) {
- StString aTitle = "System Info";
- StString anInfo = getContext().stglFullInfo();
- StString aString = aTitle + "\n\n \n" + anInfo;
- StGLMessageBox* aDialog = new StGLMessageBox(this, aString, scale(512), scale(256));
- aDialog->addButton("Close");
+ const StString aTitle = tr(ABOUT_SYSTEM);
+ StGLMessageBox* aDialog = new StGLMessageBox(this, aTitle, "", scale(512), scale(256));
+
+ StArgumentsMap anInfo;
+ getContext().stglFullInfo(anInfo);
+ StGLTable* aTable = new StGLTable(aDialog->getContent(), 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_CENTER));
+ aTable->setVisibility(true, true);
+ aTable->fillFromMap(anInfo, StGLVec3(1.0f, 1.0f, 1.0f), aDialog->getContent()->getRectPx().width(), aDialog->getContent()->getRectPx().width() / 2);
+
+ aDialog->addButton(tr(BUTTON_CLOSE));
aDialog->setVisibility(true, true);
aDialog->stglInit();
}
void StImageViewerGUI::doAboutImage(const size_t ) {
+ StHandle& anExtraInfo = myPlugin->myFileInfo;
+ if(!anExtraInfo.isNull()) {
+ return; // already opened
+ }
+
StHandle aFileNode;
StHandle aParams;
- StHandle anExtraInfo;
- StArrayList anInfoList(10);
- if(myPlugin->getCurrentFile(aFileNode, aParams, anExtraInfo) && !anExtraInfo.isNull()) {
- for(size_t aKeyIter = 0; aKeyIter < anExtraInfo->myInfo.size(); ++aKeyIter) {
- const StArgument& aPair = anExtraInfo->myInfo.getFromIndex(aKeyIter);
- anInfoList.add(aPair.getKey() + ": " + aPair.getValue() + "\n");
- }
+ if(!myPlugin->getCurrentFile(aFileNode, aParams, anExtraInfo)
+ || anExtraInfo.isNull()) {
+ StHandle aQueue = myPlugin->getMessagesQueue();
+ aQueue->pushInfo(tr(DIALOG_FILE_NOINFO));
+ anExtraInfo.nullify();
+ return;
}
- StString aTitle = "Image Info";
- StString anInfo;
- for(size_t anIter = 0; anIter < anInfoList.size(); ++anIter) {
- anInfo += anInfoList[anIter];
- }
- StString aString = aTitle + "\n\n \n" + anInfo;
- StGLMessageBox* aDialog = new StGLMessageBox(this, aString, scale(512), scale(300));
- aDialog->addButton("Close");
+ const StString aTitle = tr(DIALOG_FILE_INFO);
+ StInfoDialog* aDialog = new StInfoDialog(myPlugin, this, aTitle, scale(512), scale(300));
+
+ // translate known metadata tag names
+ for(size_t aMapIter = 0; aMapIter < anExtraInfo->Info.size(); ++aMapIter) {
+ StDictEntry& anEntry = anExtraInfo->Info.changeValue(aMapIter);
+ anEntry.changeName() = myLangMap->getValue(anEntry.getKey());
+ }
+ const int aWidthMax = aDialog->getContent()->getRectPx().width();
+ int aRowLast = (int )anExtraInfo->Info.size();
+ const int aNbRowsMax = aRowLast + 2;
+
+ StGLTable* aTable = new StGLTable(aDialog->getContent(), 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_CENTER));
+ aTable->setupTable(aNbRowsMax, 2);
+ aTable->setVisibility(true, true);
+ aTable->fillFromMap(anExtraInfo->Info, StGLVec3(1.0f, 1.0f, 1.0f), aWidthMax, aWidthMax / 2);
+
+ // add stereoscopic format info
+ const StFormatEnum anActiveSrcFormat = aParams->isSwapLR()
+ ? st::formatReversed(aParams->getSrcFormat())
+ : aParams->getSrcFormat();
+ const int aTextMaxWidth = aWidthMax - (aTable->getMarginLeft() + aTable->getMarginRight());
+ StGLTableItem& aSrcFormatItem = aTable->changeElement(aRowLast++, 0); aSrcFormatItem.setColSpan(2);
+ StGLTextArea* aSrcFormatText = new StGLTextArea(&aSrcFormatItem, 0, 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_CENTER));
+ aSrcFormatText->setupAlignment(StGLTextFormatter::ST_ALIGN_X_CENTER,
+ StGLTextFormatter::ST_ALIGN_Y_TOP);
+ aSrcFormatText->setText(StString("\n") + tr(BTN_SRC_FORMAT) + " " + trSrcFormat(anActiveSrcFormat));
+ aSrcFormatText->setTextColor(StGLVec3(1.0f, 1.0f, 1.0f));
+ aSrcFormatText->setVisibility(true, true);
+ aSrcFormatText->stglInitAutoHeightWidth(aTextMaxWidth);
+
+ // warn about wrong/missing stereoscopic format information
+ StString aSrcInfo;
+ StGLVec3 anExtraColor(1.0f, 1.0f, 1.0f);
+ if(anExtraInfo->SrcFormat == ST_V_SRC_AUTODETECT
+ && anActiveSrcFormat != ST_V_SRC_MONO
+ && anActiveSrcFormat != ST_V_SRC_SEPARATE_FRAMES) {
+ aSrcInfo = tr(INFO_NO_SRCFORMAT);
+ anExtraColor = StGLVec3(1.0f, 1.0f, 0.8f);
+ } else if(anExtraInfo->SrcFormat != ST_V_SRC_AUTODETECT
+ && anExtraInfo->SrcFormat != anActiveSrcFormat) {
+ aSrcInfo = tr(INFO_WRONG_SRCFORMAT);
+ anExtraColor = StGLVec3(1.0f, 0.0f, 0.0f);
+ }
+ if(!aSrcInfo.isEmpty()) {
+ StGLTableItem& aTabItem = aTable->changeElement(aRowLast++, 0); aTabItem.setColSpan(2);
+ StGLTextArea* aText = new StGLTextArea(&aTabItem, 0, 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_CENTER));
+ aText->setupAlignment(StGLTextFormatter::ST_ALIGN_X_CENTER,
+ StGLTextFormatter::ST_ALIGN_Y_TOP);
+ aText->setText(aSrcInfo);
+ aText->setTextColor(anExtraColor);
+ aText->setVisibility(true, true);
+ aText->stglInitAutoHeightWidth(aTextMaxWidth);
+ }
+ aTable->updateLayout();
+
+ if(anExtraInfo->IsSavable
+ && !aSrcInfo.isEmpty()) {
+ StGLButton* aSaveBtn = aDialog->addButton(tr(BUTTON_SAVE_METADATA));
+ aSaveBtn->setUserData(1);
+ aSaveBtn->signals.onBtnClick += stSlot(myPlugin, &StImageViewer::doSaveImageInfo);
+ }
+
+ aDialog->addButton(tr(BUTTON_CLOSE), true);
aDialog->setVisibility(true, true);
aDialog->stglInit();
-
}
void StImageViewerGUI::doCheckUpdates(const size_t ) {
@@ -515,6 +586,7 @@
myBtnNext(NULL),
myBtnSwapLR(NULL),
myBtnSrcFrmt(NULL),
+ myBtnPlayList(NULL),
myBtnFull(NULL),
//
myFpsWidget(NULL),
@@ -536,6 +608,10 @@
createUpperToolbar();
+ myBtnPlayList = new StGLTextureButton(this, -aMargins.right() - scale(8 + 8 + 32), -aMargins.bottom() - scale(8),
+ StGLCorner(ST_VCORNER_BOTTOM, ST_HCORNER_RIGHT));
+ myBtnPlayList->setTexturePath(iconTexture(stCString("playList"), scaleIcon(32)));
+
// fullscreen button
myBtnFull = new StGLTextureButton(this, -aMargins.right() - scale(8), -aMargins.bottom() - scale(8),
StGLCorner(ST_VCORNER_BOTTOM, ST_HCORNER_RIGHT));
@@ -575,6 +651,23 @@
};
+size_t StImageViewerGUI::trSrcFormatId(const StFormatEnum theSrcFormat) {
+ switch(theSrcFormat) {
+ case ST_V_SRC_MONO: return MENU_SRC_FORMAT_MONO;
+ case ST_V_SRC_SIDE_BY_SIDE: return MENU_SRC_FORMAT_CROSS_EYED;
+ case ST_V_SRC_PARALLEL_PAIR: return MENU_SRC_FORMAT_PARALLEL;
+ case ST_V_SRC_OVER_UNDER_RL: return MENU_SRC_FORMAT_OVERUNDER_RL;
+ case ST_V_SRC_OVER_UNDER_LR: return MENU_SRC_FORMAT_OVERUNDER_LR;
+ case ST_V_SRC_ROW_INTERLACE: return MENU_SRC_FORMAT_INTERLACED;
+ case ST_V_SRC_ANAGLYPH_G_RB: return MENU_SRC_FORMAT_ANA_RB;
+ case ST_V_SRC_ANAGLYPH_RED_CYAN: return MENU_SRC_FORMAT_ANA_RC;
+ case ST_V_SRC_ANAGLYPH_YELLOW_BLUE: return MENU_SRC_FORMAT_ANA_YB;
+ case ST_V_SRC_SEPARATE_FRAMES: return MENU_SRC_FORMAT_SEPARATE;
+ default:
+ case ST_V_SRC_AUTODETECT: return MENU_SRC_FORMAT_AUTO;
+ }
+}
+
void StImageViewerGUI::setVisibility(const StPointD_t& theCursor,
bool isMouseActive) {
myIsVisibleGUI = isMouseActive
@@ -591,7 +684,6 @@
myImage->setVisibility(true, true);
if(myMenuRoot != NULL) {
- ///myMenuRoot->setVisibility(myIsVisibleGUI, false);
myMenuRoot->setVisibility(toShowAll, false);
}
@@ -602,6 +694,9 @@
child->setVisibility(toShowAll);
}
}
+ if(myBtnPlayList != NULL) {
+ //myBtnPlayList->setVisibility(myIsMinimalGUI || toShowAll);
+ }
if(myBtnFull != NULL) {
myBtnFull->setVisibility(myIsMinimalGUI || toShowAll);
}
@@ -617,30 +712,21 @@
} else if(::isPointIn(myBtnSwapLR, theCursor)) {
size_t aLngId = myImage->params.swapLR->getValue() ? SWAP_LR_ON : SWAP_LR_OFF;
myDescr->setText(tr(aLngId));
+ } else if(::isPointIn(myBtnPlayList, theCursor)) {
+ myDescr->setText(tr(PLAYLIST));
} else if(::isPointIn(myBtnFull, theCursor)) {
myDescr->setText(tr(FULLSCREEN));
} else if(::isPointIn(myBtnSrcFrmt, theCursor)) {
- size_t aLngId = MENU_SRC_FORMAT_AUTO;
StFormatEnum aSrcFormat = (StFormatEnum )myPlugin->params.srcFormat->getValue();
if(aSrcFormat == ST_V_SRC_AUTODETECT
&& !myImage->params.stereoFile.isNull()) {
aSrcFormat = myImage->params.stereoFile->getSrcFormat();
}
- switch(aSrcFormat) {
- case ST_V_SRC_MONO: aLngId = MENU_SRC_FORMAT_MONO; break;
- case ST_V_SRC_SIDE_BY_SIDE: aLngId = MENU_SRC_FORMAT_CROSS_EYED; break;
- case ST_V_SRC_PARALLEL_PAIR: aLngId = MENU_SRC_FORMAT_PARALLEL; break;
- case ST_V_SRC_OVER_UNDER_RL: aLngId = MENU_SRC_FORMAT_OVERUNDER_RL; break;
- case ST_V_SRC_OVER_UNDER_LR: aLngId = MENU_SRC_FORMAT_OVERUNDER_LR; break;
- case ST_V_SRC_ROW_INTERLACE: aLngId = MENU_SRC_FORMAT_INTERLACED; break;
- case ST_V_SRC_ANAGLYPH_G_RB: aLngId = MENU_SRC_FORMAT_ANA_RB; break;
- case ST_V_SRC_ANAGLYPH_RED_CYAN: aLngId = MENU_SRC_FORMAT_ANA_RC; break;
- case ST_V_SRC_ANAGLYPH_YELLOW_BLUE: aLngId = MENU_SRC_FORMAT_ANA_YB; break;
- case ST_V_SRC_SEPARATE_FRAMES: aLngId = MENU_SRC_FORMAT_SEPARATE; break;
- default:
- case ST_V_SRC_AUTODETECT: aLngId = MENU_SRC_FORMAT_AUTO; break;
+ if(!myImage->params.stereoFile.isNull()
+ && myImage->params.swapLR->getValue()) {
+ aSrcFormat = st::formatReversed(aSrcFormat);
}
- myDescr->setText(tr(BTN_SRC_FORMAT) + tr(aLngId));
+ myDescr->setText(tr(BTN_SRC_FORMAT) + "\n" + trSrcFormat(aSrcFormat));
} else {
myDescr->setVisibility(false, true);
}
@@ -718,15 +804,15 @@
anAboutText = StString() + "Plugin '" + myPlugin->getMainWindow()->getRendererId() + "' doesn't provide description";
}
- StGLMessageBox* aDialog = new StGLMessageBox(this, anAboutText, scale(512), scale(300));
- aDialog->addButton("Close");
+ StGLMessageBox* aDialog = new StGLMessageBox(this, "", anAboutText, scale(512), scale(300));
+ aDialog->addButton(tr(BUTTON_CLOSE));
aDialog->setVisibility(true, true);
aDialog->stglInit();
}
void StImageViewerGUI::showUpdatesNotify() {
- StGLMessageBox* aDialog = new StGLMessageBox(this, tr(UPDATES_NOTIFY));
- aDialog->addButton("Close");
+ StGLMessageBox* aDialog = new StGLMessageBox(this, "", tr(UPDATES_NOTIFY));
+ aDialog->addButton(tr(BUTTON_CLOSE));
aDialog->setVisibility(true, true);
aDialog->stglInit();
}
diff -Nru sview-13.10/StImageViewer/StImageViewerGUI.h sview-14.01/StImageViewer/StImageViewerGUI.h
--- sview-13.10/StImageViewer/StImageViewerGUI.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageViewerGUI.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StImageViewer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
#ifndef __StImageViewerGUI_h_
#define __StImageViewerGUI_h_
-#include
+#include
#include
#include
#include
@@ -38,6 +38,29 @@
class StWindow;
/**
+ * Customized message box.
+ */
+class ST_LOCAL StInfoDialog : public StGLMessageBox {
+
+ public:
+
+ ST_LOCAL StInfoDialog(StImageViewer* thePlugin,
+ StGLWidget* theParent,
+ const StString& theTitle,
+ const int theWidth,
+ const int theHeight)
+ : StGLMessageBox(theParent, theTitle, "", theWidth, theHeight),
+ myPlugin(thePlugin) {}
+
+ ST_LOCAL virtual ~StInfoDialog();
+
+ private:
+
+ StImageViewer* myPlugin;
+
+};
+
+/**
* Root GUI widget for Image Viewer plugin.
*/
class StImageViewerGUI : public StGLRootWidget {
@@ -79,6 +102,8 @@
ST_LOCAL void doAboutImage(const size_t );
+ ST_LOCAL static size_t trSrcFormatId(const StFormatEnum theSrcFormat);
+
private:
ST_LOCAL void createUpperToolbar();
@@ -87,6 +112,10 @@
return myLangMap->getValue(theId);
}
+ ST_LOCAL const StString& trSrcFormat(const StFormatEnum theSrcFormat) const {
+ return tr(trSrcFormatId(theSrcFormat));
+ }
+
private: //! @name menus creation routines
ST_LOCAL void createMainMenu(); // Root (Main menu)
@@ -136,6 +165,7 @@
StGLTextureButton* myBtnNext;
StGLTextureButton* myBtnSwapLR;
StGLWidget* myBtnSrcFrmt;
+ StGLTextureButton* myBtnPlayList;
StGLTextureButton* myBtnFull;
StGLFpsLabel* myFpsWidget;
diff -Nru sview-13.10/StImageViewer/StImageViewerStrings.cpp sview-14.01/StImageViewer/StImageViewerStrings.cpp
--- sview-13.10/StImageViewer/StImageViewerStrings.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageViewerStrings.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2013 Kirill Gavrilov
+ * Copyright © 2013-2014 Kirill Gavrilov
*
* StImageViewer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -23,6 +23,14 @@
namespace StImageViewerStrings {
void loadDefaults(StLangMap& theStrings) {
+ theStrings(BUTTON_CLOSE,
+ "Close");
+ theStrings(BUTTON_CANCEL,
+ "Cancel");
+ theStrings(BUTTON_SAVE_METADATA,
+ "Save");
+ theStrings(BUTTON_DELETE,
+ "Delete");
theStrings(MENU_MEDIA,
"Media");
theStrings(MENU_VIEW,
@@ -35,6 +43,8 @@
"Save Image As...");
theStrings(MENU_MEDIA_SRC_FORMAT,
"Source stereo format");
+ theStrings(MENU_MEDIA_FILE_INFO,
+ "File info");
theStrings(MENU_MEDIA_QUIT,
"Quit");
theStrings(MENU_MEDIA_OPEN_IMAGE_1,
@@ -124,11 +134,13 @@
theStrings(ABOUT_VERSION,
"version");
theStrings(ABOUT_DESCRIPTION,
- "Image viewer allows you to open stereoscopic images in formats JPEG, PNG, MPO and a lot of others.\n"
- "(C) 2007-2013 Kirill Gavrilov \n"
+ "Image viewer allows you to open stereoscopic images in formats JPEG, PNG, MPO and others.\n"
+ "(C) 2007-2014 Kirill Gavrilov \n"
"Official site: www.sview.ru\n"
"\n"
"This program distributed under GPL3.0");
+ theStrings(ABOUT_SYSTEM,
+ "System Info");
theStrings(MENU_HELP_ABOUT,
"About...");
theStrings(MENU_HELP_USERTIPS,
@@ -167,11 +179,13 @@
"Previous image");
theStrings(IMAGE_NEXT,
"Next image");
+ theStrings(PLAYLIST,
+ "PlayList");
theStrings(FULLSCREEN,
"Switch\n"
"fullscreen/windowed");
theStrings(BTN_SRC_FORMAT,
- "Source format:\n");
+ "Source format:");
theStrings(UPDATES_NOTIFY,
"A new version of sView is available on the official site www.sview.ru.\n"
"Please update your program.");
@@ -181,12 +195,69 @@
"Choose LEFT image file to open");
theStrings(DIALOG_OPEN_RIGHT,
"Choose RIGHT image file to open");
+ theStrings(DIALOG_FILE_INFO,
+ "Image Info");
+ theStrings(DIALOG_FILE_NOINFO,
+ "Information is unavailable");
+ theStrings(DIALOG_DELETE_FILE_TITLE,
+ "File deletion");
+ theStrings(DIALOG_DELETE_FILE_QUESTION,
+ "Do you really want to completely remove this file?");
+ theStrings(DIALOG_SAVE_INFO_TITLE,
+ "File metadata saving");
+ theStrings(DIALOG_SAVE_INFO_QUESTION,
+ "Do you really want to save metadata to the file?");
+ theStrings(DIALOG_SAVE_INFO_UNSUPPORTED,
+ "Metadata can be saved only into JPEG files.");
theStrings(DIALOG_NOTHING_TO_SAVE,
"Nothing to save!");
theStrings(DIALOG_NO_SNAPSHOT,
"Snapshot not available!");
theStrings(DIALOG_SAVE_SNAPSHOT,
"Choose location to save snapshot");
+
+ theStrings(INFO_LEFT,
+ "[left]");
+ theStrings(INFO_RIGHT,
+ "[right]");
+ theStrings(INFO_FILE_NAME,
+ "File name");
+ theStrings(INFO_DIMENSIONS,
+ "Dimensions");
+ theStrings(INFO_LOAD_TIME,
+ "Load time");
+ theStrings(INFO_TIME_MSEC,
+ "msec");
+ theStrings(INFO_PIXEL_RATIO,
+ "Pixel ratio");
+ theStrings(INFO_COLOR_MODEL,
+ "Color model");
+ theStrings(INFO_NO_SRCFORMAT,
+ "(does not stored in metadata)");
+ theStrings(INFO_WRONG_SRCFORMAT,
+ "(does not match metadata)");
+
+ theStrings(METADATA_JPEG_COMMENT,
+ "JPEG comment");
+ theStrings(METADATA_JPEG_JPSCOMMENT,
+ "JPS comment");
+
+ theStrings(METADATA_EXIF_MAKER,
+ "Camera maker");
+ theStrings(METADATA_EXIF_MODEL,
+ "Camera model");
+ theStrings(METADATA_EXIF_USERCOMMENT,
+ "User comment");
+ theStrings(METADATA_EXIF_DATETIME,
+ "Image timestamp");
+
+ // define metadata keys
+ theStrings.addAlias("Jpeg.Comment", METADATA_JPEG_COMMENT);
+ theStrings.addAlias("Jpeg.JpsComment", METADATA_JPEG_JPSCOMMENT);
+ theStrings.addAlias("Exif.Image.Make", METADATA_EXIF_MAKER);
+ theStrings.addAlias("Exif.Image.Model", METADATA_EXIF_MODEL);
+ theStrings.addAlias("Exif.UserComment", METADATA_EXIF_USERCOMMENT);
+ theStrings.addAlias("Exif.Image.DateTime", METADATA_EXIF_DATETIME);
}
};
diff -Nru sview-13.10/StImageViewer/StImageViewerStrings.h sview-14.01/StImageViewer/StImageViewerStrings.h
--- sview-13.10/StImageViewer/StImageViewerStrings.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/StImageViewerStrings.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StImageViewer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,7 +19,7 @@
#ifndef __StImageViewerStrings_h_
#define __StImageViewerStrings_h_
-#include
+#include
class StLangMap;
@@ -33,6 +33,7 @@
SWAP_LR_ON = 1003,
BTN_SRC_FORMAT = 1004,
IMAGE_OPEN = 1015,
+ PLAYLIST = 1028,
FULLSCREEN = 1029,
// Root -> Media menu
@@ -40,6 +41,7 @@
MENU_MEDIA_OPEN_IMAGE = 1101,
MENU_MEDIA_SAVE_IMAGE_AS = 1102,
MENU_MEDIA_SRC_FORMAT = 1103,
+ MENU_MEDIA_FILE_INFO = 1104,
MENU_MEDIA_QUIT = 1109,
// Root -> Media menu -> Open File menu
@@ -123,6 +125,13 @@
DIALOG_OPEN_FILE = 2000,
DIALOG_OPEN_LEFT = 2001,
DIALOG_OPEN_RIGHT = 2002,
+ DIALOG_FILE_INFO = 2003,
+ DIALOG_FILE_NOINFO = 2004,
+ DIALOG_DELETE_FILE_TITLE = 2005,
+ DIALOG_DELETE_FILE_QUESTION = 2006,
+ DIALOG_SAVE_INFO_TITLE = 2007,
+ DIALOG_SAVE_INFO_QUESTION = 2008,
+ DIALOG_SAVE_INFO_UNSUPPORTED = 2009,
DIALOG_SAVE_SNAPSHOT = 2010,
DIALOG_NOTHING_TO_SAVE = 2011,
@@ -133,6 +142,32 @@
ABOUT_VERSION = 3001,
ABOUT_DESCRIPTION = 3002,
UPDATES_NOTIFY = 3003,
+ ABOUT_SYSTEM = 3004,
+
+ BUTTON_CLOSE = 4000,
+ BUTTON_CANCEL = 4001,
+ BUTTON_SAVE_METADATA = 4006,
+ BUTTON_DELETE = 4007,
+
+ // metadata keys
+ INFO_LEFT = 5000,
+ INFO_RIGHT = 5001,
+ INFO_FILE_NAME = 5002,
+ INFO_DIMENSIONS = 5003,
+ INFO_LOAD_TIME = 5004,
+ INFO_TIME_MSEC = 5005,
+ INFO_PIXEL_RATIO = 5006,
+ INFO_COLOR_MODEL = 5007,
+ INFO_NO_SRCFORMAT = 5008,
+ INFO_WRONG_SRCFORMAT = 5009,
+
+ // metadata keys
+ METADATA_JPEG_COMMENT = 5100,
+ METADATA_JPEG_JPSCOMMENT = 5101,
+ METADATA_EXIF_MAKER = 5200,
+ METADATA_EXIF_MODEL = 5201,
+ METADATA_EXIF_USERCOMMENT = 5202,
+ METADATA_EXIF_DATETIME = 5203,
};
diff -Nru sview-13.10/StImageViewer/lang/english/StImageViewer.lng sview-14.01/StImageViewer/lang/english/StImageViewer.lng
--- sview-13.10/StImageViewer/lang/english/StImageViewer.lng 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/lang/english/StImageViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -6,13 +6,15 @@
1001="Next image"
1002="Swap Left/Right"
1003="UnSwap Left/Right"
-1004="Source format:\n"
+1004="Stereoscopic format:"
1015="Open another image"
+1028="Show/Hide playlist"
1029="Switch\nfullscreen/windowed"
1100="Media"
1101="Open Image..."
1102="Save Image As..."
-1103="Source stereo format"
+1103="Stereoscopic format"
+1104="Image info"
1109="Quit"
1110="From One file"
1111="Left+Right files"
@@ -63,7 +65,7 @@
1504="Language"
1506="User tips"
1508="About system"
-1509="Scale Interface"
+1509="Interface Scale"
1520="Now"
1521="Each day"
1522="Each week"
@@ -75,11 +77,39 @@
1593="Force HiDPI 2X"
2000="Choose the image file to open"
2001="Choose LEFT image file to open"
-2001="Choose RIGHT image file to open"
+2002="Choose RIGHT image file to open"
+2003="Image Info"
+2004="Information is unavailable"
+2005="File deletion"
+2006="Do you really want to completely remove this file?"
+2007="File metadata saving"
+2008="Do you really want to save metadata to the file?"
+2009="Metadata can be saved only into JPEG files."
2010="Choose location to save snapshot"
2011="Nothing to save!"
2012="Snapshot not available!"
3000="sView - Image Viewer"
3001="version"
-3002="Image viewer allows you to open stereoscopic images in formats JPEG, PNG, MPO and a lot of others.\n © 2007-2013 Kirill Gavrilov \nOfficial site: www.sview.ru\n\nThis program distributed under GPL3.0"
+3002="Image viewer allows you to open stereoscopic images in formats JPEG, PNG, MPO and a lot of others.\n © 2007-2014 Kirill Gavrilov \nOfficial site: www.sview.ru\n\nThis program distributed under GPL3.0"
3003="A new version of sView is available on the official site www.sview.ru.\nPlease update your program."
+3004="System Info"
+4000="Close"
+4001="Cancel"
+4006="Save"
+4007="Delete"
+5000="[left]"
+5001="[right]"
+5002="File name"
+5003="Dimensions"
+5004="Load time"
+5005="ms"
+5006="Pixel ratio"
+5007="Color model"
+5008="(does not stored in metadata)"
+5009="(does not match metadata)"
+5100="JPEG Comment"
+5101="JPS Comment"
+5200="Camera Maker"
+5201="Camera Model"
+5202="User Comment"
+5203="Image timestamp"
diff -Nru sview-13.10/StImageViewer/lang/french/StImageViewer.lng sview-14.01/StImageViewer/lang/french/StImageViewer.lng
--- sview-13.10/StImageViewer/lang/french/StImageViewer.lng 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/lang/french/StImageViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -6,13 +6,15 @@
1001="Image Suivante"
1002="Gauche/Droite inversé"
1003="Gauche/Droite normal"
-1004="Format entrée:\n"
+1004="Format entrée:"
1015="Ouvre autre image"
+1028="Affiche/Masque playlist"
1029="Bascule\Plein écran/fenêtre"
1100="Media"
1101="Ouvre Image..."
1102="Enregistre Image Sous.."
1103="Format Stéréo d'entrée"
+1104="Image info"
1109="Quitter"
1110="Depuis un fichier"
1111="2 Fichiers Gauche+Droit"
@@ -75,11 +77,39 @@
1593="Force HiDPI 2X"
2000="Choix du fichier image à ouvrir"
2001="Choix du fichier image Gauche à ouvrir"
-2001="Choix du fichier image Droite à ouvrir"
+2002="Choix du fichier image Droite à ouvrir"
+2003="Info de l'image"
+2004="Information is unavailable"
+2005="File deletion"
+2006="Do you really want to completely remove this file?"
+2007="File metadata saving"
+2008="Do you really want to save metadata to the file?"
+2009="Metadata can be saved only into JPEG files."
2010="Emplacement de la capture écran"
2011="Rien à enregistrer!"
2012="Capture non disponible!"
3000="sView - Image Viewer"
3001="version"
-3002="Image viewer vous permet d'ouvrir des images stéréoscopiques en formats JPEG, PNG, MPO.\n © 2007-2013 Kirill Gavrilov \nSite Officiel: www.sview.ru\n\nThis program distributed under GPL3.0"
+3002="Image viewer vous permet d'ouvrir des images stéréoscopiques en formats JPEG, PNG, MPO.\n © 2007-2014 Kirill Gavrilov \nSite Officiel: www.sview.ru\n\nThis program distributed under GPL3.0"
3003="Une nouvelle version de sView est disponible sur le site officiel www.sview.ru.\nSVP, mettez votre programme à jour."
+3004="System Info"
+4000="Fermer"
+4001="Cancel"
+4006="Enregistre"
+4007="Delete"
+5000="[left]"
+5001="[right]"
+5002="Nom de fichier"
+5003="Résolution"
+5004="Load time"
+5005="ms"
+5006="Pixel ratio"
+5007="Color model"
+5008="(does not stored in metadata)"
+5009="(does not match metadata)"
+5100="JPEG commentaire"
+5101="JPS commentaire"
+5200="Camera Maker"
+5201="Camera Model"
+5202="User Comment"
+5203="Image timestamp"
diff -Nru sview-13.10/StImageViewer/lang/german/StImageViewer.lng sview-14.01/StImageViewer/lang/german/StImageViewer.lng
--- sview-13.10/StImageViewer/lang/german/StImageViewer.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StImageViewer/lang/german/StImageViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1,115 @@
+German translation file for StImageViewer program
+@author Kirill Gavrilov
+
+--------
+1000="Vorheriges Bild"
+1001="Nachstes Bild"
+1002="L&R Vertauschen An"
+1003="L&R Vertauschen Aus"
+1004="Quellformat:"
+1015="Öffnen anderen Bild"
+1028="Anzeigen/ausblenden Wiedergabeliste"
+1029="Vollbildmodus/Fenstermodus"
+1100="Medien"
+1101="Bild öffnen..."
+1102="Bild speichern als..."
+1103="Quelle Stereo-Format"
+1104="Bildinfo"
+1109="Beenden"
+1110="Einer Datei"
+1111="Zwei Dateien"
+1130="Autoerkennung"
+1131="Mono"
+1132="Schielend"
+1133="Parallel Pair"
+1134="Over/Under (R/L)"
+1135="Over/Under (L/R)"
+1136="Interlaced"
+1137="Anaglyph Rot/Cyan"
+1138="Anaglyph Grün/Rot+Blau"
+1139="Anaglyph Gelb/Blau"
+1142="2 Streams"
+1200="Ansicht"
+1201="Stereo-Ausgang"
+1202="Vollbild"
+1203="Zurückstellen"
+1204="L&R Vertauschen"
+1205="Seitenverhältnis"
+1206="Glatte Filter"
+1207="Bildeinstellung"
+1208="Oberfläche"
+1210="Stereo"
+1211="Linke Bild"
+1212="Rechte Bild"
+1213="Parallel Pair"
+1214="Cross-eyed"
+1250="Quelle"
+1251="Halten beim Neustart"
+1260="Nearest"
+1261="Linear"
+1270="Auf Standardwerte zurücksetzen"
+1271="Helligkeit"
+1272="Sättigung"
+1273="Gamma"
+1280="Fläche"
+1281="Kugel"
+1282="Zylinder"
+1400="Gerät ändern"
+1401="Über Plugin..."
+1402="FPS anzeigen"
+1403="VSync"
+1500="Hilfe"
+1501="Über..."
+1502="Nach Updates suchen"
+1503="Lizenztext"
+1504="Language"
+1506="Anwendertipps"
+1508="Über System"
+1509="Maßstab Benutzeroberfläche"
+1520="jetzt"
+1521="täglich"
+1522="wöchentlich"
+1523="jährlich"
+1524="nie"
+1590="klein"
+1591="normal"
+1592="groß"
+1593="erzwingen HiDPI 2X"
+2000="Wählen die Bilddatei zu öffnen"
+2001="Wählen die linke Bilddatei zu öffnen"
+2002="Wählen die rechte Bilddatei zu öffnen"
+2003="Bildinfo"
+2004="Information is unavailable"
+2005="Löschen von Dateien"
+2006="Do you really want to completely remove this file?"
+2007="File metadata saving"
+2008="Do you really want to save metadata to the file?"
+2009="Metadata can be saved only into JPEG files."
+2010="Wählen einen Speicherort für Schnappschuss"
+2011="Nichts zu speichern!"
+2012="Schnappschuss ist nicht verfügbar!"
+3000="sView - Image Viewer"
+3001="Version"
+3002="Image viewer allows you to open stereoscopic images in formats JPEG, PNG, MPO and a lot of others.\n © 2007-2014 Kirill Gavrilov \nOfficial site: www.sview.ru\n\nThis program distributed under GPL3.0"
+3003="A new version of sView is available on the official site www.sview.ru.\nPlease update your program."
+3004="System Info"
+4000="Schließen"
+4001="Cancel"
+4006="Speichern"
+4007="Delete"
+5000="[linke]"
+5001="[rechte]"
+5002="Dateiname"
+5003="Auflösung"
+5004="Ladezeit"
+5005="ms"
+5006="Pixel ratio"
+5007="Color model"
+5008="(does not stored in metadata)"
+5009="(does not match metadata)"
+5100="JPEG Kommentar"
+5101="JPS Kommentar"
+5200="Camera Maker"
+5201="Camera Model"
+5202="User Kommentar"
+5203="Image timestamp"
diff -Nru sview-13.10/StImageViewer/lang/korean/StImageViewer.lng sview-14.01/StImageViewer/lang/korean/StImageViewer.lng
--- sview-13.10/StImageViewer/lang/korean/StImageViewer.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StImageViewer/lang/korean/StImageViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1,116 @@
+Korean translation file for StImageViewer program
+@author Kirill Gavrilov
+@translator Kwon Daesuk
+
+--------
+1000="앞 이미지"
+1001="다음 이미지"
+1002="좌/우 변경"
+1003="좌/우 복원"
+1004="소스 포맷:"
+1015="다른 이미지 열기"
+1028="재생 목록 보이기/감추기"
+1029="전환\n전체화면/윈도화면"
+1100="미디어"
+1101="이미지 열기..."
+1102="다른 이름으로 저장..."
+1103="입력 스테레오 형식"
+1104="Image info"
+1109="나가기"
+1110="한 파일에서 열기"
+1111="좌+우 파일들에서 열기"
+1130="자동감지"
+1131="모노"
+1132="크로스-아이"
+1133="패럴렐 페어"
+1134="상/하(R/L)"
+1135="상/하(L/R)"
+1136="Interlaced"
+1137="Anaglyph Red/Cyan"
+1138="Anaglyph Green/Red+Blue"
+1139="Anaglyph Yellow/Blue"
+1142="2 Streams"
+1200="View"
+1201="입체 출력"
+1202="전체 화면"
+1203="리셋"
+1204="좌/우 변경"
+1205="화면 비율"
+1206="Smooth Filter"
+1207="이미지 보정"
+1208="Surface"
+1210="Stereo"
+1211="Left View"
+1212="Right View"
+1213="패럴렐 페어"
+1214="크로스-아이"
+1250="Source"
+1251="재시작시 유지"
+1260="Nearest"
+1261="Linear"
+1270="기본값으로 리셋"
+1271="밝기"
+1272="Saturation"
+1273="감마"
+1280="Plane"
+1281="Sphere"
+1282="Cylinder"
+1400="장치 변경"
+1401="About Plugin..."
+1402="Show FPS"
+1403="VSync"
+1500="도움말"
+1501="이 프로그램에 대해..."
+1502="업데이트 확인"
+1503="라이선스 문서"
+1504="언어 (Language)"
+1506="사용자 팁"
+1508="About system"
+1509="Interface Scale"
+1520="지금"
+1521="매일Each day"
+1522="매주Each week"
+1523="매년Each year"
+1524="하지 않음Never"
+1590="작게 Small"
+1591="보통Normal"
+1592="크게 Big"
+1593="HiDPI 2X로"
+2000="열어볼 이미지 파일 선택"
+2001="왼쪽 이미지 선택"
+2002="오른쪽 이미지 선택"
+2003="Image Info"
+2004="Information is unavailable"
+2005="File deletion"
+2006="Do you really want to completely remove this file?"
+2007="File metadata saving"
+2008="Do you really want to save metadata to the file?"
+2009="Metadata can be saved only into JPEG files."
+2010="스냅샷 저장 위치 선택"
+2011="저장할 수 없음!"
+2012="스냅샷이 없음!"
+3000="sView - 이미지 뷰어"
+3001="version"
+3002="이 이미지 뷰어로 JPEG, PNG, MPO 외 다양한 양식의 스테레오 이미지를 볼 수 있습니다.\n © 2007-2014 Kirill Gavrilov \n 공식 사이트: www.sview.ru\n\n이 프로그램은 GPL3.0 하에 배포됩니다."
+3003="sView 최신 버전은 공식 사이트 www.sview.ru에서 구할 수 있습니다.\n프로그램을 업데이트하세요."
+3004="System Info"
+4000="닫기"
+4001="Cancel"
+4006="Save"
+4007="Delete"
+5000="[left]"
+5001="[right]"
+5002="File name"
+5003="Dimensions"
+5004="Load time"
+5005="ms"
+5006="Pixel ratio"
+5007="Color model"
+5008="(does not stored in metadata)"
+5009="(does not match metadata)"
+5100="JPEG Comment"
+5101="JPS Comment"
+5200="Camera Maker"
+5201="Camera Model"
+5202="User Comment"
+5203="Image timestamp"
diff -Nru sview-13.10/StImageViewer/lang/korean/language.lng sview-14.01/StImageViewer/lang/korean/language.lng
--- sview-13.10/StImageViewer/lang/korean/language.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StImageViewer/lang/korean/language.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1 @@
+한국어
\ No newline at end of file
diff -Nru sview-13.10/StImageViewer/lang/russian/StImageViewer.lng sview-14.01/StImageViewer/lang/russian/StImageViewer.lng
--- sview-13.10/StImageViewer/lang/russian/StImageViewer.lng 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StImageViewer/lang/russian/StImageViewer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -6,13 +6,15 @@
1001="Следующая картинка"
1002="Поменять ракурсы местами"
1003="Отключить реверс ракурсов"
-1004="Исходный формат:\n"
+1004="Исходный стереоформат:"
1015="Открыть изображение"
+1028="Отобразить/Скрыть\nсписок файлов"
1029="Оконный/Полноэкранный\nрежим просмотра"
1100="Медиа"
1101="Открыть изображение..."
1102="Сохранить как..."
1103="Исходный стереоформат"
+1104="Информация о файле"
1109="Выход"
1110="Из одного файла"
1111="Левый+Правый файлы"
@@ -75,11 +77,39 @@
1593="Форсировать HiDPI 2X"
2000="Выберите картинку"
2001="Выберите файл с ЛЕВЫМ ракурсом"
-2001="Выберите файл с ПРАВЫМ ракурсом"
+2002="Выберите файл с ПРАВЫМ ракурсом"
+2003="Информация о файле"
+2004="Информация не доступна"
+2005="Удаление файла"
+2006="Вы действительно хотите\nудалить файл минуя корзину?"
+2007="Сохранение метаданных"
+2008="Вы действительно хотите\nсохранить метаданные в файл?"
+2009="Сохранение метаданных доступно только для файлов JPEG."
2010="Выберите путь для сохранения картинки"
2011="Ничего не открыто!"
2012="Изображение недоступно для сохранения!"
3000="sView - программа для просмотра изображений"
3001="версия"
-3002="Программа отображает стереоскопические изображения в форматах JPEG, PNG, MPO.\n © 2007-2013 Гаврилов Кирилл \nОфициальный сайт: www.sview.ru\n\nПрограмма распространяется на условиях GPL3.0"
+3002="Программа отображает стереоскопические изображения в форматах JPEG, PNG, MPO.\n © 2007-2014 Гаврилов Кирилл \nОфициальный сайт: www.sview.ru\n\nПрограмма распространяется на условиях GPL3.0"
3003="Доступно обновление программы.\nВы можете загрузить новую версию с официального сайта www.sview.ru."
+3004="Информация о системе"
+4000="Закрыть"
+4001="Отменить"
+4006="Сохранить"
+4007="Удалить"
+5000="[левый]"
+5001="[правый]"
+5002="Имя файла"
+5003="Разрешение"
+5004="Время загрузки"
+5005="мс"
+5006="Пропорции пикселя"
+5007="Color model"
+5008="(информация отсутствует в метаданных)"
+5009="(не соответствует метаданным)"
+5100="JPEG комментарий"
+5101="JPS комментарий"
+5200="Производитель камеры"
+5201="Модель камеры"
+5202="Комментарий"
+5203="Дата создания"
diff -Nru sview-13.10/StMoviePlayer/StMoviePlayer.cbp sview-14.01/StMoviePlayer/StMoviePlayer.cbp
--- sview-13.10/StMoviePlayer/StMoviePlayer.cbp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StMoviePlayer.cbp 2014-01-30 10:45:03.000000000 +0000
@@ -37,14 +37,7 @@
-
-
-
-
-
-
-
-
+
@@ -80,14 +73,7 @@
-
-
-
-
-
-
-
-
+
@@ -129,14 +115,7 @@
-
-
-
-
-
-
-
-
+
@@ -173,14 +152,7 @@
-
-
-
-
-
-
-
-
+
@@ -214,14 +186,7 @@
-
-
-
-
-
-
-
-
+
@@ -253,14 +218,7 @@
-
-
-
-
-
-
-
-
+
@@ -287,14 +245,7 @@
-
-
-
-
-
-
-
-
+
@@ -322,14 +273,7 @@
-
-
-
-
-
-
-
-
+
@@ -406,9 +350,18 @@
+
+
+
+
+
+
+
+
+
diff -Nru sview-13.10/StMoviePlayer/StMoviePlayer.cpp sview-14.01/StMoviePlayer/StMoviePlayer.cpp
--- sview-13.10/StMoviePlayer/StMoviePlayer.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StMoviePlayer.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -29,7 +29,9 @@
#include
#include
+#include
#include
+#include
#include
#include
#include
@@ -69,6 +71,8 @@
static const char ST_SETTING_SCALE_FORCE2X[] = "scale2X";
static const char ST_SETTING_SUBTITLES_SIZE[]= "subsSize";
static const char ST_SETTING_SUBTITLES_PARALLAX[] = "subsParallax";
+ static const char ST_SETTING_SUBTITLES_PARSER[] = "subsParser";
+ static const char ST_SETTING_SEARCH_SUBS[] = "toSearchSubs";
static const char ST_SETTING_FULLSCREEN[] = "fullscreen";
static const char ST_SETTING_VIEWMODE[] = "viewMode";
static const char ST_SETTING_STEREO_MODE[] = "viewStereoMode";
@@ -168,6 +172,8 @@
myEventDialog(false),
myEventLoaded(false),
mySeekOnLoad(-1.0),
+ myAudioOnLoad(-1),
+ mySubsOnLoad(-1),
//
myWebCtx(NULL),
//
@@ -200,6 +206,10 @@
0.0f, // default value
1.0f, // incremental step
0.1f); // equality tolerance
+ params.ToSearchSubs = new StBoolParam(true);
+ params.SubtitlesParser = new StEnumParam(1, tr(MENU_SUBTITLES_PARSER));
+ params.SubtitlesParser->changeValues().add(tr(MENU_SUBTITLES_PLAIN_TEXT));
+ params.SubtitlesParser->changeValues().add(tr(MENU_SUBTITLES_LITE_HTML));
params.alDevice = new StALDeviceParam();
params.AudioGain = new StFloat32Param( 0.0f, // sound is unattenuated
@@ -257,6 +267,8 @@
mySettings->loadParam (ST_SETTING_SHOW_LIST, params.ToShowPlayList);
mySettings->loadParam (ST_SETTING_SUBTITLES_SIZE, params.SubtitlesSize);
mySettings->loadParam (ST_SETTING_SUBTITLES_PARALLAX, params.SubtitlesParallax);
+ mySettings->loadParam (ST_SETTING_SUBTITLES_PARSER, params.SubtitlesParser);
+ mySettings->loadParam (ST_SETTING_SEARCH_SUBS, params.ToSearchSubs);
mySettings->loadParam (ST_SETTING_SHOW_FPS, params.ToShowFps);
mySettings->loadParam (ST_SETTING_VSYNC, params.IsVSyncOn);
@@ -322,6 +334,9 @@
anAction = new StActionIntValue(stCString("DoSrcSideBySide"), params.srcFormat, ST_V_SRC_SIDE_BY_SIDE);
addAction(Action_SrcSideBySideRL, anAction, ST_VK_S);
+ anAction = new StActionIntSlot(stCString("DoFileInfo"), stSlot(this, &StMoviePlayer::doAboutFile), 0);
+ addAction(Action_FileInfo, anAction, ST_VK_I);
+
anAction = new StActionIntSlot(stCString("DoListFirst"), stSlot(this, &StMoviePlayer::doListFirst), 0);
addAction(Action_ListFirst, anAction, ST_VK_HOME);
@@ -358,9 +373,18 @@
anAction = new StActionIntSlot(stCString("DoSnapshot"), stSlot(this, &StMoviePlayer::doSnapshot), StImageFile::ST_TYPE_NONE);
addAction(Action_SaveSnapshot, anAction, ST_VK_S | ST_VF_CONTROL);
+ anAction = new StActionIntSlot(stCString("DoDeleteFile"), stSlot(this, &StMoviePlayer::doDeleteFileBegin), 0);
+ addAction(Action_DeleteFile, anAction, ST_VK_DELETE | ST_VF_SHIFT);
+
anAction = new StActionBool(stCString("DoAudioMute"), params.AudioMute);
addAction(Action_AudioMute, anAction);
+ anAction = new StActionIntSlot(stCString("DoAudioDecrease"), stSlot(this, &StMoviePlayer::doAudioVolume), (size_t )-1);
+ addAction(Action_AudioDecrease, anAction, ST_VK_DOWN);
+
+ anAction = new StActionIntSlot(stCString("DoAudioIncrease"), stSlot(this, &StMoviePlayer::doAudioVolume), 1);
+ addAction(Action_AudioIncrease, anAction, ST_VK_UP);
+
anAction = new StActionIntSlot(stCString("DoAudioNext"), stSlot(this, &StMoviePlayer::doAudioNext), 1);
addAction(Action_AudioNext, anAction, ST_VK_H, ST_VK_L);
@@ -373,6 +397,9 @@
anAction = new StActionIntSlot(stCString("DoSubtitlesPrev"), stSlot(this, &StMoviePlayer::doSubtitlesNext), (size_t )-1);
addAction(Action_SubsPrev, anAction, ST_VK_U | ST_VF_SHIFT, ST_VK_T | ST_VF_SHIFT);
+ anAction = new StActionIntSlot(stCString("DoSubtitlesCopy"), stSlot(this, &StMoviePlayer::doSubtitlesCopy), 0);
+ addAction(Action_CopyToClipboard, anAction, ST_VK_C | ST_VF_CONTROL, ST_VK_INSERT | ST_VF_CONTROL);
+
anAction = new StActionIntSlot(stCString("DoPlayListReverse"), stSlot(this, &StMoviePlayer::doPlayListReverse), 0);
addAction(Action_ShowList, anAction, ST_VK_L | ST_VF_CONTROL);
@@ -417,6 +444,8 @@
mySettings->saveParam (ST_SETTING_SCALE_FORCE2X, params.ScaleHiDPI2X);
mySettings->saveParam (ST_SETTING_SUBTITLES_SIZE, params.SubtitlesSize);
mySettings->saveParam (ST_SETTING_SUBTITLES_PARALLAX, params.SubtitlesParallax);
+ mySettings->saveParam (ST_SETTING_SUBTITLES_PARSER, params.SubtitlesParser);
+ mySettings->saveParam (ST_SETTING_SEARCH_SUBS, params.ToSearchSubs);
mySettings->saveInt32 (ST_SETTING_FPSTARGET, params.TargetFps);
mySettings->saveString(ST_SETTING_OPENAL_DEVICE, params.alDevice->getTitle());
mySettings->saveInt32 (ST_SETTING_UPDATES_LAST_CHECK, myLastUpdateDay);
@@ -518,6 +547,40 @@
myGUI->myImage->params.saturation->reset();
}
+
+void StMoviePlayer::doDeleteFileBegin(const size_t ) {
+ //if(!myFileToDelete.isNull()) {
+ // return;
+ //}
+
+ myFileToDelete = myVideo->getPlayList().getCurrentFile();
+ if(myFileToDelete.isNull()
+ || myFileToDelete->size() != 0) {
+ myFileToDelete.nullify();
+ return;
+ }
+
+ const StString aText = myLangMap->getValue(StMoviePlayerStrings::DIALOG_DELETE_FILE_QUESTION)
+ + "\n" + myFileToDelete->getPath();
+
+ StGLMessageBox* aDialog = new StGLMessageBox(myGUI.access(), myLangMap->getValue(StMoviePlayerStrings::DIALOG_DELETE_FILE_TITLE),
+ aText, myGUI->scale(512), myGUI->scale(256));
+ aDialog->addButton(myLangMap->getValue(StMoviePlayerStrings::BUTTON_DELETE), true)->signals.onBtnClick += stSlot(this, &StMoviePlayer::doDeleteFileEnd);
+ aDialog->addButton(myLangMap->getValue(StMoviePlayerStrings::BUTTON_CANCEL), false);
+ aDialog->setVisibility(true, true);
+ aDialog->stglInit();
+}
+
+void StMoviePlayer::doDeleteFileEnd(const size_t ) {
+ if(myFileToDelete.isNull()
+ || myVideo.isNull()) {
+ return;
+ }
+
+ myVideo->doRemovePhysically(myFileToDelete);
+ myFileToDelete.nullify();
+}
+
void StMoviePlayer::doStopWebUI() {
#ifdef ST_HAVE_MONGOOSE
if(myWebCtx != NULL) {
@@ -607,7 +670,8 @@
myVideo = new StVideo(params.alDevice->getTitle(), myLangMap, myPlayList, aTextureQueue, aSubQueue);
myVideo->signals.onError = stSlot(myMsgQueue.access(), &StMsgQueue::doPushError);
myVideo->signals.onLoaded = stSlot(this, &StMoviePlayer::doLoaded);
- myVideo->params.UseGpu = params.UseGpu;
+ myVideo->params.UseGpu = params.UseGpu;
+ myVideo->params.ToSearchSubs = params.ToSearchSubs;
#ifdef ST_HAVE_MONGOOSE
doStartWebUI();
@@ -744,11 +808,6 @@
StApplication::doKeyDown(theEvent);
switch(theEvent.VKey) {
- // file walk
- case ST_VK_I:
- myGUI->doAboutFile(0);
- return;
-
// post process keys
case ST_VK_B: {
if(theEvent.Flags == ST_VF_SHIFT) {
@@ -841,6 +900,18 @@
}
}
+void StMoviePlayer::doAudioVolume(size_t theDirection) {
+ if(myVideo.isNull()) {
+ return;
+ }
+
+ if(theDirection == 1) {
+ params.AudioGain->increment();
+ } else {
+ params.AudioGain->decrement();
+ }
+}
+
void StMoviePlayer::doAudioNext(size_t theDirection) {
if(myVideo.isNull()) {
return;
@@ -859,6 +930,20 @@
params.subtitlesStream->setValue(aValue);
}
+void StMoviePlayer::doSubtitlesCopy(size_t ) {
+ if(myVideo.isNull()
+ || myGUI.isNull()
+ || myGUI->mySubtitles == NULL) {
+ return;
+ }
+
+ const StString& aText = myGUI->mySubtitles->getText();
+ if(aText.isEmpty()) {
+ return;
+ }
+ myWindow->toClipboard(aText);
+}
+
void StMoviePlayer::doFileNext() {
if(myVideo.isNull()) {
return;
@@ -1125,6 +1210,22 @@
myVideo->pushPlayEvent(ST_PLAYEVENT_SEEK, mySeekOnLoad);
mySeekOnLoad = -1.0;
}
+ if(myAudioOnLoad >= 0) {
+ myVideo->params.activeAudio->setValue(myAudioOnLoad);
+ params.audioStream->setValue(myAudioOnLoad);
+ myAudioOnLoad = -1;
+ }
+ if(mySubsOnLoad >= 0) {
+ myVideo->params.activeSubtitles->setValue(mySubsOnLoad);
+ params.subtitlesStream->setValue(mySubsOnLoad);
+ mySubsOnLoad = -1;
+ }
+}
+
+void StMoviePlayer::doAboutFile(const size_t ) {
+ if(!myGUI.isNull()) {
+ myGUI->doAboutFile(0);
+ }
}
void StMoviePlayer::doSwitchSrcFormat(const int32_t theSrcFormat) {
@@ -1216,6 +1317,15 @@
doOpenFileThreaded(this, OPEN_FILE_2MOVIES);
}
+void StMoviePlayer::doSaveFileInfo(const size_t theToSave) {
+ if(!myGUI.isNull()
+ && !myFileInfo.isNull()
+ && theToSave == 1) {
+ //myLoader->doSaveInfo(myFileInfo);
+ }
+ myFileInfo.nullify();
+}
+
void StMoviePlayer::doOpenRecent(const size_t theItemId) {
if(myVideo.isNull()) {
return;
@@ -1287,6 +1397,7 @@
myEventDialog.reset();
return;
}
+
switch(theOpenType) {
case OPEN_FILE_2MOVIES: {
aTitle = tr(DIALOG_OPEN_RIGHT);
@@ -1299,10 +1410,18 @@
}
break;
}
- case OPEN_STREAM_AUDIO:
+ case OPEN_STREAM_AUDIO: {
+ myPlayList->addToNode(aCurrFile, aFilePath);
+ myAudioOnLoad = myVideo->params.activeAudio->getListSize();
+ mySubsOnLoad = myVideo->params.activeSubtitles->getValue();
+ mySeekOnLoad = myVideo->getPts();
+ break;
+ }
case OPEN_STREAM_SUBTITLES: {
myPlayList->addToNode(aCurrFile, aFilePath);
- mySeekOnLoad = myVideo->getPts();
+ myAudioOnLoad = myVideo->params.activeAudio->getValue();
+ mySubsOnLoad = myVideo->params.activeSubtitles->getListSize();
+ mySeekOnLoad = myVideo->getPts();
break;
}
case OPEN_FILE_MOVIE:
diff -Nru sview-13.10/StMoviePlayer/StMoviePlayer.h sview-14.01/StMoviePlayer/StMoviePlayer.h
--- sview-13.10/StMoviePlayer/StMoviePlayer.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StMoviePlayer.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -158,14 +158,19 @@
ST_LOCAL void doListPrev(const size_t dummy = 0);
ST_LOCAL void doListNext(const size_t dummy = 0);
ST_LOCAL void doListLast(const size_t dummy = 0);
+ ST_LOCAL void doDeleteFileBegin(const size_t dummy = 0);
+ ST_LOCAL void doDeleteFileEnd (const size_t dummy = 0);
+ ST_LOCAL void doAudioVolume(size_t theDirection);
ST_LOCAL void doAudioNext(size_t theDirection);
ST_LOCAL void doSubtitlesNext(size_t theDirection);
+ ST_LOCAL void doSubtitlesCopy(size_t dummy = 0);
ST_LOCAL void doQuit(const size_t dummy = 0);
ST_LOCAL void doFileNext();
ST_LOCAL void doOpen1File(const size_t dummy = 0);
ST_LOCAL void doOpen2Files(const size_t dummy = 0);
+ ST_LOCAL void doSaveFileInfo(const size_t theToSave);
ST_LOCAL void doOpenRecent(const size_t theItemId);
ST_LOCAL void doClearRecent(const size_t dummy = 0);
ST_LOCAL void doUpdateOpenALDeviceList(const size_t dummy = 0);
@@ -179,6 +184,7 @@
ST_LOCAL void doReset(const size_t dummy = 0);
ST_LOCAL void doSnapshot(const size_t theImgType);
+ ST_LOCAL void doAboutFile(const size_t dummy = 0);
public: //! @name Properties
@@ -195,6 +201,8 @@
StHandle ScaleHiDPI2X; //!< option to set HiDPI resolution to 2.0
StHandle SubtitlesSize; //!< subtitles font size
StHandle SubtitlesParallax;//!< subtitles parallax
+ StHandle ToSearchSubs; //!< automatically search for additional subtitles/audio track files nearby video file
+ StHandle SubtitlesParser; //!< subtitles parser
StHandle alDevice; //!< active OpenAL device
StHandle AudioGain; //!< volume factor
StHandle AudioMute; //!< volume mute flag
@@ -304,6 +312,7 @@
Action_SrcMono,
Action_SrcOverUnderLR,
Action_SrcSideBySideRL,
+ Action_FileInfo,
Action_ListFirst,
Action_ListLast,
Action_ListPrev,
@@ -316,11 +325,15 @@
Action_SeekRight5,
Action_Open1File,
Action_SaveSnapshot,
+ Action_DeleteFile,
Action_AudioMute,
+ Action_AudioDecrease,
+ Action_AudioIncrease,
Action_AudioPrev,
Action_AudioNext,
Action_SubsPrev,
Action_SubsNext,
+ Action_CopyToClipboard,
Action_ShowList,
Action_ImageAdjustReset,
Action_StereoParamsBegin,
@@ -347,10 +360,14 @@
StHandle myGUI; //!< GUI root widget
StHandle myVideo; //!< main video playback class
StHandle myUpdates; //!< check updates utility
+ StHandle myFileToDelete; //!< file node for removal
+ StHandle myFileInfo; //!< file info for opened dialog
StCondition myEventDialog; //!< event to prevent showing multiple open/save file dialogs
StCondition myEventLoaded; //!< indicate that new file was open
double mySeekOnLoad; //!< seeking target
+ int32_t myAudioOnLoad; //!< audio track on load
+ int32_t mySubsOnLoad; //!< subtitles track on load
mg_context* myWebCtx; //!< web UI context
diff -Nru sview-13.10/StMoviePlayer/StMoviePlayer.rc sview-14.01/StMoviePlayer/StMoviePlayer.rc
--- sview-13.10/StMoviePlayer/StMoviePlayer.rc 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StMoviePlayer.rc 2014-01-30 10:45:03.000000000 +0000
@@ -15,7 +15,7 @@
BEGIN
VALUE "FileDescription", "Stereoscopic Movie Player\000"
VALUE "FileVersion", SVIEW_SDK_VER_STRING "\000"
- VALUE "LegalCopyright", "\251 2007-2013 Kirill Gavrilov\000"
+ VALUE "LegalCopyright", "\251 2007-2014 Kirill Gavrilov\000"
VALUE "ProductName", "StMoviePlayer\000"
VALUE "ProductVersion", SVIEW_SDK_VER_STRING "\000"
VALUE "OfficialSite", "www.sview.ru\000"
diff -Nru sview-13.10/StMoviePlayer/StMoviePlayerGUI.cpp sview-14.01/StMoviePlayer/StMoviePlayerGUI.cpp
--- sview-13.10/StMoviePlayer/StMoviePlayerGUI.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StMoviePlayerGUI.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -51,6 +51,7 @@
#include
#include
#include
+#include
#include
#include
@@ -193,6 +194,7 @@
anItem->signals.onItemClick.connect(myPlugin, &StMoviePlayer::doOpenRecent);
aMenuMedia->addItem(tr(MENU_MEDIA_SAVE_SNAPSHOT_AS), myPlugin->getAction(StMoviePlayer::Action_SaveSnapshot), aMenuSaveImage);
aMenuMedia->addItem(tr(MENU_MEDIA_SRC_FORMAT), aMenuSrcFormat);
+ aMenuMedia->addItem(tr(MENU_MEDIA_FILE_INFO), myPlugin->getAction(StMoviePlayer::Action_FileInfo));
aMenuMedia->addItem(tr(MENU_MEDIA_AL_DEVICE), myMenuOpenAL);
aMenuMedia->addItem("Audio Volume", aMenuVolume);
@@ -537,13 +539,13 @@
/**
* Dialog for Audio/Video synchronization control.
*/
-class StDelayControl : public StGLMessageBox {
+class ST_LOCAL StDelayControl : public StGLMessageBox {
public:
StDelayControl(StMoviePlayerGUI* theParent,
const StHandle& theTrackedValue)
- : StGLMessageBox(theParent, "", theParent->scale(400), theParent->scale(260)),
+ : StGLMessageBox(theParent, theParent->tr(DIALOG_AUDIO_DELAY_TITLE), "", theParent->scale(400), theParent->scale(260)),
myRange(NULL) {
changeRectPx().moveX( myRoot->scale( 64));
changeRectPx().moveY(-myRoot->scale(128));
@@ -557,17 +559,9 @@
aContent->setVisibility(true, true);
const StGLVec3 aWhite(1.0f, 1.0f, 1.0f);
- StGLTextArea* aTitle = new StGLTextArea(aContent, 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT),
- aContent->getRectPx().width(), myRoot->scale(10));
- aTitle->setupAlignment(StGLTextFormatter::ST_ALIGN_X_CENTER, StGLTextFormatter::ST_ALIGN_Y_TOP);
- aTitle->setText(theParent->tr(DIALOG_AUDIO_DELAY_TITLE));
- aTitle->setTextColor(aWhite);
- aTitle->setVisibility(true, true);
- aTitle->stglInitAutoHeight();
-
- StGLTextArea* aText = new StGLTextArea(aContent, 0, aTitle->getRectPx().bottom(), StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT),
+ StGLTextArea* aText = new StGLTextArea(aContent, 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_LEFT),
aContent->getRectPx().width(), myRoot->scale(10));
- aText->setText(StString("\n\n") + theParent->tr(DIALOG_AUDIO_DELAY_DESC) + "\n");
+ aText->setText(theParent->tr(DIALOG_AUDIO_DELAY_DESC) + "\n");
aText->setTextColor(aWhite);
aText->setVisibility(true, true);
aText->stglInitAutoHeight();
@@ -691,7 +685,7 @@
}
void StMoviePlayerGUI::doAboutProgram(const size_t ) {
- StGLMessageBox* aDialog = new StGLMessageBox(this,
+ StGLMessageBox* aDialog = new StGLMessageBox(this, "",
tr(ABOUT_DPLUGIN_NAME) + '\n'
+ tr(ABOUT_VERSION) + ": " + StVersionInfo::getSDKVersionString()
+ " "+ StThread::getArchString()
@@ -707,43 +701,157 @@
}
void StMoviePlayerGUI::doAboutSystem(const size_t ) {
- StString aTitle = "System Info";
- StString anInfo = getContext().stglFullInfo();
- StString aString = aTitle + "\n\n \n" + anInfo;
- StGLMessageBox* aDialog = new StGLMessageBox(this, aString, scale(512), scale(256));
+ const StString aTitle = tr(ABOUT_SYSTEM);
+ StGLMessageBox* aDialog = new StGLMessageBox(this, aTitle, "", scale(512), scale(256));
+
+ StArgumentsMap anInfo;
+ getContext().stglFullInfo(anInfo);
+ StGLTable* aTable = new StGLTable(aDialog->getContent(), 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_CENTER));
+ aTable->setVisibility(true, true);
+ aTable->fillFromMap(anInfo, StGLVec3(1.0f, 1.0f, 1.0f), aDialog->getContent()->getRectPx().width(), aDialog->getContent()->getRectPx().width() / 2);
+
aDialog->addButton(tr(BUTTON_CLOSE));
aDialog->setVisibility(true, true);
aDialog->stglInit();
}
+/**
+ * Customized message box.
+ */
+class ST_LOCAL StInfoDialog : public StGLMessageBox {
+
+ public:
+
+ ST_LOCAL StInfoDialog(StMoviePlayer* thePlugin,
+ StGLWidget* theParent,
+ const StString& theTitle,
+ const int theWidth,
+ const int theHeight)
+ : StGLMessageBox(theParent, theTitle, "", theWidth, theHeight),
+ myPlugin(thePlugin) {}
+
+ ST_LOCAL virtual ~StInfoDialog() {
+ myPlugin->doSaveFileInfo(0);
+ }
+
+ private:
+
+ StMoviePlayer* myPlugin;
+
+};
+
void StMoviePlayerGUI::doAboutFile(const size_t ) {
+ StHandle& anExtraInfo = myPlugin->myFileInfo;
+ if(!anExtraInfo.isNull()) {
+ return; // already opened
+ }
+
StHandle aFileNode;
StHandle aParams;
- StHandle anExtraInfo;
- StString aCodecsInfo;
- StArrayList anInfoList(10);
- if(myPlugin->getCurrentFile(aFileNode, aParams, anExtraInfo) && !anExtraInfo.isNull()) {
- for(size_t aKeyIter = 0; aKeyIter < anExtraInfo->myInfo.size(); ++aKeyIter) {
- const StArgument& aPair = anExtraInfo->myInfo.getFromIndex(aKeyIter);
- anInfoList.add(aPair.getKey() + ": " + aPair.getValue() + "\n");
- }
+ if(!myPlugin->getCurrentFile(aFileNode, aParams, anExtraInfo)
+ || anExtraInfo.isNull()) {
+ StHandle aQueue = myPlugin->getMessagesQueue();
+ aQueue->pushInfo(tr(DIALOG_FILE_NOINFO));
+ anExtraInfo.nullify();
+ return;
+ }
- aCodecsInfo = "\nActive codecs\n \n";
- for(size_t aKeyIter = 0; aKeyIter < anExtraInfo->myCodecs.size(); ++aKeyIter) {
- const StArgument& aPair = anExtraInfo->myCodecs.getFromIndex(aKeyIter);
- if(!aPair.getValue().isEmpty()) {
- aCodecsInfo += aPair.getValue() + "\n";
- }
- }
+ const int THE_MIN_WIDTH = scale(512);
+ const StString aTitle = tr(DIALOG_FILE_INFO);
+ const int aWidth = stMax(int(double(getRectPx().width()) * 0.6), THE_MIN_WIDTH);
+ StInfoDialog* aDialog = new StInfoDialog(myPlugin, this, aTitle, aWidth, scale(300));
+
+ // translate known metadata tag names
+ for(size_t aMapIter = 0; aMapIter < anExtraInfo->Info.size(); ++aMapIter) {
+ StDictEntry& anEntry = anExtraInfo->Info.changeValue(aMapIter);
+ StString aKey = anEntry.getKey().lowerCased();
+ anEntry.changeName() = myLangMap->getValue(aKey);
+ }
+
+ const StGLVec3 aWhite(1.0f, 1.0f, 1.0f);
+ const int aWidthMax = aDialog->getContent()->getRectPx().width();
+ StGLTable* aTable = new StGLTable(aDialog->getContent(), 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_CENTER));
+ int aRowLast = (int )anExtraInfo->Info.size();
+ const int aNbRowsMax = aRowLast + (int )anExtraInfo->Codecs.size() + 3;
+ aTable->setupTable((int )aNbRowsMax, 2);
+ aTable->setVisibility(true, true);
+ aTable->fillFromMap(anExtraInfo->Info, aWhite,
+ aWidthMax, aWidthMax / 2);
+
+ const int aTextMaxWidth = aWidthMax - (aTable->getMarginLeft() + aTable->getMarginRight());
+
+ // add stereoscopic format info
+ const StFormatEnum anActiveSrcFormat = aParams->isSwapLR()
+ ? st::formatReversed(aParams->getSrcFormat())
+ : aParams->getSrcFormat();
+ StGLTableItem& aSrcFormatItem = aTable->changeElement(aRowLast++, 0); aSrcFormatItem.setColSpan(2);
+ StGLTextArea* aSrcFormatText = new StGLTextArea(&aSrcFormatItem, 0, 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_CENTER));
+ aSrcFormatText->setupAlignment(StGLTextFormatter::ST_ALIGN_X_CENTER,
+ StGLTextFormatter::ST_ALIGN_Y_TOP);
+ aSrcFormatText->setText(StString("\n") + tr(BTN_SRC_FORMAT) + " " + trSrcFormat(anActiveSrcFormat));
+ aSrcFormatText->setTextColor(aWhite);
+ aSrcFormatText->setVisibility(true, true);
+ aSrcFormatText->stglInitAutoHeightWidth(aTextMaxWidth);
+
+ // warn about wrong/missing stereoscopic format information
+ StString aSrcInfo;
+ StGLVec3 anExtraColor = aWhite;
+ if(anExtraInfo->SrcFormat == ST_V_SRC_AUTODETECT
+ && anActiveSrcFormat != ST_V_SRC_MONO
+ && anActiveSrcFormat != ST_V_SRC_SEPARATE_FRAMES) {
+ aSrcInfo = tr(INFO_NO_SRCFORMAT);
+ anExtraColor = StGLVec3(1.0f, 1.0f, 0.8f);
+ } else if(anExtraInfo->SrcFormat != ST_V_SRC_AUTODETECT
+ && anExtraInfo->SrcFormat != anActiveSrcFormat) {
+ aSrcInfo = tr(INFO_WRONG_SRCFORMAT);
+ anExtraColor = StGLVec3(1.0f, 0.0f, 0.0f);
+ }
+ if(!aSrcInfo.isEmpty()) {
+ StGLTableItem& aTabItem = aTable->changeElement(aRowLast++, 0); aTabItem.setColSpan(2);
+ StGLTextArea* aText = new StGLTextArea(&aTabItem, 0, 0, StGLCorner(ST_VCORNER_CENTER, ST_HCORNER_CENTER));
+ aText->setupAlignment(StGLTextFormatter::ST_ALIGN_X_CENTER,
+ StGLTextFormatter::ST_ALIGN_Y_TOP);
+ aText->setText(aSrcInfo);
+ aText->setTextColor(anExtraColor);
+ aText->setVisibility(true, true);
+ aText->stglInitAutoHeightWidth(aTextMaxWidth);
}
- StString aTitle = "File Info";
- StString anInfo;
- for(size_t anIter = 0; anIter < anInfoList.size(); ++anIter) {
- anInfo += anInfoList[anIter];
+ // append information about active decoders
+ StGLTableItem& aCodecItem = aTable->changeElement(aRowLast++, 0);
+ aCodecItem.setColSpan(2);
+
+ StGLTextArea* aCodecsText = new StGLTextArea(&aCodecItem, 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_CENTER));
+ aCodecsText->setupAlignment(StGLTextFormatter::ST_ALIGN_X_LEFT,
+ StGLTextFormatter::ST_ALIGN_Y_TOP);
+ aCodecsText->setText(StString('\n') + tr(DIALOG_FILE_DECODERS) + '\n');
+ aCodecsText->setTextColor(aWhite);
+ aCodecsText->setVisibility(true, true);
+ aCodecsText->stglInitAutoHeightWidth(aTextMaxWidth);
+ for(size_t aKeyIter = 0; aKeyIter < anExtraInfo->Codecs.size(); ++aKeyIter) {
+ const StArgument& aPair = anExtraInfo->Codecs.getFromIndex(aKeyIter);
+ if(aPair.getValue().isEmpty()) {
+ continue;
+ }
+
+ StGLTableItem& anItem = aTable->changeElement(aRowLast++, 0);
+ anItem.setColSpan(2);
+
+ StGLTextArea* aText = new StGLTextArea(&anItem, 0, 0, StGLCorner(ST_VCORNER_TOP, ST_HCORNER_CENTER));
+ aText->setupAlignment(StGLTextFormatter::ST_ALIGN_X_LEFT,
+ StGLTextFormatter::ST_ALIGN_Y_TOP);
+ aText->setText(aPair.getValue());
+ aText->setTextColor(aWhite);
+ aText->setVisibility(true, true);
+ aText->stglInitAutoHeightWidth(aTextMaxWidth);
+ }
+ aTable->updateLayout();
+ const int aWidthAdjust = aWidth - stMax(aTable->getRectPx().width() + aDialog->getMarginLeft() + aDialog->getMarginRight(), THE_MIN_WIDTH);
+ if(aWidthAdjust > 0) {
+ aDialog->changeRectPx().right() -= aWidthAdjust;
+ aDialog->getContent()->changeRectPx().right() -= aWidthAdjust;
}
- StString aString = aTitle + "\n\n \n" + anInfo + aCodecsInfo;
- StGLMessageBox* aDialog = new StGLMessageBox(this, aString, scale(512), scale(300));
+
aDialog->addButton(tr(BUTTON_CLOSE));
aDialog->setVisibility(true, true);
aDialog->stglInit();
@@ -890,7 +998,8 @@
myImage = new StGLImageRegion(this, theTextureQueue, false);
mySubtitles = new StGLSubtitles (this, theSubQueue,
myPlugin->params.SubtitlesSize,
- myPlugin->params.SubtitlesParallax);
+ myPlugin->params.SubtitlesParallax,
+ myPlugin->params.SubtitlesParser);
createUpperToolbar();
@@ -998,6 +1107,26 @@
return child != NULL && !child->isVisible();
}
+size_t StMoviePlayerGUI::trSrcFormatId(const StFormatEnum theSrcFormat) {
+ switch(theSrcFormat) {
+ case ST_V_SRC_MONO: return MENU_SRC_FORMAT_MONO;
+ case ST_V_SRC_SIDE_BY_SIDE: return MENU_SRC_FORMAT_CROSS_EYED;
+ case ST_V_SRC_PARALLEL_PAIR: return MENU_SRC_FORMAT_PARALLEL;
+ case ST_V_SRC_OVER_UNDER_RL: return MENU_SRC_FORMAT_OVERUNDER_RL;
+ case ST_V_SRC_OVER_UNDER_LR: return MENU_SRC_FORMAT_OVERUNDER_LR;
+ case ST_V_SRC_ROW_INTERLACE: return MENU_SRC_FORMAT_INTERLACED;
+ //case ST_V_SRC_VERTICAL_INTERLACE:
+ case ST_V_SRC_SEPARATE_FRAMES: return MENU_SRC_FORMAT_SEPARATE;
+ case ST_V_SRC_PAGE_FLIP: return MENU_SRC_FORMAT_PAGEFLIP;
+ case ST_V_SRC_ANAGLYPH_RED_CYAN: return MENU_SRC_FORMAT_ANA_RC;
+ case ST_V_SRC_ANAGLYPH_G_RB: return MENU_SRC_FORMAT_ANA_RB;
+ case ST_V_SRC_ANAGLYPH_YELLOW_BLUE: return MENU_SRC_FORMAT_ANA_YB;
+ case ST_V_SRC_TILED_4X: return MENU_SRC_FORMAT_TILED_4X;
+ default:
+ case ST_V_SRC_AUTODETECT: return MENU_SRC_FORMAT_AUTO;
+ }
+}
+
void StMoviePlayerGUI::setVisibility(const StPointD_t& theCursor,
bool theIsMouseMoved) {
const bool toShowPlayList = myPlugin->params.ToShowPlayList->getValue();
@@ -1051,29 +1180,16 @@
size_t aLngId = myImage->params.swapLR->getValue() ? SWAP_LR_ON : SWAP_LR_OFF;
myDescr->setText(tr(aLngId));
} else if(myBtnSrcFrmt->isPointIn(theCursor)) {
- size_t aLngId = MENU_SRC_FORMAT_AUTO;
StFormatEnum aSrcFormat = (StFormatEnum )myPlugin->params.srcFormat->getValue();
if(aSrcFormat == ST_V_SRC_AUTODETECT
&& !myImage->params.stereoFile.isNull()) {
aSrcFormat = myImage->params.stereoFile->getSrcFormat();
}
- switch(aSrcFormat) {
- case ST_V_SRC_MONO: aLngId = MENU_SRC_FORMAT_MONO; break;
- case ST_V_SRC_SIDE_BY_SIDE: aLngId = MENU_SRC_FORMAT_CROSS_EYED; break;
- case ST_V_SRC_PARALLEL_PAIR: aLngId = MENU_SRC_FORMAT_PARALLEL; break;
- case ST_V_SRC_OVER_UNDER_RL: aLngId = MENU_SRC_FORMAT_OVERUNDER_RL; break;
- case ST_V_SRC_OVER_UNDER_LR: aLngId = MENU_SRC_FORMAT_OVERUNDER_LR; break;
- case ST_V_SRC_ROW_INTERLACE: aLngId = MENU_SRC_FORMAT_INTERLACED; break;
- case ST_V_SRC_ANAGLYPH_G_RB: aLngId = MENU_SRC_FORMAT_ANA_RB; break;
- case ST_V_SRC_ANAGLYPH_RED_CYAN: aLngId = MENU_SRC_FORMAT_ANA_RC; break;
- case ST_V_SRC_ANAGLYPH_YELLOW_BLUE: aLngId = MENU_SRC_FORMAT_ANA_YB; break;
- case ST_V_SRC_PAGE_FLIP: aLngId = MENU_SRC_FORMAT_PAGEFLIP; break;
- case ST_V_SRC_TILED_4X: aLngId = MENU_SRC_FORMAT_TILED_4X; break;
- case ST_V_SRC_SEPARATE_FRAMES: aLngId = MENU_SRC_FORMAT_SEPARATE; break;
- default:
- case ST_V_SRC_AUTODETECT: aLngId = MENU_SRC_FORMAT_AUTO; break;
+ if(!myImage->params.stereoFile.isNull()
+ && myImage->params.swapLR->getValue()) {
+ aSrcFormat = st::formatReversed(aSrcFormat);
}
- myDescr->setText(tr(BTN_SRC_FORMAT) + tr(aLngId));
+ myDescr->setText(tr(BTN_SRC_FORMAT) + "\n" + trSrcFormat(aSrcFormat));
} else if(myBtnPlay->isPointIn(theCursor)) {
myDescr->setText(tr(VIDEO_PLAYPAUSE));
} else if(myBtnPrev->isPointIn(theCursor)) {
@@ -1147,6 +1263,13 @@
delete anItem;
}
+ // create text parser menu
+ StGLMenu* aParserMenu = new StGLMenu(this, 0, 0, StGLMenu::MENU_VERTICAL);
+ for(size_t anIter = 0; anIter < myPlugin->params.SubtitlesParser->getValues().size(); ++anIter) {
+ aParserMenu->addItem(myPlugin->params.SubtitlesParser->getValues()[anIter], myPlugin->params.SubtitlesParser, (int32_t )anIter);
+ }
+ aParserMenu->stglInit();
+
myMenuSubtitles->addItem(tr(MENU_SUBTITLES_NONE), myPlugin->params.subtitlesStream, -1);
if(!theStreamsList.isNull()) {
for(size_t aStreamId = 0; aStreamId < theStreamsList->size(); ++aStreamId) {
@@ -1180,6 +1303,7 @@
aRange->setVisibility(true, true);
}
+ myMenuSubtitles->addItem(tr(MENU_SUBTITLES_PARSER), aParserMenu);
if(theIsFilePlayed) {
//myMenuSubtitles->addSplitter();
myMenuSubtitles->addItem(tr(MENU_SUBTITLES_ATTACH))
@@ -1221,14 +1345,14 @@
anAboutText = StString() + "Plugin '" + myPlugin->getMainWindow()->getRendererId() + "' doesn't provide description";
}
- StGLMessageBox* aDialog = new StGLMessageBox(this, anAboutText, scale(512), scale(300));
+ StGLMessageBox* aDialog = new StGLMessageBox(this, "", anAboutText, scale(512), scale(300));
aDialog->addButton(tr(BUTTON_CLOSE));
aDialog->setVisibility(true, true);
aDialog->stglInit();
}
void StMoviePlayerGUI::showUpdatesNotify() {
- StGLMessageBox* aDialog = new StGLMessageBox(this, tr(UPDATES_NOTIFY));
+ StGLMessageBox* aDialog = new StGLMessageBox(this, "", tr(UPDATES_NOTIFY));
aDialog->addButton(tr(BUTTON_CLOSE));
aDialog->setVisibility(true, true);
aDialog->stglInit();
diff -Nru sview-13.10/StMoviePlayer/StMoviePlayerGUI.h sview-14.01/StMoviePlayer/StMoviePlayerGUI.h
--- sview-13.10/StMoviePlayer/StMoviePlayerGUI.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StMoviePlayerGUI.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -59,6 +59,12 @@
return myLangMap->getValue(theId);
}
+ ST_LOCAL const StString& trSrcFormat(const StFormatEnum theSrcFormat) const {
+ return tr(trSrcFormatId(theSrcFormat));
+ }
+
+ ST_LOCAL static size_t trSrcFormatId(const StFormatEnum theSrcFormat);
+
/**
* @return absolute path to the texture
*/
diff -Nru sview-13.10/StMoviePlayer/StMoviePlayerInfo.h sview-14.01/StMoviePlayer/StMoviePlayerInfo.h
--- sview-13.10/StMoviePlayer/StMoviePlayerInfo.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StMoviePlayerInfo.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2010 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -342,9 +342,27 @@
#define ST_SRT_MIME_STRING ST_SRT_MIME ":" ST_SRT_EXT ":" ST_SRT_DESC
/**
+ *.smi
+ */
+#define ST_SMI_MIME "subtitles/x-smi"
+#define ST_SMI_EXT "smi"
+#define ST_SMI_DESC "SAMI - Utf-8 subtitles"
+#define ST_SMI_MIME_STRING ST_SMI_MIME ":" ST_SMI_EXT ":" ST_SMI_DESC
+
+/**
+ *.sub
+ */
+#define ST_SUB_MIME "subtitles/x-sub"
+#define ST_SUB_EXT "sub"
+#define ST_SUB_DESC "SUB - Image-based subtitles"
+#define ST_SUB_MIME_STRING ST_SUB_MIME ":" ST_SUB_EXT ":" ST_SUB_DESC
+
+/**
* Define Subtitles MIME list.
*/
#define ST_VIDEO_PLUGIN_SUBTIT_MIME_CHAR ST_SRT_MIME_STRING ";" \
+ST_SMI_MIME_STRING ";" \
+ST_SUB_MIME_STRING ";" \
"\000"
#endif // __StVideoPluginInfo_h_
diff -Nru sview-13.10/StMoviePlayer/StMoviePlayerStrings.cpp sview-14.01/StMoviePlayer/StMoviePlayerStrings.cpp
--- sview-13.10/StMoviePlayer/StMoviePlayerStrings.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StMoviePlayerStrings.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2013 Kirill Gavrilov
+ * Copyright © 2013-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,8 +25,14 @@
void loadDefaults(StLangMap& theStrings) {
theStrings(BUTTON_CLOSE,
"Close");
+ theStrings(BUTTON_CANCEL,
+ "Cancel");
theStrings(BUTTON_RESET,
"Reset");
+ theStrings(BUTTON_SAVE_METADATA,
+ "Save");
+ theStrings(BUTTON_DELETE,
+ "Delete");
theStrings(MENU_MEDIA,
"Media");
theStrings(MENU_VIEW,
@@ -57,6 +63,12 @@
"Font Size");
theStrings(MENU_SUBTITLES_PARALLAX,
"Parallax");
+ theStrings(MENU_SUBTITLES_PARSER,
+ "Parser");
+ theStrings(MENU_SUBTITLES_PLAIN_TEXT,
+ "Plain text");
+ theStrings(MENU_SUBTITLES_LITE_HTML,
+ "Lite HTML");
theStrings(MENU_HELP,
"Help");
theStrings(MENU_MEDIA_OPEN_MOVIE,
@@ -87,6 +99,8 @@
"Web UI can not be started on {0} port!");
theStrings(MENU_MEDIA_QUIT,
"Quit");
+ theStrings(MENU_MEDIA_FILE_INFO,
+ "File info");
theStrings(MENU_MEDIA_OPEN_MOVIE_1,
"From One file");
theStrings(MENU_MEDIA_OPEN_MOVIE_2,
@@ -188,10 +202,12 @@
"version");
theStrings(ABOUT_DESCRIPTION,
"Movie player allows you to play stereoscopic video.\n"
- "(C) 2007-2013 Kirill Gavrilov \n"
+ "(C) 2007-2014 Kirill Gavrilov \n"
"Official site: www.sview.ru\n"
"\n"
"This program distributed under GPL3.0");
+ theStrings(ABOUT_SYSTEM,
+ "System Info");
theStrings(MENU_HELP_ABOUT,
"About...");
theStrings(MENU_HELP_USERTIPS,
@@ -239,7 +255,7 @@
theStrings(FILE_VIDEO_OPEN,
"Open another movie");
theStrings(BTN_SRC_FORMAT,
- "Source format:\n");
+ "Source format:");
theStrings(VIDEO_PLAYPAUSE,
"Play/Pause");
theStrings(VIDEO_LIST_PREV,
@@ -259,12 +275,132 @@
"Choose the video file to open");
theStrings(DIALOG_OPEN_RIGHT,
"Choose RIGHT video file to open");
+ theStrings(DIALOG_FILE_INFO,
+ "File Info");
+ theStrings(DIALOG_FILE_NOINFO,
+ "Information is unavailable");
+ theStrings(DIALOG_DELETE_FILE_TITLE,
+ "File deletion");
+ theStrings(DIALOG_DELETE_FILE_QUESTION,
+ "Do you really want to completely remove this file?");
+ theStrings(DIALOG_FILE_DECODERS,
+ "Active decoders:");
theStrings(DIALOG_NOTHING_TO_SAVE,
"Nothing to save!");
theStrings(DIALOG_NO_SNAPSHOT,
"Snapshot not available!");
theStrings(DIALOG_SAVE_SNAPSHOT,
"Choose location to save snapshot");
+
+ theStrings(INFO_LEFT,
+ "[left]");
+ theStrings(INFO_RIGHT,
+ "[right]");
+ theStrings(INFO_FILE_NAME,
+ "File name(s)");
+ theStrings(INFO_DIMENSIONS,
+ "Video dimensions");
+ theStrings(INFO_LOAD_TIME,
+ "Load time");
+ theStrings(INFO_TIME_MSEC,
+ "msec");
+ theStrings(INFO_PIXEL_RATIO,
+ "Pixel ratio");
+ theStrings(INFO_PIXEL_FORMAT,
+ "Pixel format");
+ theStrings(INFO_NO_SRCFORMAT,
+ "(does not stored in metadata)");
+ theStrings(INFO_WRONG_SRCFORMAT,
+ "(does not match metadata)");
+ theStrings(INFO_DURATION,
+ "Duration");
+
+ theStrings(METADATA_TITLE,
+ "Title");
+ theStrings(METADATA_COMPOSER,
+ "Composer");
+ theStrings(METADATA_ARTIST,
+ "Artist");
+ theStrings(METADATA_ALBUM_ARTIST,
+ "Album artist");
+ theStrings(METADATA_ALBUM,
+ "Album");
+ theStrings(METADATA_DISC,
+ "Disc");
+ theStrings(METADATA_DISC_TOTAL,
+ "Nb. of discs");
+ theStrings(METADATA_GENRE,
+ "Genre");
+ theStrings(METADATA_COMMENT,
+ "Comment");
+ theStrings(METADATA_NOTES,
+ "Notes");
+ theStrings(METADATA_DESCRIPTION,
+ "Description");
+ theStrings(METADATA_PUBLISHER,
+ "Publisher");
+ theStrings(METADATA_COPYRIGHT,
+ "Copyright");
+ theStrings(METADATA_ENCODER,
+ "Encoder");
+ theStrings(METADATA_ENGINEER,
+ "Engineer");
+ theStrings(METADATA_SOURCE,
+ "Source");
+ theStrings(METADATA_CREATION_TIME,
+ "Creation time");
+ theStrings(METADATA_DATE,
+ "Date");
+ theStrings(METADATA_YEAR,
+ "Year");
+ theStrings(METADATA_LANGUAGE,
+ "Language");
+ theStrings(METADATA_TRACK,
+ "Track");
+ theStrings(METADATA_TRACK_TOTAL,
+ "Nb. of tracks");
+ theStrings(METADATA_TRACK_GAIN,
+ "Track gain");
+ theStrings(METADATA_TRACK_PEAK,
+ "Track peak");
+ theStrings(METADATA_ALBUM_GAIN,
+ "Album gain");
+ theStrings(METADATA_ALBUM_PEAK,
+ "Album peak");
+
+ // define metadata keys, should be lower cased
+ theStrings.addAlias("title", METADATA_TITLE);
+ theStrings.addAlias("composer", METADATA_COMPOSER);
+ theStrings.addAlias("artist", METADATA_ARTIST);
+ theStrings.addAlias("album_artist", METADATA_ALBUM_ARTIST);
+ theStrings.addAlias("album artist", METADATA_ALBUM_ARTIST);
+ theStrings.addAlias("album", METADATA_ALBUM);
+ theStrings.addAlias("disc", METADATA_DISC);
+ theStrings.addAlias("disctotal", METADATA_DISC_TOTAL);
+ theStrings.addAlias("totaldiscs", METADATA_DISC_TOTAL);
+ theStrings.addAlias("genre", METADATA_GENRE);
+ theStrings.addAlias("comment", METADATA_COMMENT);
+ theStrings.addAlias("notes", METADATA_NOTES);
+ theStrings.addAlias("description", METADATA_DESCRIPTION);
+ theStrings.addAlias("publisher", METADATA_PUBLISHER);
+ theStrings.addAlias("copyright", METADATA_COPYRIGHT);
+ theStrings.addAlias("encoder", METADATA_ENCODER);
+ theStrings.addAlias("encoded_by", METADATA_ENCODER);
+ theStrings.addAlias("engineer", METADATA_ENGINEER);
+ theStrings.addAlias("source", METADATA_SOURCE);
+ theStrings.addAlias("creation_time", METADATA_CREATION_TIME);
+ theStrings.addAlias("date", METADATA_DATE);
+ theStrings.addAlias("year", METADATA_YEAR);
+ theStrings.addAlias("language", METADATA_LANGUAGE);
+ theStrings.addAlias("track", METADATA_TRACK);
+ theStrings.addAlias("tracktotal", METADATA_TRACK_TOTAL);
+ theStrings.addAlias("totaltracks", METADATA_TRACK_TOTAL);
+ theStrings.addAlias("replaygain_track_gain", METADATA_TRACK_GAIN);
+ theStrings.addAlias("replaygain_track_peak", METADATA_TRACK_PEAK);
+ theStrings.addAlias("replaygain_album_gain", METADATA_ALBUM_GAIN);
+ theStrings.addAlias("replaygain_album_peak", METADATA_ALBUM_PEAK);
+ //theStrings.addAlias("album dynamic range", METADATA_ALBUM_DYNAMIC_RANGE);
+ //theStrings.addAlias("dynamic range", METADATA_DYNAMIC_RANGE);
}
};
diff -Nru sview-13.10/StMoviePlayer/StMoviePlayerStrings.h sview-14.01/StMoviePlayer/StMoviePlayerStrings.h
--- sview-13.10/StMoviePlayer/StMoviePlayerStrings.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StMoviePlayerStrings.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -48,6 +48,7 @@
MENU_MEDIA_GPU_DECODING = 1107,
MENU_MEDIA_WEBUI = 1108,
MENU_MEDIA_QUIT = 1109,
+ MENU_MEDIA_FILE_INFO = 1170,
// Root -> Media menu -> Open File menu
MENU_MEDIA_OPEN_MOVIE_1 = 1110,
@@ -129,6 +130,10 @@
MENU_SUBTITLES_ATTACH = 1353,
MENU_SUBTITLES_SIZE = 1354,
MENU_SUBTITLES_PARALLAX = 1355,
+ MENU_SUBTITLES_PARSER = 1356,
+
+ MENU_SUBTITLES_PLAIN_TEXT = 1360,
+ MENU_SUBTITLES_LITE_HTML = 1361,
// Root -> Output menu
MENU_CHANGE_DEVICE = 1400, // Root -> Output -> Change Device menu
@@ -174,6 +179,11 @@
DIALOG_OPEN_FILE = 2000,
DIALOG_OPEN_LEFT = 2001,
DIALOG_OPEN_RIGHT = 2002,
+ DIALOG_FILE_INFO = 2003,
+ DIALOG_FILE_NOINFO = 2004,
+ DIALOG_DELETE_FILE_TITLE = 2005,
+ DIALOG_DELETE_FILE_QUESTION = 2006,
+ DIALOG_FILE_DECODERS = 2007,
DIALOG_SAVE_SNAPSHOT = 2010,
DIALOG_NOTHING_TO_SAVE = 2011,
@@ -184,9 +194,54 @@
ABOUT_VERSION = 3001,
ABOUT_DESCRIPTION = 3002,
UPDATES_NOTIFY = 3003,
+ ABOUT_SYSTEM = 3004,
- BUTTON_CLOSE = 4000,
- BUTTON_RESET = 4005,
+ BUTTON_CLOSE = 4000,
+ BUTTON_CANCEL = 4001,
+ BUTTON_RESET = 4005,
+ BUTTON_SAVE_METADATA = 4006,
+ BUTTON_DELETE = 4007,
+
+ // metadata keys
+ INFO_LEFT = 5000,
+ INFO_RIGHT = 5001,
+ INFO_FILE_NAME = 5002,
+ INFO_DIMENSIONS = 5003,
+ INFO_LOAD_TIME = 5004,
+ INFO_TIME_MSEC = 5005,
+ INFO_PIXEL_RATIO = 5006,
+ INFO_PIXEL_FORMAT = 5007,
+ INFO_NO_SRCFORMAT = 5008,
+ INFO_WRONG_SRCFORMAT = 5009,
+ INFO_DURATION = 5010,
+
+ // metadata keys
+ METADATA_TITLE = 5300,
+ METADATA_COMPOSER = 5301,
+ METADATA_ARTIST = 5302,
+ METADATA_ALBUM_ARTIST = 5303,
+ METADATA_ALBUM = 5304,
+ METADATA_DISC = 5305,
+ METADATA_DISC_TOTAL = 5306,
+ METADATA_GENRE = 5307,
+ METADATA_COMMENT = 5308,
+ METADATA_NOTES = 5309,
+ METADATA_DESCRIPTION = 5310,
+ METADATA_PUBLISHER = 5311,
+ METADATA_COPYRIGHT = 5312,
+ METADATA_ENCODER = 5313,
+ METADATA_ENGINEER = 5314,
+ METADATA_SOURCE = 5315,
+ METADATA_CREATION_TIME = 5316,
+ METADATA_DATE = 5317,
+ METADATA_YEAR = 5318,
+ METADATA_LANGUAGE = 5319,
+ METADATA_TRACK = 5320,
+ METADATA_TRACK_TOTAL = 5321,
+ METADATA_TRACK_GAIN = 5322,
+ METADATA_TRACK_PEAK = 5323,
+ METADATA_ALBUM_GAIN = 5324,
+ METADATA_ALBUM_PEAK = 5325,
};
diff -Nru sview-13.10/StMoviePlayer/StVideo/StAudioQueue.cpp sview-14.01/StMoviePlayer/StVideo/StAudioQueue.cpp
--- sview-13.10/StMoviePlayer/StVideo/StAudioQueue.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StAudioQueue.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,7 +1,7 @@
/**
* This source is a part of sView program.
*
- * Copyright © Kirill Gavrilov, 2009-2013
+ * Copyright © Kirill Gavrilov, 2009-2014
*/
#include "StAudioQueue.h"
@@ -12,22 +12,23 @@
/**
* Check OpenAL state.
*/
-void stalCheckErrors(const StString& ST_DEBUG_VAR(theProcedure)) {
- ALenum error = alGetError();
- switch(error) {
- case AL_NO_ERROR: return; // alright
- case AL_INVALID_NAME: ST_DEBUG_LOG(theProcedure + ": AL_INVALID_NAME"); return;
- case AL_INVALID_ENUM: ST_DEBUG_LOG(theProcedure + ": AL_INVALID_ENUM"); return;
- case AL_INVALID_VALUE: ST_DEBUG_LOG(theProcedure + ": AL_INVALID_VALUE"); return;
- case AL_INVALID_OPERATION: ST_DEBUG_LOG(theProcedure + ": AL_INVALID_OPERATION"); return;
- case AL_OUT_OF_MEMORY: ST_DEBUG_LOG(theProcedure + ": AL_OUT_OF_MEMORY"); return;
- default: ST_DEBUG_LOG(theProcedure + ": OpenAL unknown error"); return;
+bool stalCheckErrors(const StString& ST_DEBUG_VAR(theProcedure)) {
+ ALenum anError = alGetError();
+ switch(anError) {
+ case AL_NO_ERROR: return true; // alright
+ case AL_INVALID_NAME: ST_DEBUG_LOG(theProcedure + ": AL_INVALID_NAME"); return false;
+ case AL_INVALID_ENUM: ST_DEBUG_LOG(theProcedure + ": AL_INVALID_ENUM"); return false;
+ case AL_INVALID_VALUE: ST_DEBUG_LOG(theProcedure + ": AL_INVALID_VALUE"); return false;
+ case AL_INVALID_OPERATION: ST_DEBUG_LOG(theProcedure + ": AL_INVALID_OPERATION"); return false;
+ case AL_OUT_OF_MEMORY: ST_DEBUG_LOG(theProcedure + ": AL_OUT_OF_MEMORY"); return false;
+ default: ST_DEBUG_LOG(theProcedure + ": OpenAL unknown error"); return false;
}
}
-static const StGLVec3 POSITION_CENTER ( 0.0f, 0.0f, 0.0f);
static const StGLVec3 POSITION_LEFT (-1.0f, 0.0f, 0.0f);
static const StGLVec3 POSITION_RIGHT ( 1.0f, 0.0f, 0.0f);
+
+static const StGLVec3 POSITION_CENTER ( 0.0f, 0.0f, 0.0f);
static const StGLVec3 POSITION_FRONT_LEFT (-1.0f, 0.0f, -1.0f);
static const StGLVec3 POSITION_FRONT_CENTER ( 0.0f, 0.0f, -1.0f);
static const StGLVec3 POSITION_FRONT_RIGHT ( 1.0f, 0.0f, -1.0f);
@@ -35,6 +36,11 @@
static const StGLVec3 POSITION_REAR_LEFT (-1.0f, 0.0f, 1.0f);
static const StGLVec3 POSITION_REAR_RIGHT ( 1.0f, 0.0f, 1.0f);
+static const StGLVec3 POSITION_REAR_LEFT71 (-1.0f, 0.0f, 1.0f);
+static const StGLVec3 POSITION_REAR_RIGHT71 ( 1.0f, 0.0f, 1.0f);
+static const StGLVec3 POSITION_SIDE_LEFT71 (-1.0f, 0.0f, 0.0f);
+static const StGLVec3 POSITION_SIDE_RIGHT71 ( 1.0f, 0.0f, 0.0f);
+
/**
* Check if dynamically linked version of FFmpeg libraries
* is old or not.
@@ -76,6 +82,15 @@
stalCheckErrors("alSource*4.0");
}
+void StAudioQueue::stalConfigureSources5_0() {
+ alSourcefv(myAlSources[0], AL_POSITION, POSITION_FRONT_LEFT);
+ alSourcefv(myAlSources[1], AL_POSITION, POSITION_FRONT_RIGHT);
+ alSourcefv(myAlSources[2], AL_POSITION, POSITION_FRONT_CENTER);
+ alSourcefv(myAlSources[3], AL_POSITION, POSITION_REAR_LEFT);
+ alSourcefv(myAlSources[4], AL_POSITION, POSITION_REAR_RIGHT);
+ stalCheckErrors("alSource*5.0");
+}
+
void StAudioQueue::stalConfigureSources5_1() {
alSourcefv(myAlSources[0], AL_POSITION, POSITION_FRONT_LEFT);
alSourcefv(myAlSources[1], AL_POSITION, POSITION_FRONT_RIGHT);
@@ -86,6 +101,18 @@
stalCheckErrors("alSource*5.1");
}
+void StAudioQueue::stalConfigureSources7_1() {
+ alSourcefv(myAlSources[0], AL_POSITION, POSITION_FRONT_LEFT);
+ alSourcefv(myAlSources[1], AL_POSITION, POSITION_FRONT_RIGHT);
+ alSourcefv(myAlSources[2], AL_POSITION, POSITION_FRONT_CENTER);
+ alSourcefv(myAlSources[3], AL_POSITION, POSITION_LFE);
+ alSourcefv(myAlSources[4], AL_POSITION, POSITION_REAR_LEFT71);
+ alSourcefv(myAlSources[5], AL_POSITION, POSITION_REAR_RIGHT71);
+ alSourcefv(myAlSources[6], AL_POSITION, POSITION_SIDE_LEFT71);
+ alSourcefv(myAlSources[7], AL_POSITION, POSITION_SIDE_RIGHT71);
+ stalCheckErrors("alSource*7.1");
+}
+
bool StAudioQueue::stalInit() {
StHandle aDevName = myAlDeviceName;
if(!myAlCtx.create(*aDevName)) {
@@ -373,8 +400,10 @@
deinit();
return false;
}
- } else if(myCodecCtx->channels == 6) {
- if(myAlCtx.hasExtMultiChannel) {
+ } else if(myCodecCtx->channels == 5
+ || myCodecCtx->channels == 6) {
+ if(myAlCtx.hasExtMultiChannel
+ && myCodecCtx->channels != 5) {
if(myBufferSrc.getFormat() == PCM8_UNSIGNED) {
myAlFormat = alGetEnumValue("AL_FORMAT_51CHN8");
myBufferOut.setFormat(PCM8_UNSIGNED);
@@ -425,22 +454,75 @@
myBufferOut.setFormat(PCM16_SIGNED);
}
- myBufferOut.setupChannels(StChannelMap::CH51, StChannelMap::PCM, 6);
- if(isReoderingNeeded()) {
- // workaround for old FFmpeg
- if(myCodec->id == CODEC_ID_AC3) {
- myBufferSrc.setupChannels(StChannelMap::CH51, StChannelMap::AC3, 1);
- } else if(myCodec->id == CODEC_ID_VORBIS) {
- myBufferSrc.setupChannels(StChannelMap::CH51, StChannelMap::OGG, 1);
+
+ if(myCodecCtx->channels == 5) {
+ myBufferOut.setupChannels(StChannelMap::CH50, StChannelMap::PCM, 5);
+ myBufferSrc.setupChannels(StChannelMap::CH50, StChannelMap::PCM, isPlanar ? myCodecCtx->channels : 1);
+ stalConfigureSources5_0();
+ } else {
+ myBufferOut.setupChannels(StChannelMap::CH51, StChannelMap::PCM, 6);
+ if(isReoderingNeeded()) {
+ // workaround for old FFmpeg
+ if(myCodec->id == CODEC_ID_AC3) {
+ myBufferSrc.setupChannels(StChannelMap::CH51, StChannelMap::AC3, 1);
+ } else if(myCodec->id == CODEC_ID_VORBIS) {
+ myBufferSrc.setupChannels(StChannelMap::CH51, StChannelMap::OGG, 1);
+ } else {
+ myBufferSrc.setupChannels(StChannelMap::CH51, StChannelMap::PCM, 1);
+ }
} else {
- myBufferSrc.setupChannels(StChannelMap::CH51, StChannelMap::PCM, 1);
+ myBufferSrc.setupChannels(StChannelMap::CH51, StChannelMap::PCM, isPlanar ? myCodecCtx->channels : 1);
}
- } else {
- myBufferSrc.setupChannels(StChannelMap::CH51, StChannelMap::PCM, isPlanar ? myCodecCtx->channels : 1);
+ stalConfigureSources5_1();
}
- stalConfigureSources5_1();
ST_DEBUG_LOG("OpenAL: multichannel extension (AL_FORMAT_51CHN16) not available");
}
+ } else if(myCodecCtx->channels == 8) {
+ if(myAlCtx.hasExtMultiChannel) {
+ if(myBufferSrc.getFormat() == PCM8_UNSIGNED) {
+ myAlFormat = alGetEnumValue("AL_FORMAT_71CHN8");
+ myBufferOut.setFormat(PCM8_UNSIGNED);
+ } else if(myBufferSrc.getFormat() == PCM32_SIGNED ||
+ myBufferSrc.getFormat() == PCM32FLOAT ||
+ myBufferSrc.getFormat() == PCM64FLOAT) {
+ // use float32 format to reduce quality degradation
+ myAlFormat = alGetEnumValue("AL_FORMAT_71CHN32");
+ myBufferOut.setFormat(PCM32FLOAT);
+ } else {
+ // default - int16_t
+ myAlFormat = alGetEnumValue("AL_FORMAT_71CHN16");
+ myBufferOut.setFormat(PCM16_SIGNED);
+ }
+
+ myBufferSrc.setupChannels(StChannelMap::CH40, StChannelMap::PCM, isPlanar ? myCodecCtx->channels : 1);
+ myBufferOut.setupChannels(StChannelMap::CH40, StChannelMap::PCM, 1);
+ stalConfigureSources1();
+ } else {
+ if(myBufferSrc.getFormat() == PCM8_UNSIGNED) {
+ myAlFormat = AL_FORMAT_MONO8;
+ myBufferOut.setFormat(PCM8_UNSIGNED);
+ } else if(myBufferSrc.getFormat() == PCM64FLOAT && myAlCtx.hasExtFloat64) {
+ // use float64 extension
+ myAlFormat = alGetEnumValue("AL_FORMAT_MONO_DOUBLE_EXT");
+ myBufferOut.setFormat(PCM64FLOAT);
+ } else if((myBufferSrc.getFormat() == PCM32_SIGNED ||
+ myBufferSrc.getFormat() == PCM32FLOAT ||
+ myBufferSrc.getFormat() == PCM64FLOAT)
+ && myAlCtx.hasExtFloat32) {
+ // use float32 extension to reduce quality degradation
+ myAlFormat = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
+ myBufferOut.setFormat(PCM32FLOAT);
+ } else {
+ // default - int16_t
+ myAlFormat = AL_FORMAT_MONO16;
+ myBufferOut.setFormat(PCM16_SIGNED);
+ }
+
+ myBufferOut.setupChannels(StChannelMap::CH71, StChannelMap::PCM, 8);
+ myBufferSrc.setupChannels(StChannelMap::CH71, StChannelMap::PCM, isPlanar ? myCodecCtx->channels : 1);
+ stalConfigureSources7_1();
+ ST_DEBUG_LOG("OpenAL: multichannel extension (AL_FORMAT_71CHN16) not available");
+ }
}
fillCodecInfo(myCodec);
return true;
@@ -546,6 +628,11 @@
bool toTryToPlay = false;
bool isQueued = false;
if(aProcessed == 0 && aQueued < NUM_AL_BUFFERS) {
+ if(myBufferOut.isEmpty()) {
+ ST_DEBUG_LOG(" EMPTY BUFFER ");
+ return true;
+ }
+
stalCheckErrors("reset state");
///ST_DEBUG_LOG("AL, queue more buffers " + aQueued + " / " + NUM_AL_BUFFERS);
myPrevFormat = myAlFormat;
@@ -554,7 +641,7 @@
alBufferData(myAlBuffers[aSrcId][aQueued], myAlFormat,
myBufferOut.getPlane(aSrcId), (ALsizei )myBufferOut.getPlaneSize(),
myBufferOut.getFreq());
- stalCheckErrors("alBufferData");
+ stalCheckErrors("alBufferData1");
alSourceQueueBuffers(myAlSources[aSrcId], 1, &myAlBuffers[aSrcId][aQueued]);
stalCheckErrors("alSourceQueueBuffers");
}
@@ -596,7 +683,7 @@
alBufferData(alBuffIdToFill, myAlFormat,
myBufferOut.getPlane(aSrcId), (ALsizei )myBufferOut.getPlaneSize(),
myBufferOut.getFreq());
- stalCheckErrors("alBufferData");
+ stalCheckErrors("alBufferData2");
alSourceQueueBuffers(myAlSources[aSrcId], 1, &alBuffIdToFill);
stalCheckErrors("alSourceQueueBuffers");
} else {
diff -Nru sview-13.10/StMoviePlayer/StVideo/StAudioQueue.h sview-14.01/StMoviePlayer/StVideo/StAudioQueue.h
--- sview-13.10/StMoviePlayer/StVideo/StAudioQueue.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StAudioQueue.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -126,7 +126,9 @@
ST_LOCAL void stalConfigureSources1();
ST_LOCAL void stalConfigureSources2_0();
ST_LOCAL void stalConfigureSources4_0();
+ ST_LOCAL void stalConfigureSources5_0();
ST_LOCAL void stalConfigureSources5_1();
+ ST_LOCAL void stalConfigureSources7_1();
ST_LOCAL bool stalQueue(const double thePts);
diff -Nru sview-13.10/StMoviePlayer/StVideo/StPCMBuffer.cpp sview-14.01/StMoviePlayer/StVideo/StPCMBuffer.cpp
--- sview-13.10/StMoviePlayer/StVideo/StPCMBuffer.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StPCMBuffer.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,7 +26,7 @@
*/
#define ST_MAX_AUDIO_FRAME_SIZE 192000
-StChannelMap::StChannelMap(const StChannelMap::Channels theChannels,
+StChannelMap::StChannelMap(const StChannelMap::Channels theChannels,
const StChannelMap::OrderRules theRules)
: count(0),
channels(theChannels) {
@@ -35,11 +35,11 @@
}
switch(theChannels) {
case StChannelMap::CH10:
- FL = FR = FC = LFE = RL = RR = 0;
+ FL = FR = FC = LFE = RL = RR = SL = SR = 0;
count = 1;
return;
case StChannelMap::CH20:
- FL = FC = LFE = RL = RR = 0; FR = 1;
+ FL = FC = LFE = RL = RR = SL = SR = 0; FR = 1;
count = 2;
return;
case StChannelMap::CH40:
@@ -48,10 +48,20 @@
FR = 1;
RL = 2;
RR = 3;
- FC = LFE = 0;
+ FC = LFE = SL = SR = 0;
+ return;
+ case StChannelMap::CH50:
+ count = 5;
+ FL = 0;
+ FR = 1;
+ FC = 2;
+ RL = 3;
+ RR = 4;
+ LFE = SL = SR = 0;
return;
case StChannelMap::CH51:
count = 6;
+ SL = SR = 0;
switch(theRules) {
case StChannelMap::PCM: {
FL = 0;
@@ -79,6 +89,17 @@
return;
}
}
+ case StChannelMap::CH71:
+ count = 8;
+ FL = 0;
+ FR = 1;
+ FC = 2;
+ LFE = 3;
+ RL = 4;
+ RR = 5;
+ SL = 6;
+ SR = 7;
+ return;
}
}
@@ -350,6 +371,17 @@
myPlaneSize += anAddedPlaneSize;
return true;
}
+ case StChannelMap::CH50: {
+ for(size_t sampleSrcId(0), sampleOutId(0); sampleSrcId < aSamplesSrcCount; sampleSrcId += aSmplSrcInc, sampleOutId += aSmplOutInc) {
+ sampleConv(aBuffersSrc[0][sampleSrcId], aBuffersOut[0][sampleOutId]);
+ sampleConv(aBuffersSrc[1][sampleSrcId], aBuffersOut[1][sampleOutId]);
+ sampleConv(aBuffersSrc[2][sampleSrcId], aBuffersOut[2][sampleOutId]);
+ sampleConv(aBuffersSrc[3][sampleSrcId], aBuffersOut[3][sampleOutId]);
+ sampleConv(aBuffersSrc[4][sampleSrcId], aBuffersOut[4][sampleOutId]);
+ }
+ myPlaneSize += anAddedPlaneSize;
+ return true;
+ }
case StChannelMap::CH51: {
for(size_t sampleSrcId(0), sampleOutId(0); sampleSrcId < aSamplesSrcCount; sampleSrcId += aSmplSrcInc, sampleOutId += aSmplOutInc) {
sampleConv(aBuffersSrc[0][sampleSrcId], aBuffersOut[0][sampleOutId]);
@@ -362,6 +394,20 @@
myPlaneSize += anAddedPlaneSize;
return true;
}
+ case StChannelMap::CH71: {
+ for(size_t sampleSrcId(0), sampleOutId(0); sampleSrcId < aSamplesSrcCount; sampleSrcId += aSmplSrcInc, sampleOutId += aSmplOutInc) {
+ sampleConv(aBuffersSrc[0][sampleSrcId], aBuffersOut[0][sampleOutId]);
+ sampleConv(aBuffersSrc[1][sampleSrcId], aBuffersOut[1][sampleOutId]);
+ sampleConv(aBuffersSrc[2][sampleSrcId], aBuffersOut[2][sampleOutId]);
+ sampleConv(aBuffersSrc[3][sampleSrcId], aBuffersOut[3][sampleOutId]);
+ sampleConv(aBuffersSrc[4][sampleSrcId], aBuffersOut[4][sampleOutId]);
+ sampleConv(aBuffersSrc[5][sampleSrcId], aBuffersOut[5][sampleOutId]);
+ sampleConv(aBuffersSrc[6][sampleSrcId], aBuffersOut[6][sampleOutId]);
+ sampleConv(aBuffersSrc[7][sampleSrcId], aBuffersOut[7][sampleOutId]);
+ }
+ myPlaneSize += anAddedPlaneSize;
+ return true;
+ }
default:
return false;
}
diff -Nru sview-13.10/StMoviePlayer/StVideo/StPCMBuffer.h sview-14.01/StMoviePlayer/StVideo/StPCMBuffer.h
--- sview-13.10/StMoviePlayer/StVideo/StPCMBuffer.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StPCMBuffer.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -95,9 +95,10 @@
//CH31,
CH40,
//CH41,
+ CH50, // 3 Front + 2 Rear
CH51, // 3 Front + 2 Rear + LFE
//CH61,
- //CH71
+ CH71
} Channels;
typedef enum tagOrderRules {
@@ -119,6 +120,8 @@
size_t LFE; //!< Low Frequency
size_t RL; //!< Rear Left
size_t RR; //!< Rear Right
+ size_t SL; //!< Side Left
+ size_t SR; //!< Side Right
public:
@@ -131,7 +134,9 @@
&& FC == theOther.FC
&& LFE == theOther.LFE
&& RL == theOther.RL
- && RR == theOther.RR;
+ && RR == theOther.RR
+ && SL == theOther.SL
+ && SR == theOther.SR;
}
ST_LOCAL bool operator!=(const StChannelMap& theOther) const {
diff -Nru sview-13.10/StMoviePlayer/StVideo/StParamActiveStream.cpp sview-14.01/StMoviePlayer/StVideo/StParamActiveStream.cpp
--- sview-13.10/StMoviePlayer/StVideo/StParamActiveStream.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StParamActiveStream.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2011 Kirill Gavrilov
+ * Copyright © 2011-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +24,13 @@
myMutex(),
myIsChanged(false) {}
+int32_t StParamActiveStream::getListSize() const {
+ myMutex.lock();
+ const int32_t aSize = int32_t(myList->size());
+ myMutex.unlock();
+ return aSize;
+}
+
StHandle< StArrayList > StParamActiveStream::getList() const {
myMutex.lock();
StHandle< StArrayList > aList = myList;
diff -Nru sview-13.10/StMoviePlayer/StVideo/StParamActiveStream.h sview-14.01/StMoviePlayer/StVideo/StParamActiveStream.h
--- sview-13.10/StMoviePlayer/StVideo/StParamActiveStream.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StParamActiveStream.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2011 Kirill Gavrilov
+ * Copyright © 2011-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -74,6 +74,11 @@
*/
ST_LOCAL bool wasChanged() const;
+ /**
+ * @return list size
+ */
+ ST_LOCAL int32_t getListSize() const;
+
private:
StHandle< StArrayList > myList;
diff -Nru sview-13.10/StMoviePlayer/StVideo/StSubtitleQueue.cpp sview-14.01/StMoviePlayer/StVideo/StSubtitleQueue.cpp
--- sview-13.10/StMoviePlayer/StVideo/StSubtitleQueue.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StSubtitleQueue.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2011-2013 Kirill Gavrilov
+ * Copyright © 2011-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,6 +21,8 @@
#include
#include
+#include
+
namespace {
static const StString ST_CRLF_REDUNDANT = "\x0D\x0A";
static const StString ST_CRLF_REPLACEMENT = " \x0A";
@@ -39,10 +41,8 @@
: StAVPacketQueue(512),
myOutQueue(theSubtitlesQueue),
myThread(NULL),
- myASS(),
evDowntime(true),
toQuit(false) {
- //
myThread = new StThread(threadFunction, (void* )this);
}
@@ -166,14 +166,50 @@
switch(aRect->type) {
case SUBTITLE_BITMAP: {
- // unsupported yet
+ if(aDuration < 0.001) {
+ aDuration = 3.0; // duration is always zero here...
+ }
+
+ StHandle aNewSubItem = new StSubItem(aPts, aPts + aDuration);
+ aNewSubItem->Image.initTrash(StImagePlane::ImgRGBA, aRect->w, aRect->h);
+
+ SwsContext* aCtxToRgb = sws_getContext(aRect->w, aRect->h, stAV::PIX_FMT::PAL8,
+ aRect->w, aRect->h, stAV::PIX_FMT::RGBA32,
+ SWS_BICUBIC, NULL, NULL, NULL);
+ if(aCtxToRgb == NULL) {
+ break;
+ }
+
+ uint8_t* aDstData[4] = {
+ (uint8_t* )aNewSubItem->Image.getData(),
+ NULL,
+ NULL,
+ NULL
+ };
+ const int aDstLinesize[4] = {
+ (int )aNewSubItem->Image.getSizeRowBytes(),
+ 0,
+ 0,
+ 0
+ };
+
+ sws_scale(aCtxToRgb,
+ aRect->pict.data, aRect->pict.linesize,
+ 0, aRect->h,
+ aDstData, aDstLinesize);
+ sws_freeContext(aCtxToRgb);
+
+ /*ST_DEBUG_LOG(" |" + aRectId + "/" + aSubtitle.num_rects + "| " //+ aRect->x + "x" + aRect->y + " WH= "
+ + aRect->w + "x" + aRect->h + " c= " + aRect->nb_colors
+ + " pts= " + aPts
+ + " dur= " + aDuration);*/
+ myOutQueue->push(aNewSubItem);
break;
}
case SUBTITLE_TEXT: {
- StString aText = aRect->text;
- aText.replaceFast(ST_CRLF_REDUNDANT, ST_CRLF_REPLACEMENT); // remove redundant CR symbols
- StHandle aNewSubItem = new StSubItem(aText,
- aPts, aPts + aDuration);
+ StHandle aNewSubItem = new StSubItem(aPts, aPts + aDuration);
+ aNewSubItem->Text = aRect->text;
+ aNewSubItem->Text.replaceFast(ST_CRLF_REDUNDANT, ST_CRLF_REPLACEMENT); // remove redundant CR symbols
myOutQueue->push(aNewSubItem);
break;
}
@@ -208,10 +244,9 @@
#endif
} else {
// just plain text
- StString aText = (const char* )aPacket->getData();
- aText.replaceFast(ST_CRLF_REDUNDANT, ST_CRLF_REPLACEMENT); // remove redundant CR symbols
- StHandle aNewSubItem = new StSubItem(aText,
- aPts, aPts + aDuration);
+ StHandle aNewSubItem = new StSubItem(aPts, aPts + aDuration);
+ aNewSubItem->Text = (const char* )aPacket->getData();
+ aNewSubItem->Text.replaceFast(ST_CRLF_REDUNDANT, ST_CRLF_REPLACEMENT); // remove redundant CR symbols
myOutQueue->push(aNewSubItem);
}
diff -Nru sview-13.10/StMoviePlayer/StVideo/StSubtitleQueue.h sview-14.01/StMoviePlayer/StVideo/StSubtitleQueue.h
--- sview-13.10/StMoviePlayer/StVideo/StSubtitleQueue.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StSubtitleQueue.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2011-2013 Kirill Gavrilov
+ * Copyright © 2011-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
diff -Nru sview-13.10/StMoviePlayer/StVideo/StSubtitlesASS.cpp sview-14.01/StMoviePlayer/StVideo/StSubtitlesASS.cpp
--- sview-13.10/StMoviePlayer/StVideo/StSubtitlesASS.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StSubtitlesASS.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2011 Kirill Gavrilov
+ * Copyright © 2011-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -252,7 +252,7 @@
aText.replaceFast(ST_CRLF_REDUNDANT, ST_CRLF_REPLACEMENT);
aText.replaceFast(ST_ASS_NEWLINE, ST_NEWLINE_REPLACEMENT);
aText.replaceFast(ST_ASS_NEWLINE2, ST_NEWLINE_REPLACEMENT);
- StHandle aNewSubItem = new StSubItem(aText,
- thePts, thePts + aDuration);
+ StHandle aNewSubItem = new StSubItem(thePts, thePts + aDuration);
+ aNewSubItem->Text = aText;
return aNewSubItem;
}
diff -Nru sview-13.10/StMoviePlayer/StVideo/StSubtitlesASS.h sview-14.01/StMoviePlayer/StVideo/StSubtitlesASS.h
--- sview-13.10/StMoviePlayer/StVideo/StSubtitlesASS.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StSubtitlesASS.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2011 Kirill Gavrilov
+ * Copyright © 2011-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -94,4 +94,4 @@
};
-#endif //__StSubtitlesASS_h_
+#endif // __StSubtitlesASS_h_
diff -Nru sview-13.10/StMoviePlayer/StVideo/StVideo.cpp sview-14.01/StMoviePlayer/StVideo/StVideo.cpp
--- sview-13.10/StMoviePlayer/StVideo/StVideo.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StVideo.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -21,7 +21,8 @@
#include "../StMoviePlayerStrings.h"
#include
-#include
+
+using namespace StMoviePlayerStrings;
namespace {
static const char ST_AUDIOS_MIME_STRING[] = ST_VIDEO_PLUGIN_AUDIO_MIME_CHAR;
@@ -63,6 +64,11 @@
stAV::init();
myPlayList->setExtensions(myMimesVideo.getExtensionsList());
+ myTracksExt = myMimesSubs.getExtensionsList();
+ StArrayList anAudioExt = myMimesAudio.getExtensionsList();
+ for(size_t anExtIter = 0; anExtIter < anAudioExt.size(); ++anExtIter) {
+ myTracksExt.add(anAudioExt.getValue(anExtIter));
+ }
params.UseGpu = new StBoolParam(false);
params.activeAudio = new StParamActiveStream();
@@ -273,13 +279,20 @@
StString aTitleString, aFolder;
StFileNode::getFolderAndFile(theFileToLoad, aFolder, aTitleString);
- myFileInfoTmp->myInfo.add(StArgument("File name", aTitleString));
+ if(myFileInfoTmp->Path.isEmpty()) {
+ myFileInfoTmp->Path = theFileToLoad;
+ }
+ StDictEntry& aFileNamePair = myFileInfoTmp->Info.addChange(tr(INFO_FILE_NAME));
+ if(!aFileNamePair.getValue().isEmpty()) {
+ aFileNamePair.changeValue() += "\n";
+ }
+ aFileNamePair.changeValue() += aTitleString;
// collect metadata
for(stAV::meta::Tag* aTag = stAV::meta::findTag(aFormatCtx->metadata, "", NULL, stAV::meta::SEARCH_IGNORE_SUFFIX);
aTag != NULL;
aTag = stAV::meta::findTag(aFormatCtx->metadata, "", aTag, stAV::meta::SEARCH_IGNORE_SUFFIX)) {
- myFileInfoTmp->myInfo.add(StArgument(aTag->key, aTag->value));
+ myFileInfoTmp->Info.add(StArgument(aTag->key, aTag->value));
}
theMaxDuration = stMax(theMaxDuration, stAV::unitsToSeconds(aFormatCtx->duration));
@@ -296,19 +309,22 @@
if(myVideoMaster->isInitialized()) {
const int aSizeX = myVideoMaster->sizeX();
const int aSizeY = myVideoMaster->sizeY();
- StString aDimsStr = StString() + aSizeX + " x " + aSizeY;
const int aCodedSizeX = myVideoMaster->getCodedSizeX();
const int aCodedSizeY = myVideoMaster->getCodedSizeY();
+ StString aDimsStr = StString() + aSizeX + " x " + aSizeY;
if(aCodedSizeX != aSizeX
|| aCodedSizeY != aSizeY) {
aDimsStr += StString(" (") + aCodedSizeX + " x " + aCodedSizeY + ")";
}
- myFileInfoTmp->myInfo.add(StArgument("Video Dimensions", aDimsStr));
- myFileInfoTmp->myInfo.add(StArgument("Pixel Format",
+
+ StDictEntry& aDimInfo = myFileInfoTmp->Info.addChange(tr(INFO_DIMENSIONS));
+ aDimInfo.changeValue() = aDimsStr;
+
+ myFileInfoTmp->Info.add(StArgument(tr(INFO_PIXEL_FORMAT),
myVideoMaster->getPixelFormatString()));
- myFileInfoTmp->myInfo.add(StArgument("Pixel Ratio",
+ myFileInfoTmp->Info.add(StArgument(tr(INFO_PIXEL_RATIO),
StString() + myVideoMaster->getPixelRatio()));
- myFileInfoTmp->myInfo.add(StArgument("Duration",
+ myFileInfoTmp->Info.add(StArgument(tr(INFO_DURATION),
StFormatTime::formatSeconds(theMaxDuration)));
}
} else if(!myVideoSlave->isInitialized()) {
@@ -319,14 +335,18 @@
const int aSizeX = myVideoSlave->sizeX();
const int aSizeY = myVideoSlave->sizeY();
- StString aDimsStr = StString() + aSizeX + " x " + aSizeY;
const int aCodedSizeX = myVideoSlave->getCodedSizeX();
const int aCodedSizeY = myVideoSlave->getCodedSizeY();
+ StString aDimsStr = StString() + aSizeX + " x " + aSizeY;
if(aCodedSizeX != aSizeX
|| aCodedSizeY != aSizeY) {
aDimsStr += StString(" (") + aCodedSizeX + " x " + aCodedSizeY + ")";
}
- myFileInfoTmp->myInfo.add(StArgument("Video Dimensions (slave)", aDimsStr));
+ aDimsStr += " [2]";
+
+ StDictEntry& aDimInfo = myFileInfoTmp->Info.addChange(tr(INFO_DIMENSIONS));
+ aDimInfo.changeValue() += "\n";
+ aDimInfo.changeValue() += aDimsStr;
if(myVideoMaster->getSrcFormat() == ST_V_SRC_AUTODETECT) {
myVideoMaster->setSlave(myVideoSlave);
@@ -420,10 +440,40 @@
return false;
}
} else {
- if(!addFile(theNewSource->getPath(),
+ const StString aFullPath = theNewSource->getPath();
+ if(!addFile(aFullPath,
aStreamsListA, aStreamsListS, aDuration)) {
return false;
}
+
+ // search for additional tracks
+ if(params.ToSearchSubs->getValue()
+ && myVideoMaster->isInitialized()
+ && !StFileNode::isRemoteProtocolPath(aFullPath)) {
+ StString aFolder, aFileName;
+ StFileNode::getFolderAndFile(aFullPath, aFolder, aFileName);
+ if(aFileName.getLength() > 8) { // ignore too short names
+ StString aName, anExtension, aTrackName, aTrackExtension;
+ StFileNode::getNameAndExtension(aFileName, aName, anExtension);
+ if(myTracksFolder.getPath() != aFolder) {
+ // notice that playlist re-loading is not checked here...
+ myTracksFolder.setSubPath(aFolder);
+ myTracksFolder.init(myTracksExt, 1);
+ }
+ for(size_t aNodeIter = 0; aNodeIter < myTracksFolder.size(); ++aNodeIter) {
+ const StFileNode* aNode = myTracksFolder.getValue(aNodeIter);
+ const StString& aTrackFileName = aNode->getSubPath();
+ StFileNode::getNameAndExtension(aTrackFileName, aTrackName, aTrackExtension);
+ if(aFileName != aTrackFileName
+ && aTrackName.isStartsWithIgnoreCase(aName)) {
+ //myPlayList->addToNode(aCurrFile, aFilePath);
+ //myPlayList->getCurrentFile(theNewSource, theNewParams)
+ addFile(aNode->getPath(),
+ aStreamsListA, aStreamsListS, aDuration);
+ }
+ }
+ }
+ }
}
if(!myVideoMaster->isInitialized() && !myAudio->isInitialized()) {
@@ -431,19 +481,25 @@
return false;
}
- StArgument aTitle = myFileInfoTmp->myInfo["TITLE"];
+ StArgument aTitle = myFileInfoTmp->Info["TITLE"];
if(!aTitle.isValid()) {
- aTitle = myFileInfoTmp->myInfo["title"];
+ aTitle = myFileInfoTmp->Info["title"];
}
- StArgument anArtist = myFileInfoTmp->myInfo["ARTIST"];
+ StArgument anArtist = myFileInfoTmp->Info["ARTIST"];
if(!anArtist.isValid()) {
- anArtist = myFileInfoTmp->myInfo["artist"];
+ anArtist = myFileInfoTmp->Info["artist"];
}
if(anArtist.isValid() && aTitle.isValid()) {
- myPlayList->setTitle(theNewParams, anArtist.getValue() + " - " + aTitle.getValue());
+ StString anArtistStr = anArtist.getValue();
+ StString aTitleStr = aTitle.getValue();
+ anArtistStr.rightAdjust();
+ aTitleStr .rightAdjust();
+ myPlayList->setTitle(theNewParams, anArtistStr + " - " + aTitleStr);
} else if(aTitle.isValid()) {
- if(aTitle.getValue().getLength() < 20) {
+ StString aTitleStr = aTitle.getValue();
+ aTitleStr.rightAdjust();
+ if(aTitleStr.getLength() < 20) {
// protection against messed title
StString aFileName;
StString aFolder;
@@ -454,15 +510,15 @@
aPath = theNewSource->getPath();
}
StFileNode::getFolderAndFile(aPath, aFolder, aFileName);
- myPlayList->setTitle(theNewParams, aTitle.getValue() + " (" + aFileName + ")");
+ myPlayList->setTitle(theNewParams, aTitleStr + " (" + aFileName + ")");
} else {
- myPlayList->setTitle(theNewParams, aTitle.getValue());
+ myPlayList->setTitle(theNewParams, aTitleStr);
}
}
myCurrNode = theNewSource;
myCurrParams = theNewParams;
- myFileInfoTmp->myId = myCurrParams;
+ myFileInfoTmp->Id = myCurrParams;
params.activeAudio->setList(aStreamsListA, aStreamsListA->isEmpty() ? -1 : 0);
params.activeSubtitles->setList(aStreamsListS, -1); // do not show subtitles by default
@@ -515,10 +571,13 @@
}
if(!isSeekDone) {
// at last - try to seek the format context itself...
- int64_t aSeekTarget = stAV::secondsToUnits(theSeekPts);
- isSeekDone = av_seek_frame(theFormatCtx, -1, aSeekTarget, 0) >= 0;
+ const int aFlags = toSeekBack ? AVSEEK_FLAG_BACKWARD : 0;
+ int64_t aSeekTarget = stAV::secondsToUnits(theSeekPts);
+ isSeekDone = av_seek_frame(theFormatCtx, -1, aSeekTarget, aFlags) >= 0;
if(!isSeekDone) {
- ST_DEBUG_LOG("Seeking disaster!");
+ #ifdef __ST_DEBUG__
+ ST_ERROR_LOG("Disaster! Seeking to " + theSeekPts + " [" + theFormatCtx->filename + "] has failed.");
+ #endif
}
}
}
@@ -527,16 +586,16 @@
const signed int theStreamId,
const double theSeekPts,
const bool toSeekBack) {
+ const int aFlags = toSeekBack ? AVSEEK_FLAG_BACKWARD : 0;
AVStream* aStream = theFormatCtx->streams[theStreamId];
int64_t aSeekTarget = stAV::secondsToUnits(aStream, theSeekPts + stAV::unitsToSeconds(aStream, aStream->start_time));
-
- bool isSeekDone = av_seek_frame(theFormatCtx, theStreamId, aSeekTarget, 0) >= 0;
+ bool isSeekDone = av_seek_frame(theFormatCtx, theStreamId, aSeekTarget, aFlags) >= 0;
// try 10 more times in backward direction to work-around huge duration between key frames
// will not work for some streams with undefined cur_dts (AV_NOPTS_VALUE)!!!
for(int aTries = 10; isSeekDone && toSeekBack && aTries > 0 && (aStream->cur_dts > aSeekTarget); --aTries) {
aSeekTarget -= stAV::secondsToUnits(aStream, 1.0);
- isSeekDone = av_seek_frame(theFormatCtx, theStreamId, aSeekTarget, 0) >= 0;
+ isSeekDone = av_seek_frame(theFormatCtx, theStreamId, aSeekTarget, aFlags) >= 0;
}
if(!isSeekDone) {
@@ -969,7 +1028,8 @@
fileToSave += StString('.') + saveExt;
}
ST_DEBUG_LOG("Save snapshot to the path '" + fileToSave + '\'');
- if(!dataResult->save(fileToSave, theImgType)) {
+ if(!dataResult->save(fileToSave, theImgType,
+ toSaveStereo ? ST_V_SRC_SIDE_BY_SIDE : ST_V_SRC_AUTODETECT)) {
// TODO (Kirill Gavrilov#7)
signals.onError(dataResult->getState());
return false;
@@ -985,19 +1045,42 @@
myEventMutex.lock();
StHandle anInfo = myFileInfo;
myEventMutex.unlock();
- if(anInfo.isNull() || anInfo->myId != theParams) {
+ if(anInfo.isNull() || anInfo->Id != theParams) {
return NULL;
}
- anInfo->myCodecs.clear();
- anInfo->myCodecs.add(StArgument("vcodec1", myVideoMaster->getCodecInfo()));
- anInfo->myCodecs.add(StArgument("vcodec2", myVideoSlave->getCodecInfo()));
- anInfo->myCodecs.add(StArgument("audio", myAudio->getCodecInfo()));
- anInfo->myCodecs.add(StArgument("subtitles", mySubtitles->getCodecInfo()));
+ // continuously read source format since it can be stored in frame
+ anInfo->SrcFormat = myVideoMaster->getSrcFormatInfo();
+
+ anInfo->Codecs.clear();
+ anInfo->Codecs.add(StArgument("vcodec1", myVideoMaster->getCodecInfo()));
+ anInfo->Codecs.add(StArgument("vcodec2", myVideoSlave->getCodecInfo()));
+ anInfo->Codecs.add(StArgument("audio", myAudio->getCodecInfo()));
+ anInfo->Codecs.add(StArgument("subtitles", mySubtitles->getCodecInfo()));
return anInfo;
}
+void StVideo::doRemovePhysically(const StHandle& theFile) {
+ if(theFile.isNull()
+ || theFile->size() != 0) {
+ return;
+ }
+
+ const StHandle aCurrent = myPlayList->getCurrentFile();
+ const bool toPlayNext = !aCurrent.isNull()
+ && aCurrent->size() == 0
+ && aCurrent->getPath().isEquals(theFile->getPath());
+
+ myEventMutex.lock();
+ myFilesToDelete.add(theFile);
+ myEventMutex.unlock();
+
+ if(toPlayNext) {
+ doLoadNext();
+ }
+}
+
void StVideo::mainLoop() {
bool isOpenSuccess = false;
StHandle aFileToLoad;
@@ -1044,14 +1127,30 @@
myVideoTimer.nullify();
- for(;;) {
- if(popPlayEvent(aDummy, aDummyBool) == ST_PLAYEVENT_NEXT) {
- if(toQuit) {
- return;
+ myEventMutex.lock();
+ if(!myFilesToDelete.isEmpty()) {
+ const StHandle aCurrent = myPlayList->getCurrentFile();
+ if(!aCurrent.isNull()
+ && aCurrent->getPath().isEquals(myFilesToDelete[0]->getPath())) {
+ close();
+ }
+ for(size_t anIter = 0; anIter < myFilesToDelete.size(); ++anIter) {
+ const StHandle& aNode = myFilesToDelete[anIter];
+ if(!myPlayList->removePhysically(aNode)) {
+ signals.onError(StString("File can not be deleted!\n" + aNode->getPath()));
}
- } else {
+ }
+ myFilesToDelete.clear();
+ }
+ myEventMutex.unlock();
+
+ for(;;) {
+ if(popPlayEvent(aDummy, aDummyBool) != ST_PLAYEVENT_NEXT) {
myPlayList->walkToNext(false);
}
+ if(toQuit) {
+ return;
+ }
isOpenSuccess = false;
if(myPlayList->getCurrentFile(aFileToLoad, aFileParams)) {
isOpenSuccess = openSource(aFileToLoad, aFileParams);
diff -Nru sview-13.10/StMoviePlayer/StVideo/StVideo.h sview-14.01/StMoviePlayer/StVideo/StVideo.h
--- sview-13.10/StMoviePlayer/StVideo/StVideo.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StVideo.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2007-2013 Kirill Gavrilov
+ * Copyright © 2007-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
// forward declarations
class StSubQueue;
@@ -37,12 +38,19 @@
struct StMovieInfo {
- StHandle myId;
- StArgumentsMap myInfo;
- StArgumentsMap myCodecs;
+ StHandle Id;
+ StArgumentsMap Info;
+ StArgumentsMap Codecs;
+ StString Path; //!< file path
+ StFormatEnum SrcFormat; //!< source format as stored in file metadata
+ bool IsSavable; //!< indicate that file can be saved without re-encoding
+
+ StMovieInfo() : SrcFormat(ST_V_SRC_AUTODETECT), IsSavable(false) {}
};
+template<> inline void StArray< StHandle >::sort() {}
+
/**
* Special class for video playback.
*/
@@ -140,7 +148,7 @@
*/
ST_LOCAL StHandle getFileInfo(const StHandle& theParams) const;
- public: //!< callback Slots
+ public: //! @name callback Slots
/**
* Interrupt the playback and load current position in playlist.
@@ -150,6 +158,11 @@
}
/**
+ * Add file node for removal.
+ */
+ ST_LOCAL void doRemovePhysically(const StHandle& theFile);
+
+ /**
* Save current displayed frame.
*/
ST_LOCAL void doSaveSnapshotAs(const size_t theImgType) {
@@ -180,17 +193,18 @@
ST_LOCAL void setAudioDelay(const float theDelaySec);
- public: //!< Properties
+ public: //! @name Properties
struct {
StHandle UseGpu; //!< use video decoding on GPU when available
+ StHandle ToSearchSubs; //!< automatically search for additional subtitles/audio track files nearby video file
StHandle activeAudio; //!< active Audio stream
StHandle activeSubtitles; //!< active Subtitles stream
} params;
- public: //!< Signals
+ public: //! @name Signals
/**
* All callback handlers should be thread-safe.
@@ -261,6 +275,10 @@
private: //! @name auxiliary methods
+ ST_LOCAL const StString& tr(const size_t theId) const {
+ return myLangMap->getValue(theId);
+ }
+
/**
* Just redirect callback slot.
*/
@@ -358,6 +376,11 @@
StHandle myCurrParams; //!< paramters for active file node
StHandle myTextureQueue; //!< decoded frames queue
+ StArrayList myTracksExt; //!< extra tracks extensions list
+ StFolder myTracksFolder; //!< cached list of subtitles/audio tracks in the current folder
+ StArrayList< StHandle >
+ myFilesToDelete;//!< file nodes for removal
+
StHandle myVideoTimer; //!< video refresh timer (Audio -> Video sync)
mutable StMutex myEventMutex; //!< lock for thread-safety
double myDuration; //!< active file duration in seconds
@@ -372,4 +395,4 @@
};
-#endif //__StVideo_h_
+#endif // __StVideo_h_
diff -Nru sview-13.10/StMoviePlayer/StVideo/StVideoQueue.cpp sview-14.01/StMoviePlayer/StVideo/StVideoQueue.cpp
--- sview-13.10/StMoviePlayer/StVideo/StVideoQueue.cpp 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StVideoQueue.cpp 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -691,6 +691,16 @@
}
// we currently allow to override source format stored in metadata
+ #ifdef ST_AV_NEWSTEREO
+ AVFrameSideData* aSideData = av_frame_get_side_data(myFrame.Frame, AV_FRAME_DATA_STEREO3D);
+ if(aSideData != NULL) {
+ AVStereo3D* aStereo = (AVStereo3D* )aSideData->data;
+ mySrcFormatInfo = stAV::stereo3dAvToSt(aStereo->type);
+ if(aStereo->flags & AV_STEREO3D_FLAG_INVERT) {
+ mySrcFormatInfo = st::formatReversed(mySrcFormatInfo);
+ }
+ }
+ #endif
if(stAV::meta::readTag(myFrame.Frame, THE_SRC_MODE_KEY, aTagValue)) {
for(size_t aSrcId = 0;; ++aSrcId) {
const StFFmpegStereoFormat& aFlag = STEREOFLAGS[aSrcId];
@@ -765,7 +775,7 @@
if(isOddNumber(myFramesCounter)) {
myCachedFrame.fill(myDataAdp);
} else {
- pushFrame(myCachedFrame, myDataAdp, aPacket->getSource(), ST_V_SRC_SEPARATE_FRAMES, myFramePts);
+ pushFrame(myCachedFrame, myDataAdp, aPacket->getSource(), ST_V_SRC_PAGE_FLIP, myFramePts);
}
++myFramesCounter;
} else {
diff -Nru sview-13.10/StMoviePlayer/StVideo/StVideoQueue.h sview-14.01/StMoviePlayer/StVideo/StVideoQueue.h
--- sview-13.10/StMoviePlayer/StVideo/StVideoQueue.h 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/StVideo/StVideoQueue.h 2014-01-30 10:45:03.000000000 +0000
@@ -1,5 +1,5 @@
/**
- * Copyright © 2009-2013 Kirill Gavrilov
+ * Copyright © 2009-2014 Kirill Gavrilov
*
* StMoviePlayer program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -100,6 +100,16 @@
return stAV::PIX_FMT::getString(myCodecCtx->pix_fmt);
}
+ /**
+ * @return sterescopic information stored in file
+ */
+ ST_LOCAL StFormatEnum getSrcFormatInfo() const {
+ return mySrcFormatInfo;
+ }
+
+ /**
+ * @return source format detection rule
+ */
ST_LOCAL StFormatEnum getSrcFormat() const {
return mySrcFormat;
}
diff -Nru sview-13.10/StMoviePlayer/lang/english/StMoviePlayer.lng sview-14.01/StMoviePlayer/lang/english/StMoviePlayer.lng
--- sview-13.10/StMoviePlayer/lang/english/StMoviePlayer.lng 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/lang/english/StMoviePlayer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -4,7 +4,7 @@
--------
1002="Swap Left/Right"
1003="UnSwap Left/Right"
-1004="Source format:\n"
+1004="Stereoscopic format:"
1015="Open another movie"
1020="Play/Pause"
1021="Show/Hide playlist"
@@ -14,7 +14,8 @@
1100="Media"
1101="Open Movie..."
1102="Save Snapshot..."
-1103="Source stereo format"
+1103="Stereoscopic format"
+1170="File info"
1104="Audio Device"
1105="Shuffle"
1106="Recent files"
@@ -72,7 +73,7 @@
1301="None"
1302="Audio/Video delay"
1303="Attach from file"
-1320="Audio/Video syncronization"
+1320="Audio/Video synchronization"
1321="Enter positive value if audio appears earlier than video and negative otherwise."
1322="Audio delay:"
1323="second(s)"
@@ -81,6 +82,9 @@
1353="Attach from file"
1354="Font Size"
1355="Parallax"
+1356="Text parser"
+1360="Plain text"
+1361="Lite HTML"
1400="Change device"
1401="About Plugin..."
1402="FPS Control"
@@ -96,7 +100,7 @@
1506="User tips"
1507="Experimental features"
1508="About system"
-1509="Scale Interface"
+1509="Interface Scale"
1520="Now"
1521="Each day"
1522="Each week"
@@ -112,13 +116,59 @@
1593="Force HiDPI 2X"
2000="Choose the video file to open"
2001="Choose LEFT video file to open"
-2001="Choose RIGHT video file to open"
+2002="Choose RIGHT video file to open"
+2003="File Info"
+2004="File information is unavailable"
+2005="File deletion"
+2006="Do you really want to completely remove this file?"
+2007="Active decoders:"
2010="Choose location to save snapshot"
2011="Nothing to save!"
2012="Snapshot not available!"
3000="sView - Movie Player"
3001="version"
-3002="Movie player allows you to play stereoscopic video.\n © 2007-2013 Kirill Gavrilov \nOfficial site: www.sview.ru\n\nThis program distributed under GPL3.0"
+3002="Movie player allows you to play stereoscopic video.\n © 2007-2014 Kirill Gavrilov \nOfficial site: www.sview.ru\n\nThis program distributed under GPL3.0"
3003="A new version of sView is available on the official site www.sview.ru.\nPlease update your program."
+3004="System Info"
4000="Close"
+4001="Cancel"
4005="Reset"
+4006="Save"
+4007="Delete"
+5000="[left]"
+5001="[right]"
+5002="File name(s)"
+5003="Video dimensions"
+5004="Load time"
+5005="ms"
+5006="Pixel ratio"
+5007="Pixel format"
+5008="(does not stored in metadata)"
+5009="(does not match metadata)"
+5010="Duration"
+5300="Title"
+5301="Composer"
+5302="Artist"
+5303="Album artist"
+5304="Album"
+5305="Disc"
+5306="Nb. of discs"
+5307="Genre"
+5308="Comment"
+5309="Notes"
+5310="Description"
+5311="Publisher"
+5312="Copyright"
+5313="Encoder"
+5314="Engineer"
+5315="Source"
+5316="Creation time"
+5317="Date"
+5318="Year"
+5319="Language"
+5320="Track"
+5321="Nb. of tracks"
+5322="Track gain"
+5323="Track peak"
+5324="Album gain"
+5325="Album peak"
diff -Nru sview-13.10/StMoviePlayer/lang/french/StMoviePlayer.lng sview-14.01/StMoviePlayer/lang/french/StMoviePlayer.lng
--- sview-13.10/StMoviePlayer/lang/french/StMoviePlayer.lng 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/lang/french/StMoviePlayer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -4,7 +4,7 @@
--------
1002="Gauche/Droite inversé"
1003="Gauche/Droite normal"
-1004="Format entrée:\n"
+1004="Format entrée:"
1015="Ouvre autre vidéo"
1020="Lecture/Pause"
1021="Affiche/Masque playlist"
@@ -15,6 +15,7 @@
1101="Ouvre Video..."
1102="Enregistre Capture..."
1103="Format Stéréo d'entrée"
+1170="File info"
1104="Audio Device"
1105="Shuffle"
1106="Recent files"
@@ -72,7 +73,7 @@
1301="None"
1302="Audio/Video delay"
1303="Attach from file"
-1320="Audio/Video syncronization"
+1320="Audio/Video synchronization"
1321="Enter positive value if audio appears earlier than video and negative otherwise."
1322="Audio delay:"
1323="second(s)"
@@ -81,6 +82,9 @@
1353="Attach from file"
1354="Font Size"
1355="Parallax"
+1356="Text parser"
+1360="Plain text"
+1361="Lite HTML"
1400="Changer la sortie"
1401="A propos du Plugin..."
1402="Contrôle de I/S"
@@ -112,13 +116,59 @@
1593="Force HiDPI 2X"
2000="Choix du fichier vidéo à ouvrir"
2001="Choix du fichier vidéo Gauche à ouvrir"
-2001="Choix du fichier vidéo Droite à ouvrir"
+2002="Choix du fichier vidéo Droite à ouvrir"
+2003="File Info"
+2004="File information is unavailable"
+2005="File deletion"
+2006="Do you really want to completely remove this file?"
+2007="Active decoders:"
2010="Emplacement de la capture écran"
2011="Rien à enregistrer!"
2012="Capture non disponible!"
3000="sView - Movie Player"
3001="version"
-3002="Movie Player vous permet d'ouvrir des vidéo stéréoscopiques.\n © 2007-2013 Kirill Gavrilov \nSite Officiel: www.sview.ru\n\nThis program distributed under GPL3.0"
+3002="Movie Player vous permet d'ouvrir des vidéo stéréoscopiques.\n © 2007-2014 Kirill Gavrilov \nSite Officiel: www.sview.ru\n\nThis program distributed under GPL3.0"
3003="Une nouvelle version de sView est disponible sur le site officiel www.sview.ru.\nSVP, mettez votre programme à jour."
+3004="System Info"
4000="Fermer"
+4001="Cancel"
4005="Reset"
+4006="Enregistre"
+4007="Delete"
+5000="[left]"
+5001="[right]"
+5002="File name(s)"
+5003="Résolution vidéo"
+5004="Load time"
+5005="ms"
+5006="Pixel ratio"
+5007="Pixel format"
+5008="(does not stored in metadata)"
+5009="(does not match metadata)"
+5010="Durée"
+5300="Title"
+5301="Composer"
+5302="Artist"
+5303="Album artist"
+5304="Album"
+5305="Disc"
+5306="Nb. of discs"
+5307="Genre"
+5308="Comment"
+5309="Notes"
+5310="Description"
+5311="Publisher"
+5312="Copyright"
+5313="Encoder"
+5314="Engineer"
+5315="Source"
+5316="Creation time"
+5317="Date"
+5318="Année"
+5319="Language"
+5320="Track"
+5321="Nb. of tracks"
+5322="Track gain"
+5323="Track peak"
+5324="Album gain"
+5325="Album peak"
diff -Nru sview-13.10/StMoviePlayer/lang/german/StMoviePlayer.lng sview-14.01/StMoviePlayer/lang/german/StMoviePlayer.lng
--- sview-13.10/StMoviePlayer/lang/german/StMoviePlayer.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StMoviePlayer/lang/german/StMoviePlayer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1,174 @@
+German translation file for StMoviePlayer program
+@author Kirill Gavrilov
+
+--------
+1002="L&R Vertauschen An"
+1003="L&R Vertauschen Aus"
+1004="Quellformat:"
+1015="Öffnen anderen Film"
+1020="Wiedergabe/Pause"
+1021="Anzeigen/ausblenden Wiedergabeliste"
+1022="Vorheriges Stück"
+1023="Nachfolgendes Stück"
+1029="Vollbildmodus/Fenstermodus"
+1100="Medien"
+1101="Film öffnen..."
+1102="Videoschnappschuss speichern..."
+1103="Quelle Stereo-Format"
+1170="File info"
+1104="Audiogerät"
+1105="Shuffle"
+1106="Zuletzt geöffnete Medien öffnen"
+1107="GPU-basierter Video-Dekodierung"
+1108="Web UI"
+1109="Beenden"
+1110="Einer Datei"
+1111="Zwei Dateien"
+1130="Autoerkennung"
+1131="Mono"
+1132="Schielend"
+1133="Parallel Pair"
+1134="Over/Under (R/L)"
+1135="Over/Under (L/R)"
+1136="Interlaced"
+1137="Anaglyph Rot/Cyan"
+1138="Anaglyph Grün/Rot+Blau"
+1139="Anaglyph Gelb/Blau"
+1140="Rahmen-sequentielle"
+1141="2x720p in 1080p tiled"
+1142="2 Streams"
+1160="Verlauf löschen"
+1180="Turn Off"
+1181="Starten einmal"
+1182="Starten jedesmal"
+1185="Show errors"
+1186="Web UI can not be started on {0} port!"
+1200="Ansicht"
+1201="Stereo-Ausgang"
+1202="Vollbild"
+1203="Zurückstellen"
+1204="L&R Vertauschen"
+1205="Seitenverhältnis"
+1206="Glatte Filter"
+1207="Bildeinstellung"
+1208="Oberfläche"
+1210="Stereo"
+1211="Linke Bild"
+1212="Rechte Bild"
+1213="Parallel Pair"
+1214="Cross-eyed"
+1250="Quelle"
+1251="Halten beim Neustart"
+1260="Nearest"
+1261="Linear"
+1262="Blend Deinterlace"
+1270="Auf Standardwerte zurücksetzen"
+1271="Helligkeit"
+1272="Sättigung"
+1273="Gamma"
+1280="Fläche"
+1281="Kugel"
+1282="Zylinder"
+1300="Audio"
+1301="keiner"
+1302="Audio/Video Verzögerung"
+1303="Bringen aus der Datei"
+1320="Audio/Video Synchronisierung"
+1321="Enter positive value if audio appears earlier than video and negative otherwise."
+1322="Audioverzögerung:"
+1323="Sek."
+1350="Untertitel"
+1351="keiner"
+1353="Bringen aus der Datei"
+1354="Schriftgröße"
+1355="Parallax"
+1356="Text parser"
+1360="Plain text"
+1361="Lite HTML"
+1400="Gerät ändern"
+1401="Über Plugin..."
+1402="FPS Kontrolle"
+1420="VSync"
+1421="Zeige Meter"
+1422="Reduce CPU usage"
+1500="Hilfe"
+1501="Über..."
+1502="Nach Updates suchen"
+1503="Lizenztext"
+1504="Language"
+1505="Blockieren Schlaf"
+1506="Anwendertipps"
+1507="Experimentelle Funktionen"
+1508="Über System"
+1509="Maßstab Benutzeroberfläche"
+1520="jetzt"
+1521="täglich"
+1522="wöchentlich"
+1523="jährlich"
+1524="nie"
+1550="nie"
+1551="immer"
+1552="während der Wiedergabe"
+1553="Wenn in Vollbild"
+1590="klein"
+1591="normal"
+1592="groß"
+1593="erzwingen HiDPI 2X"
+2000="Wählen die Videodatei zu öffnen"
+2001="Wählen die linke Videodatei zu öffnen"
+2002="Wählen die rechte Videodatei zu öffnen"
+2003="File Info"
+2004="File information is unavailable"
+2005="Löschen von Dateien"
+2006="Do you really want to completely remove this file?"
+2007="Active decoders:"
+2010="Wählen einen Speicherort für Videoschnappschuss"
+2011="Nichts zu speichern!"
+2012="Schnappschuss ist nicht verfügbar!"
+3000="sView - Movie Player"
+3001="Version"
+3002="Movie player allows you to play stereoscopic video.\n © 2007-2014 Kirill Gavrilov \nOfficial site: www.sview.ru\n\nThis program distributed under GPL3.0"
+3003="A new version of sView is available on the official site www.sview.ru.\nPlease update your program."
+3004="System Info"
+4000="Schließen"
+4001="Cancel"
+4005="Reset"
+4006="Speichern"
+4007="Delete"
+5000="[left]"
+5001="[right]"
+5002="File name(s)"
+5003="Video dimensions"
+5004="Load time"
+5005="ms"
+5006="Pixel ratio"
+5007="Pixel format"
+5008="(does not stored in metadata)"
+5009="(does not match metadata)"
+5010="Dauer"
+5300="Titel"
+5301="Composer"
+5302="Artist"
+5303="Album artist"
+5304="Album"
+5305="Disc"
+5306="Nb. of discs"
+5307="Genre"
+5308="Kommentar"
+5309="Notes"
+5310="Beschreibung"
+5311="Publisher"
+5312="Copyright"
+5313="Encoder"
+5314="Engineer"
+5315="Source"
+5316="Creation time"
+5317="Datum"
+5318="Jahr"
+5319="Sprache"
+5320="Track"
+5321="Nb. of tracks"
+5322="Track gain"
+5323="Track peak"
+5324="Album gain"
+5325="Album peak"
diff -Nru sview-13.10/StMoviePlayer/lang/korean/StMoviePlayer.lng sview-14.01/StMoviePlayer/lang/korean/StMoviePlayer.lng
--- sview-13.10/StMoviePlayer/lang/korean/StMoviePlayer.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StMoviePlayer/lang/korean/StMoviePlayer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1,175 @@
+Korean translation file for StMoviePlayer program
+@author Kirill Gavrilov
+@translator Kwon Daesuk
+
+--------
+1002="좌/우 교체"
+1003="좌/우 복원"
+1004="소스 형식:"
+1015="다른 영상 열기"
+1020="재생/멈춤"
+1021="재생 목록 보이기/감추기"
+1022="앞 파일 재생"
+1023="다음 파일 재생"
+1029="전환\n전체화면/윈도우화면"
+1100="미디어"
+1101="파일 열기..."
+1102="스냅샷 저장..."
+1103="소스 스테레오 형식"
+1170="File info"
+1104="오디오 장치"
+1105="셔플"
+1106="최근 파일"
+1107="GPU 비디오 디코딩"
+1108="웹 UI"
+1109="종료"
+1110="파일 하나에서 재생"
+1111="좌+우 각 파일에서 재생"
+1130="자동감지"
+1131="단일영상"
+1132="크로스-아이"
+1133="패럴렐 페어"
+1134="상/하 (R/L)"
+1135="상/하 (L/R)"
+1136="인터레이스"
+1137="red/cyan"
+1138="green/red+blue"
+1139="yellow/blue"
+1140="순차 프레임"
+1141="2x720p in 1080p tiled"
+1142="2 스트림"
+1160="재생 기록 소거"
+1180="끄기"
+1181="한번만 실행"
+1182="매번 실행"
+1185="오류 보이기"
+1186="웹 UI {0} 포트에서 시작 불가!"
+1200="보기"
+1201="입체 출력"
+1202="전체 화면"
+1203="리셋"
+1204="좌/우 교체"
+1205="화면 비율"
+1206="Smooth 필터"
+1207="이미지 수정"
+1208="Surface"
+1210="Stereo"
+1211="왼쪽 View"
+1212="오른쪽 View"
+1213="패럴렐 페어"
+1214="크로스 아이"
+1250="Source"
+1251="재시작시 유지"
+1260="Nearest"
+1261="Linear"
+1262="Blend Deinterlace"
+1270="초기값 리셋"
+1271="밝기"
+1272="Saturation"
+1273="감마"
+1280="Plane"
+1281="Sphere"
+1282="Cylinder"
+1300="Audio"
+1301="없음"
+1302="오디오/비디오 지연시간"
+1303="파일에서 불러오기"
+1320="오디오/비디오 동기화"
+1321="오디오가 화면보다 먼저 들리면 +값을, 반대이면 -값을 넣으시오"
+1322="오디오 지연:"
+1323="초(s)"
+1350="자막"
+1351="없음"
+1353="파일에서 불러오기"
+1354="폰트 크기"
+1355="Parallax"
+1356="Text parser"
+1360="Plain text"
+1361="Lite HTML"
+1400="장치 변경"
+1401="About Plugin..."
+1402="FPS 제어"
+1420="VSync"
+1421="Show Meter"
+1422="CPU 부하 감소"
+1500="도움말"
+1501="이 프로그램에 대해..."
+1502="업데이트 확인"
+1503="라이선스 문서"
+1504="언어 (Language)"
+1505="블록 슬리핑"
+1506="사용자 팁"
+1507="실험적 기능"
+1508="시스템에 대해"
+1509="Interface Scale"
+1520="지금"
+1521="매일"
+1522="매주"
+1523="매년"
+1524="하지않음"
+1550="하지않음"
+1551="항상"
+1552="재생중"
+1553="전체화면중"
+1590="작게"
+1591="보통"
+1592="크게"
+1593="HiDPI 2X 로"
+2000="재생할 비디오 파일을 선택하시오"
+2001="좌안 비디오 파일을 선택하시오"
+2002="우안 비디오 파일을 선택하시오"
+2003="File Info"
+2004="File information is unavailable"
+2005="File deletion"
+2006="Do you really want to completely remove this file?"
+2007="Active decoders:"
+2010="스냅샷을 저장할 위치를 선택하시오"
+2011="저장할 수 없음!"
+2012="스냅샷 없음!"
+3000="sView - 3D 동영상 플레이어"
+3001="version"
+3002="이 동영상 플레이어는 스테레오스코픽 동영상을 재생할 수 있습니다.\n © 2007-2014 Kirill Gavrilov \nOfficial site: www.sview.ru\n\n이 프로그램은 GPL3.0 하에 배포됩니다."
+3003="sView 새 버전은 www.sview.ru 에서 얻으실 수 있습니다.\n 프로그램을 업데이트 하세요."
+3004="System Info"
+4000="닫기"
+4001="Cancel"
+4005="리셋"
+4006="Save"
+4007="Delete"
+5000="[left]"
+5001="[right]"
+5002="File name(s)"
+5003="Video dimensions"
+5004="Load time"
+5005="ms"
+5006="Pixel ratio"
+5007="Pixel format"
+5008="(does not stored in metadata)"
+5009="(does not match metadata)"
+5010="Duration"
+5300="Title"
+5301="Composer"
+5302="Artist"
+5303="Album artist"
+5304="Album"
+5305="Disc"
+5306="Nb. of discs"
+5307="Genre"
+5308="Comment"
+5309="Notes"
+5310="Description"
+5311="Publisher"
+5312="Copyright"
+5313="Encoder"
+5314="Engineer"
+5315="Source"
+5316="Creation time"
+5317="Date"
+5318="Year"
+5319="Language"
+5320="Track"
+5321="Nb. of tracks"
+5322="Track gain"
+5323="Track peak"
+5324="Album gain"
+5325="Album peak"
diff -Nru sview-13.10/StMoviePlayer/lang/korean/language.lng sview-14.01/StMoviePlayer/lang/korean/language.lng
--- sview-13.10/StMoviePlayer/lang/korean/language.lng 1970-01-01 00:00:00.000000000 +0000
+++ sview-14.01/StMoviePlayer/lang/korean/language.lng 2014-01-30 10:45:03.000000000 +0000
@@ -0,0 +1 @@
+한국어
\ No newline at end of file
diff -Nru sview-13.10/StMoviePlayer/lang/russian/StMoviePlayer.lng sview-14.01/StMoviePlayer/lang/russian/StMoviePlayer.lng
--- sview-13.10/StMoviePlayer/lang/russian/StMoviePlayer.lng 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/lang/russian/StMoviePlayer.lng 2014-01-30 10:45:03.000000000 +0000
@@ -4,7 +4,7 @@
--------
1002="Поменять ракурсы местами"
1003="Отключить реверс ракурсов"
-1004="Исходный формат:\n"
+1004="Исходный стереоформат:"
1015="Открыть видеофайл"
1020="Пауза/Воспроизведение"
1021="Отобразить/Скрыть\nсписок файлов"
@@ -15,6 +15,7 @@
1101="Открыть видео..."
1102="Сохранить кадр..."
1103="Исходный стереоформат"
+1170="Информация о файле"
1104="Аудио устройство"
1105="Случайный порядок"
1106="Последние файлы"
@@ -107,19 +108,68 @@
1553="В полноэкранном режиме"
1354="Размер текста"
1355="Параллакс"
+1356="Text parser"
+1360="Plain text"
+1361="Lite HTML"
1590="Мелко"
1591="Нормально"
1592="Крупно"
1593="Форсировать HiDPI 2X"
2000="Выберите видеофайл"
2001="Выберите видеофайл с ЛЕВЫМ ракурсом"
-2001="Выберите видеофайл с ПРАВЫМ ракурсом"
+2002="Выберите видеофайл с ПРАВЫМ ракурсом"
+2003="Информация о файле"
+2004="Информация о файле недоступна"
+2005="Удаление файла"
+2006="Вы действительно хотите\nудалить файл минуя корзину?"
+2007="Активные декодеры:"
2010="Выберите путь для сохранения картинки"
2011="Ничего не открыто!"
2012="Изображение недоступно для сохранения!"
3000="sView - программа для воспроизведения видео"
3001="версия"
-3002="Программа воспроизводит стереоскопическое видео.\n © 2007-2013 Гаврилов Кирилл \nОфициальный сайт: www.sview.ru\n\nПрограмма распространяется на условиях GPL3.0"
+3002="Программа воспроизводит стереоскопическое видео.\n © 2007-2014 Гаврилов Кирилл \nОфициальный сайт: www.sview.ru\n\nПрограмма распространяется на условиях GPL3.0"
3003="Доступно обновление программы.\nВы можете загрузить новую версию с официального сайта www.sview.ru."
+3004="Информация о системе"
4000="Закрыть"
+4001="Отменить"
4005="Сбросить"
+4006="Сохранить"
+4007="Удалить"
+5000="[левый]"
+5001="[правый]"
+5002="Имена файлов"
+5003="Разрешение видео"
+5004="Время загрузки"
+5005="мс"
+5006="Пропорции пикселя"
+5007="Пиксельный формат"
+5008="(информация отсутствует в метаданных)"
+5009="(не соответствует метаданным)"
+5010="Продолжительность"
+5300="Заголовок"
+5301="Композитор"
+5302="Artist"
+5303="Album artist"
+5304="Альбом"
+5305="Диск"
+5306="Количество дисков"
+5307="Жанр"
+5308="Комментарий"
+5309="Примечания"
+5310="Описание"
+5311="Publisher"
+5312="Copyright"
+5313="Encoder"
+5314="Engineer"
+5315="Источник"
+5316="Дата создания"
+5317="Дата"
+5318="Год"
+5319="Язык"
+5320="Track"
+5321="Nb. of tracks"
+5322="Track gain"
+5323="Track peak"
+5324="Album gain"
+5325="Album peak"
Binary files /tmp/MNWssWIMVS/sview-13.10/StMoviePlayer/web/favicon.ico and /tmp/OrsWdxfD0p/sview-14.01/StMoviePlayer/web/favicon.ico differ
diff -Nru sview-13.10/StMoviePlayer/web/index.htm sview-14.01/StMoviePlayer/web/index.htm
--- sview-13.10/StMoviePlayer/web/index.htm 2013-10-05 08:32:22.000000000 +0000
+++ sview-14.01/StMoviePlayer/web/index.htm 2014-01-30 10:45:03.000000000 +0000
@@ -1,6 +1,7 @@
-
+
+
sView Web UI