Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Movie import #1258

Merged
merged 20 commits into from
May 7, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2109f8f
Add movie importing features
scribblemaniac Aug 31, 2019
ce079a8
Add ffprobe to CI builds
scribblemaniac Aug 31, 2019
4218c7a
Detect failed movie video import
scribblemaniac Aug 31, 2019
1bb7f1b
Add cancel to movie import and audio mixing step of movie export
scribblemaniac Aug 31, 2019
036bcd3
Add cancel to movie audio import
scribblemaniac Aug 31, 2019
e8593f1
Add progress updates and cancel to numbered image sequence import
scribblemaniac Aug 31, 2019
5aa5fdc
Added support for many new audio formats
scribblemaniac Sep 7, 2019
45aaada
Create a Movies import format that matches all supported extensions
scribblemaniac Sep 14, 2019
52c2fb9
Make ffprobe optional by default and don't include by default
scribblemaniac Sep 14, 2019
3650d8a
Merge branch 'master' into movie-import
scribblemaniac Mar 4, 2020
0dc229c
Write to disk during movie import
scribblemaniac Mar 4, 2020
d458c10
Change ffmpeg-based duration detection
scribblemaniac Mar 4, 2020
3b4aa3a
Add some checks and TODOs to the movie importer
scribblemaniac Mar 4, 2020
055e626
Delete temporary folders on closing without saving
scribblemaniac Mar 4, 2020
9804aec
Merge branch 'master' into pr-1258-changes
MrStevns May 4, 2020
5a7257b
Move MovieImport Logic into MovieImporter class and decouple UI from …
MrStevns May 6, 2020
df12488
Rename verifyFFMPEG -> verifyFFmpegExists
MrStevns May 6, 2020
ea33310
Refactor movie importer...again
scribblemaniac May 7, 2020
1dc3ade
Fix blank dialog when cancelling movie import
scribblemaniac May 7, 2020
514f130
Remove unnecessary QProgressDialog reference in Editor
scribblemaniac May 7, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Merge branch 'master' into movie-import
  • Loading branch information
scribblemaniac committed Mar 4, 2020
commit 3650d8a5d6d4e4a86604a4fa01030b0845960725
19 changes: 7 additions & 12 deletions app/src/filedialogex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,18 +180,13 @@ QString FileDialog::openFileFilters( FileType fileType )
{
switch ( fileType )
{
case FileType::ANIMATION: return PFF_OPEN_ALL_FILE_FILTER;
case FileType::IMAGE: return PENCIL_IMAGE_FILTER;
case FileType::IMAGE_SEQUENCE: return PENCIL_IMAGE_SEQ_FILTER;
case FileType::GIF: return QString("%1 (*.gif)").arg(tr("Animated GIF"));
case FileType::MOVIE: { return PENCIL_MOVIE_EXT; }
case FileType::SOUND: return QString("%1 (*.wav *.mp3 *.wma *.ogg *.flac *.opus *.aiff *.aac *.caf);;WAV (*.wav);;MP3 (*.mp3);;WMA (*.wma);;OGG (*.ogg);;FLAC (*.flac);;Opus (*.opus);;AIFF (*.aiff);;AAC (*.aac);;CAF (*.caf)").arg("Sounds");
case FileType::PALETTE:
return QString("%1 (*.xml *.gpl);;%2 (*.xml);;%3 (*.gpl)")
.arg(tr("Palette"))
.arg(tr("Pencil2D Palette"))
.arg(tr("GIMP Palette"));
default: Q_ASSERT( false );
case FileType::ANIMATION: return PFF_PROJECT_EXT_FILTER;
case FileType::IMAGE: return PFF_IMAGE_FILTER;
case FileType::IMAGE_SEQUENCE: return PFF_IMAGE_SEQ_FILTER;
case FileType::GIF: return PFF_GIF_EXT_FILTER;
case FileType::MOVIE: return PFF_MOVIE_EXT;
case FileType::SOUND: return PFF_SOUND_EXT_FILTER;
case FileType::PALETTE: return PFF_PALETTE_EXT_FILTER;
}
return "";
}
Expand Down
117 changes: 12 additions & 105 deletions app/src/mainwindow2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,14 +251,16 @@ void MainWindow2::createMenus()
//connect( ui->actionExport_Svg_Image, &QAction::triggered, editor, &Editor::saveSvg );
connect(ui->actionImport_Image, &QAction::triggered, this, &MainWindow2::importImage);
connect(ui->actionImport_ImageSeq, &QAction::triggered, this, &MainWindow2::importImageSequence);
connect(ui->actionImport_ImageSeqNum, &QAction::triggered, this, &MainWindow2::importImageSequenceNumbered);
connect(ui->actionImport_ImageSeqNum, &QAction::triggered, this, &MainWindow2::importPredefinedImageSet);
connect(ui->actionImportLayers_from_pclx, &QAction::triggered, this, &MainWindow2::importLayers);
connect(ui->actionImport_MovieVideo, &QAction::triggered, this, &MainWindow2::importMovieVideo);
connect(ui->actionImport_Gif, &QAction::triggered, this, &MainWindow2::importGIF);

connect(ui->actionImport_Sound, &QAction::triggered, mCommands, &ActionCommands::importSound);
connect(ui->actionImport_MovieAudio, &QAction::triggered, this, &MainWindow2::importMovieAudio);

connect(ui->actionImport_Palette, &QAction::triggered, this, &MainWindow2::importPalette);
connect(ui->actionImport_Append_Palette, &QAction::triggered, this, &MainWindow2::importPalette);
connect(ui->actionImport_Replace_Palette, &QAction::triggered, this, &MainWindow2::openPalette);

//--- Edit Menu ---
connect(ui->actionUndo, &QAction::triggered, mEditor, &Editor::undo);
Expand Down Expand Up @@ -364,7 +366,7 @@ void MainWindow2::createMenus()
mColorBox->toggleViewAction(),
mColorPalette->toggleViewAction(),
mTimeLine->toggleViewAction(),
mDisplayOptionWidget->toggleViewAction(),
mDisplayOptionWidget->toggleViewAction(),
mColorInspector->toggleViewAction(),
mOnionSkinWidget->toggleViewAction()
};
Expand Down Expand Up @@ -902,104 +904,9 @@ void MainWindow2::importPredefinedImageSet()

void MainWindow2::importLayers()
{
// Show a progress dialog, as this can take a while if you have lots of images.
QProgressDialog progress(tr("Importing movie video..."), tr("Abort"), 0, 100, this);
hideQuestionMark(progress);
progress.setWindowModality(Qt::WindowModal);
progress.show();

// local vars for testing file validity
int dot = strFilePath.lastIndexOf(".");
int slash = strFilePath.lastIndexOf("/");
QString fName = strFilePath.mid(slash + 1);
QString path = strFilePath.left(slash + 1);
QString digit = strFilePath.mid(slash + 1, dot - slash - 1);

// Find number of digits (min: 1, max: digit.length - 1)
int digits = 0;
for (int i = digit.length() - 1; i > 0; i--)
{
if (digit.at(i).isDigit())
{
digits++;
}
else
{
break;
}
}
if (digits < 1) { return; }
digit = strFilePath.mid(dot - digits, digits);
QString prefix = strFilePath.mid(slash + 1, dot - slash - digits - 1);
QString suffix = strFilePath.mid(dot, strFilePath.length() - 1);

QDir dir = strFilePath.left(strFilePath.lastIndexOf("/"));
QStringList sList = dir.entryList(QDir::Files, QDir::Name);
if (sList.isEmpty()) { return; }

// List of files is not empty. Let's go find the relevant files
QStringList finalList;
int validLength = prefix.length() + digit.length() + suffix.length();
for (int i = 0; i < sList.size(); i++)
{
if (sList[i].startsWith(prefix) &&
sList[i].length() == validLength &&
sList[i].mid(sList[i].lastIndexOf(".") - digits, digits).toInt() > 0 &&
sList[i].endsWith(suffix))
{
finalList.append(sList[i]);
}
}
if (finalList.isEmpty()) { return; }

// List of relevant files is not empty. Let's validate them
dot = finalList[0].lastIndexOf(".");

QString msg = "";
for (int i = 0; i < finalList.size(); i++)
{
if (!(finalList[i].mid(dot - digits, digits).toInt()
&& (finalList[i].mid(dot - digits, digits).toInt() > 0)))
{
msg = tr("Illegal numbering");
}
if (msg.length() > 0)
{
QMessageBox msgBox;
msgBox.setText(msg);
msgBox.exec();
return;
}
}
progress.setValue(5);
QApplication::processEvents();

// Flag this so we don't prompt the user about auto-save in the middle of the import.
mIsImportingImageSequence = true;

prefix = mCommands->nameSuggest(prefix);
mEditor->layers()->createBitmapLayer(prefix);
Layer *layer = mEditor->layers()->findLayerByName(prefix);
Q_ASSERT(layer != nullptr);
LayerManager* lMgr = mEditor->layers();
lMgr->setCurrentLayer(layer);
for (int i = 0; i < finalList.size(); i++)
{
mEditor->scrubTo(finalList[i].mid(dot - digits, digits).toInt());
bool ok = mEditor->importImage(path + finalList[i]);
if (!ok) { break; }
layer->addNewKeyFrameAt(finalList[i].mid(dot - digits, digits).toInt());
if (progress.wasCanceled()) { break; }
progress.setValue(qFloor(5 + (i+1) / static_cast<qreal>(finalList.size()) * 95));
QApplication::processEvents();
}
mIsImportingImageSequence = false;
ui->scribbleArea->updateCurrentFrame();
mTimeLine->updateContent();
mEditor->layers()->notifyAnimationLengthChanged();

progress.setValue(100);
progress.close();
ImportLayersDialog *importLayers = new ImportLayersDialog(this);
importLayers->setCore(mEditor);
importLayers->exec();
}

void MainWindow2::importGIF()
Expand Down Expand Up @@ -1146,7 +1053,7 @@ void MainWindow2::lockWidgets(bool shouldLock)
mOnionSkinWidget->setFeatures(feat);
mToolOptions->setFeatures(feat);
mToolBox->setFeatures(feat);
mTimeLine->setFeatures(feat);
mTimeLine->setFeatures(feat);
}

void MainWindow2::preferences()
Expand Down Expand Up @@ -1195,7 +1102,7 @@ bool MainWindow2::newObject()

bool MainWindow2::newObjectFromPresets(int presetIndex)
{
Object* object = nullptr;
Object* object = nullptr;
QString presetFilePath = (presetIndex > 0) ? PresetDialog::getPresetPath(presetIndex) : "";
if (!presetFilePath.isEmpty())
{
Expand Down Expand Up @@ -1278,7 +1185,7 @@ void MainWindow2::setupKeyboardShortcuts()
ui->actionImport_ImageSeq->setShortcut(cmdKeySeq(CMD_IMPORT_IMAGE_SEQ));
ui->actionImport_MovieVideo->setShortcut(cmdKeySeq(CMD_IMPORT_MOVIE_VIDEO));
ui->actionImport_MovieAudio->setShortcut(cmdKeySeq(CMD_IMPORT_MOVIE_AUDIO));
ui->actionImport_Palette->setShortcut(cmdKeySeq(CMD_IMPORT_PALETTE));
ui->actionImport_Append_Palette->setShortcut(cmdKeySeq(CMD_IMPORT_PALETTE));
ui->actionImport_Sound->setShortcut(cmdKeySeq(CMD_IMPORT_SOUND));

ui->actionExport_Image->setShortcut(cmdKeySeq(CMD_EXPORT_IMAGE));
Expand Down Expand Up @@ -1373,7 +1280,7 @@ void MainWindow2::setupKeyboardShortcuts()
mColorBox->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_COLOR_WHEEL));
mColorPalette->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_COLOR_LIBRARY));
mTimeLine->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_TIMELINE));
mDisplayOptionWidget->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_DISPLAY_OPTIONS));
mDisplayOptionWidget->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_DISPLAY_OPTIONS));
mColorInspector->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_COLOR_INSPECTOR));
mOnionSkinWidget->toggleViewAction()->setShortcut(cmdKeySeq(CMD_TOGGLE_ONION_SKIN));

Expand Down
2 changes: 2 additions & 0 deletions app/src/mainwindow2.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public slots:
void importImageSequence();
void importImageSequenceNumbered();
void addLayerByFilename(QString strFilePath);
void importPredefinedImageSet();
void importLayers();
void importMovieVideo();
void importGIF();
void importMovieAudio();
Expand Down
63 changes: 60 additions & 3 deletions app/ui/mainwindow2.ui
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>24</height>
<height>19</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
Expand All @@ -66,6 +66,7 @@
<addaction name="actionImport_ImageSeqNum"/>
<addaction name="actionImport_MovieVideo"/>
<addaction name="actionImport_Gif"/>
<addaction name="actionImportLayers_from_pclx"/>
<addaction name="separator"/>
<addaction name="actionImport_Sound"/>
<addaction name="actionImport_MovieAudio"/>
Expand Down Expand Up @@ -1013,14 +1014,70 @@
<string>Peg bar Alignment</string>
</property>
</action>
<action name="actionImport_Movie_2">
<action name="actionImport_MovieVideo">
<property name="text">
<string>Movie...</string>
<string>Movie Video...</string>
</property>
</action>
<action name="actionImport_MovieAudio">
<property name="text">
<string>Movie Audio...</string>
</property>
</action>
<action name="actionImport_Append_Palette">
<property name="text">
<string>Append to Palette...</string>
</property>
</action>
<action name="actionImport_Replace_Palette">
<property name="text">
<string>Replace Palette...</string>
</property>
</action>
<action name="actionExport_Other_Palette_formats">
<property name="text">
<string>Other Palette format...</string>
</property>
</action>
<action name="actionChangeLineColorCurrent_keyframe">
<property name="text">
<string>Current keyframe</string>
</property>
</action>
<action name="actionChangeLineColorAll_keyframes_on_layer">
<property name="text">
<string>All keyframes on layer</string>
</property>
</action>
<action name="actionImportLayers_from_pclx">
<property name="text">
<string>Layers from PCLX...</string>
</property>
</action>
<action name="actionVisibilityCurrentLayerOnly">
<property name="text">
<string>Current layer only</string>
</property>
</action>
<action name="actionVisibilityRelative">
<property name="text">
<string>Relative</string>
</property>
</action>
<action name="actionVisibilityAll">
<property name="text">
<string>All layers</string>
</property>
</action>
<action name="actionOnionSkins">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Onion Skins</string>
</property>
<property name="toolTip">
<string>Onion Skins</string>
</property>
</action>
</widget>
Expand Down
51 changes: 1 addition & 50 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,53 +55,4 @@ after_build:
- if %APPVEYOR_REPO_BRANCH%==master set upload=yes
- if %APPVEYOR_REPO_BRANCH%==release set upload=yes
- if "%FORCE_NIGHTLY_UPLOAD%"=="yes" set upload=yes
- if %PLATFORM_%==x86 (
echo "-----Deploying 32 Bit Version-----" &
dir /s &
md bin\plugins\ &
echo "Copying ffmpeg plugin" &
call curl.exe -o bin\plugins\ffmpeg-4.1.1-win32-static.zip "https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-4.1.1-win32-static.zip" &
call 7z.exe x bin\plugins\ffmpeg-4.1.1-win32-static.zip -o"bin\plugins" &
echo "move ffmpeg.exe and delete leftovers" &
del bin\plugins\ffmpeg-4.1.1-win32-static.zip &
move /y bin\plugins\ffmpeg-4.1.1-win32-static\bin\ffmpeg.exe bin\plugins &
rmdir /q /s bin\plugins\ffmpeg-4.1.1-win32-static &
echo "copying qt libraries" &
windeployqt bin\pencil2d.exe &
echo "zipping" &
Rename bin Pencil2D &
call 7z.exe a "pencil2d-win32-%date:~-4,4%"-"%date:~-10,2%"-"%date:~7,2%.zip" Pencil2D\ &
echo "zipping done" &
echo "what's inside?" &
call 7z.exe l "pencil2d-win32-%date:~-4,4%"-"%date:~-10,2%"-"%date:~7,2%.zip" &
if %upload%==yes (
echo "deploying to google drive" &
cd %APPVEYOR_BUILD_FOLDER%\util &
call %PYTHON%\\python.exe nightly-build-upload.py "%WIN32_NIGHTLY_PARENT%" "%APPVEYOR_BUILD_FOLDER%\build\pencil2d-win32-%date:~-4,4%"-"%date:~-10,2%"-"%date:~7,2%.zip" &
echo "32 Bit deployed" ) )

- if %PLATFORM_%==amd64 (
echo "----- Deploying 64 Bit Version -----" &
echo "rename and zip folder" &
dir /s &
md bin\plugins\ &
echo "Copying ffmpeg plugin" &
call curl.exe -o bin\plugins\ffmpeg-4.1.1-win64-static.zip "https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-4.1.1-win64-static.zip" &
call 7z.exe x bin\plugins\ffmpeg-4.1.1-win64-static.zip -o"bin\plugins" &
echo "move ffmpeg.exe and delete ffmpeg leftovers" &
del bin\plugins\ffmpeg-4.1.1-win64-static.zip &
move /y bin\plugins\ffmpeg-4.1.1-win64-static\bin\ffmpeg.exe bin\plugins &
rmdir /q /s bin\plugins\ffmpeg-4.1.1-win64-static &
echo "copying qt libraries" &
windeployqt bin\pencil2d.exe &
echo "zipping" &
Rename bin Pencil2D &
call 7z.exe a "pencil2d-win64-%date:~-4,4%"-"%date:~-10,2%"-"%date:~7,2%.zip" Pencil2D\ &
echo "zipping done" &
echo "what's inside?" &
call 7z.exe l "pencil2d-win64-%date:~-4,4%"-"%date:~-10,2%"-"%date:~7,2%.zip" &
if %upload%==yes (
echo "deploying to google drive" &
cd %APPVEYOR_BUILD_FOLDER%\util &
call %PYTHON%\\python.exe nightly-build-upload.py "%WIN64_NIGHTLY_PARENT%" "%APPVEYOR_BUILD_FOLDER%\build\pencil2d-win64-%date:~-4,4%"-"%date:~-10,2%"-"%date:~7,2%.zip" &
echo "64 Bit Deployed" ) )
- powershell ..\util\after-build.ps1 -upload %upload% -platform %PLATFORM_% -branch %APPVEYOR_REPO_BRANCH%
10 changes: 6 additions & 4 deletions core_lib/src/util/fileformat.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ GNU General Public License for more details.
QObject::tr("Pencil formats") + " (*.pclx *.pcl);;" + QObject::tr("Pencil Project") + " (*.pclx);;" + QObject::tr("Legacy Pencil Project") + " (*.pcl)"

#define PFF_MOVIE_EXT \
QObject::tr("Movie formats") + " AVI (*.avi);;MPEG(*.mpg);;MOV(*.mov);;MP4(*.mp4);;SWF(*.swf);;FLV(*.flv);;WMV(*.wmv)"
QObject::tr("Movie formats") + "*.avi *.mpg *.mpeg *.mov *.mp4 *.mkv *.ogv *.swf *.flv *.webm *.wmv);;" \
"AVI(*.avi);;MPEG(*.mpg *.mpeg);;MOV(*.mov);;MP4(*.mp4);;MKV(*.mkv);;OGV(*.ogv)" \
";;SWF(*.swf);;FLV(*.flv);;WEBM(*.webm);;WMV(*.wmv)"

#define PFF_IMAGE_FILTER \
QObject::tr( "Image formats") + " (*.png *.jpg *.jpeg *.bmp *.tif *.tiff);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);; TIFF(*.tif *.tiff)"
QObject::tr( "Image formats") + " (*.png *.jpg *.jpeg *.bmp *.tif *.tiff);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);;TIFF(*.tif *.tiff)"

#define PFF_IMAGE_SEQ_FILTER \
QObject::tr( "Image formats") + " (*.png *.jpg *.jpeg *.bmp *.tif *.tiff);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);; TIFF(*.tif *.tiff)"
QObject::tr( "Image formats") + " (*.png *.jpg *.jpeg *.bmp *.tif *.tiff);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);;TIFF(*.tif *.tiff)"

#define PFF_PALETTE_EXT_FILTER \
QObject::tr("Palette formats") + " (*.xml *.gpl);;" + QObject::tr("Pencil Palette") + " (*.xml);;" + QObject::tr("GIMP Palette") + " (*.gpl)"
Expand All @@ -45,7 +47,7 @@ GNU General Public License for more details.
QObject::tr("Animated GIF") + " (*.gif)"

#define PFF_SOUND_EXT_FILTER \
QObject::tr("Sound formats") + " (*.wav *.mp3);;WAV (*.wav);;MP3 (*.mp3)"
QObject::tr("Sound formats") + " (*.wav *.mp3 *.wma *.ogg *.flac *.opus *.aiff *.aac *.caf);;WAV (*.wav);;MP3 (*.mp3);;WMA (*.wma);;OGG (*.ogg);;FLAC (*.flac);;Opus (*.opus);;AIFF (*.aiff);;AAC (*.aac);;CAF (*.caf)"


#define PFF_DEFAULT_PROJECT_EXT \
Expand Down
11 changes: 0 additions & 11 deletions core_lib/src/util/pencildef.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,6 @@ GNU General Public License for more details.
#define M_PI 3.14159265358979323846
#endif

#define PENCIL_MOVIE_EXT \
QString( "%1 (*.avi *.mpg *.mpeg *.mov *.mp4 *.mkv *.ogv *.swf *.flv *.webm *.wmv);;" \
"AVI(*.avi);;MPEG(*.mpg *.mpeg);;MOV(*.mov);;MP4(*.mp4);;MKV(*.mkv);;OGV(*.ogv)" \
";;SWF(*.swf);;FLV(*.flv);;WEBM(*.webm);;WMV(*.wmv)" ).arg(QObject::tr("Movies"))

#define PENCIL_IMAGE_FILTER \
QString( "%1 (*.png *.jpg *.jpeg *.bmp *.tif *.tiff);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);;TIFF(*.tif *.tiff)" ).arg(QObject::tr("Images"))

#define PENCIL_IMAGE_SEQ_FILTER \
QString( "%1 (*.png *.jpg *.jpeg *.bmp *.tif *.tiff);;PNG (*.png);;JPG(*.jpg *.jpeg);;BMP(*.bmp);;TIFF(*.tif *.tiff)" ).arg(QObject::tr("Images"))

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define S__GIT_TIMESTAMP TOSTRING(GIT_TIMESTAMP)
Expand Down
You are viewing a condensed version of this merge commit. You can view the full changes here.