comparison trunk/src/Modules/Output/Graphics/Devices/GraphicsOutputDeviceMovie.cc @ 398:3ee03a6b95a0

- All \t to two spaces (style guide compliance)
author tomwalters
date Fri, 15 Oct 2010 05:46:53 +0000
parents 7a573750b186
children dd13c9834ceb
comparison
equal deleted inserted replaced
397:7a573750b186 398:3ee03a6b95a0
36 * as needed until the correct signal time is reached. 36 * as needed until the correct signal time is reached.
37 */ 37 */
38 #include "Support/Common.h" 38 #include "Support/Common.h"
39 39
40 #ifdef _WINDOWS 40 #ifdef _WINDOWS
41 # include <direct.h> // for _mkdir&_rmdir 41 # include <direct.h> // for _mkdir&_rmdir
42 #else 42 #else
43 # include <sys/types.h> 43 # include <sys/types.h>
44 # include <dirent.h> // for opendir&friends 44 # include <dirent.h> // for opendir&friends
45 #endif 45 #endif
46 #include <stdio.h> 46 #include <stdio.h>
47 #include <string.h> 47 #include <string.h>
48 48
49 49
50 #include "Output/GraphicsOutputDeviceMovie.h" 50 #include "Output/GraphicsOutputDeviceMovie.h"
51 51
52 GraphicsOutputDeviceMovie::GraphicsOutputDeviceMovie(Parameters *pParam) 52 GraphicsOutputDeviceMovie::GraphicsOutputDeviceMovie(Parameters *pParam)
53 : GraphicsOutputDeviceCairo(pParam) { // or GraphicsOutputDevicePlotutils 53 : GraphicsOutputDeviceCairo(pParam) { // or GraphicsOutputDevicePlotutils
54 m_sMovieFile[0] = '\0'; 54 m_sMovieFile[0] = '\0';
55 m_sSoundFile[0] = '\0'; 55 m_sSoundFile[0] = '\0';
56 } 56 }
57 57
58 bool GraphicsOutputDeviceMovie::Initialize(const char *sSoundFile, 58 bool GraphicsOutputDeviceMovie::Initialize(const char *sSoundFile,
59 const char *sMovieFile) { 59 const char *sMovieFile) {
60 FILE *f; 60 FILE *f;
61 AIM_ASSERT(sSoundFile); 61 AIM_ASSERT(sSoundFile);
62 AIM_ASSERT(sMovieFile); 62 AIM_ASSERT(sMovieFile);
63 63
64 // Check sound file exists 64 // Check sound file exists
65 if ((f = fopen(sSoundFile, "r")) == NULL) { 65 if ((f = fopen(sSoundFile, "r")) == NULL) {
66 AIM_ERROR(_T("Couldn't open sound file '%s' for movie creation."), 66 AIM_ERROR(_T("Couldn't open sound file '%s' for movie creation."),
67 sSoundFile); 67 sSoundFile);
68 return false; 68 return false;
69 } 69 }
70 fclose(f); 70 fclose(f);
71 strcpy(m_sSoundFile, sSoundFile); 71 strcpy(m_sSoundFile, sSoundFile);
72 72
73 // Check movie output file can be made 73 // Check movie output file can be made
74 if ( (f=fopen(sMovieFile, "w"))==NULL ) { 74 if ( (f=fopen(sMovieFile, "w"))==NULL ) {
75 aimERROR(_T("Couldn't open movie file '%s' to write to."), 75 aimERROR(_T("Couldn't open movie file '%s' to write to."),
76 sMovieFile); 76 sMovieFile);
77 return false; 77 return false;
78 } 78 }
79 fclose(f); 79 fclose(f);
80 strcpy(m_sMovieFile, sMovieFile); 80 strcpy(m_sMovieFile, sMovieFile);
81 81
82 // Get a temporary image output directory 82 // Get a temporary image output directory
83 //! \warning Not really safe ... but windows has no mkdtemp() 83 //! \warning Not really safe ... but windows has no mkdtemp()
84 //! \todo Make build system check for mkdtemp() to use it when available. See TODO.txt. 84 //! \todo Make build system check for mkdtemp() to use it when available. See TODO.txt.
85 char *sTmpDir = NULL; 85 char *sTmpDir = NULL;
86 #ifdef _WINDOWS 86 #ifdef _WINDOWS
87 if ((sTmpDir = _tempnam(NULL, AIM_NAME)) 87 if ((sTmpDir = _tempnam(NULL, AIM_NAME))
88 && _mkdir(sTmpDir) >= 0) { 88 && _mkdir(sTmpDir) >= 0) {
89 strcpy(m_sDir, sTmpDir); 89 strcpy(m_sDir, sTmpDir);
90 strcat(m_sDir, "\\"); // Make sure to end with trailing slash 90 strcat(m_sDir, "\\"); // Make sure to end with trailing slash
91 } else 91 } else
92 #else 92 #else
93 strcpy(m_sDir, "/tmp/"AIM_NAME"-movie.XXXXXX"); 93 strcpy(m_sDir, "/tmp/"AIM_NAME"-movie.XXXXXX");
94 if (mkdtemp(m_sDir)) { 94 if (mkdtemp(m_sDir)) {
95 strcat(m_sDir, "/"); // Make sure to end with trailing slash 95 strcat(m_sDir, "/"); // Make sure to end with trailing slash
96 } else 96 } else
97 #endif 97 #endif
98 { 98 {
99 AIM_ERROR(_T("Couldn't create a temporary directory for movie output.")); 99 AIM_ERROR(_T("Couldn't create a temporary directory for movie output."));
100 if (sTmpDir) free(sTmpDir); 100 if (sTmpDir) free(sTmpDir);
101 return false; 101 return false;
102 } 102 }
103 if (sTmpDir) { 103 if (sTmpDir) {
104 free(sTmpDir); 104 free(sTmpDir);
105 } 105 }
106 106
107 // We want png for movie conversion 107 // We want png for movie conversion
108 //! \bug This may change the user preference in GUI, hmm what to do? See TODO.txt 108 //! \bug This may change the user preference in GUI, hmm what to do? See TODO.txt
109 m_pParam->SetString("output.img.format", "png"); 109 m_pParam->SetString("output.img.format", "png");
110 //if ( !GraphicsOutputDevicePlotutils::Initialize(m_sDir) ) { 110 //if ( !GraphicsOutputDevicePlotutils::Initialize(m_sDir) ) {
111 if ( !GraphicsOutputDeviceCairo::Initialize(m_sDir) ) { 111 if ( !GraphicsOutputDeviceCairo::Initialize(m_sDir) ) {
112 return false; 112 return false;
113 } 113 }
114 114
115 return true; 115 return true;
116 } 116 }
117 117
118 void GraphicsOutputDeviceMovie::Start() { 118 void GraphicsOutputDeviceMovie::Start() {
119 //GraphicsOutputDevicePlotutils::Start(); 119 //GraphicsOutputDevicePlotutils::Start();
120 GraphicsOutputDeviceCairo::Start(); 120 GraphicsOutputDeviceCairo::Start();
121 // Just output a single frame to get audio/video in sync, put params in there 121 // Just output a single frame to get audio/video in sync, put params in there
122 gGrab(); 122 gGrab();
123 PlotParameterScreen(); 123 PlotParameterScreen();
124 gRelease(); 124 gRelease();
125 } 125 }
126 126
127 void GraphicsOutputDeviceMovie::Stop() { 127 void GraphicsOutputDeviceMovie::Stop() {
128 // Make sure Plotutils is really done writing. 128 // Make sure Plotutils is really done writing.
129 //GraphicsOutputDevicePlotutils::Stop(); 129 //GraphicsOutputDevicePlotutils::Stop();
130 GraphicsOutputDeviceCairo::Stop(); 130 GraphicsOutputDeviceCairo::Stop();
131 CloseFile(); 131 CloseFile();
132 132
133 #ifdef __WX__ 133 #ifdef __WX__
134 // GUI only: popup dialog 134 // GUI only: popup dialog
135 #else 135 #else
136 printf("Generating movie ... \n"); 136 printf("Generating movie ... \n");
137 #endif 137 #endif
138 AIM_ASSERT(m_pParam); 138 AIM_ASSERT(m_pParam);
139 // Convert images and sound file to a movie 139 // Convert images and sound file to a movie
140 //! \warning Movie files are overwritten without warning 140 //! \warning Movie files are overwritten without warning
141 //! \bug ffmpeg only works with colour images, not with bw. So make sure to not use bw only in drawing.. 141 //! \bug ffmpeg only works with colour images, not with bw. So make sure to not use bw only in drawing..
142 // Always convert to audio stream of 44.1kHz or problems may occur in playing or conversio. 142 // Always convert to audio stream of 44.1kHz or problems may occur in playing or conversio.
143 float fFps = 1000.0 / m_pParam->GetFloat("output.frameperiod"); 143 float fFps = 1000.0 / m_pParam->GetFloat("output.frameperiod");
144 char sffmpegPath[1024]; 144 char sffmpegPath[1024];
145 if (!m_pParam->IsSet("output.ffmpeg_path")) { 145 if (!m_pParam->IsSet("output.ffmpeg_path")) {
146 strcpy(sffmpegPath,"ffmpeg"); 146 strcpy(sffmpegPath,"ffmpeg");
147 } else { 147 } else {
148 strcpy(sffmpegPath, m_pParam->GetString("output.ffmpeg_path")); 148 strcpy(sffmpegPath, m_pParam->GetString("output.ffmpeg_path"));
149 } 149 }
150 char sCodecOptions[1024]; 150 char sCodecOptions[1024];
151 if (!m_pParam->IsSet("output.ffmpeg_codec_options")) { 151 if (!m_pParam->IsSet("output.ffmpeg_codec_options")) {
152 strcpy(sCodecOptions,""); 152 strcpy(sCodecOptions,"");
153 } else { 153 } else {
154 strcpy(sCodecOptions, m_pParam->GetString("output.ffmpeg_codec_options")); 154 strcpy(sCodecOptions, m_pParam->GetString("output.ffmpeg_codec_options"));
155 } 155 }
156 156
157 char sCmdLine[1024]; //!\todo check that snprintf does not want a larger buffer 157 char sCmdLine[1024]; //!\todo check that snprintf does not want a larger buffer
158 snprintf(sCmdLine, sizeof(sCmdLine)/sizeof(sCmdLine[0]), 158 snprintf(sCmdLine, sizeof(sCmdLine)/sizeof(sCmdLine[0]),
159 "%s -r %.2f -y -i \"%s\" -i \"%s%%06d.png\" " 159 "%s -r %.2f -y -i \"%s\" -i \"%s%%06d.png\" "
160 "-title \"%s\" -comment \"Generated by "AIM_NAME" "AIM_VERSION_STRING"\" " 160 "-title \"%s\" -comment \"Generated by "AIM_NAME" "AIM_VERSION_STRING"\" "
161 "-sameq -r %.2f -ar 44100 -acodec pcm_s16le %s \"%s\"", 161 "-sameq -r %.2f -ar 44100 -acodec pcm_s16le %s \"%s\"",
162 sffmpegPath, fFps, m_sSoundFile, m_sDir, 162 sffmpegPath, fFps, m_sSoundFile, m_sDir,
163 m_pParam->GetString("output.movie.title"), 163 m_pParam->GetString("output.movie.title"),
164 fFps, sCodecOptions, m_sMovieFile); 164 fFps, sCodecOptions, m_sMovieFile);
165 printf(sCmdLine); 165 printf(sCmdLine);
166 printf("\n"); 166 printf("\n");
167 if (system(sCmdLine)) { 167 if (system(sCmdLine)) {
168 AIM_ERROR(_T("Couldn't create movie output.")); 168 AIM_ERROR(_T("Couldn't create movie output."));
169 } 169 }
170 170
171 #ifdef __WX__ 171 #ifdef __WX__
172 // GUI only: close dialog again 172 // GUI only: close dialog again
173 #endif 173 #endif
174 // Remove files in temporary directory and the dir itself 174 // Remove files in temporary directory and the dir itself
175 //! \todo make portable function, possibly decided on by build system 175 //! \todo make portable function, possibly decided on by build system
176 #ifdef _WINDOWS 176 #ifdef _WINDOWS
177 HANDLE hList; 177 HANDLE hList;
178 WIN32_FIND_DATA FileData; 178 WIN32_FIND_DATA FileData;
179 snprintf(sCmdLine, sizeof(sCmdLine)/sizeof(sCmdLine[0]), "%s/*.*", m_sDir); 179 snprintf(sCmdLine, sizeof(sCmdLine)/sizeof(sCmdLine[0]), "%s/*.*", m_sDir);
180 if ((hList = FindFirstFile(sCmdLine, &FileData)) == INVALID_HANDLE_VALUE) { 180 if ((hList = FindFirstFile(sCmdLine, &FileData)) == INVALID_HANDLE_VALUE) {
181 AIM_ERROR(_T("Couldn't remove files from temporary directory.")); 181 AIM_ERROR(_T("Couldn't remove files from temporary directory."));
182 return; 182 return;
183 } 183 }
184 bool bRMfinished = false; 184 bool bRMfinished = false;
185 while (!bRMfinished) { 185 while (!bRMfinished) {
186 snprintf(sCmdLine, 186 snprintf(sCmdLine,
187 sizeof(sCmdLine)/sizeof(sCmdLine[0]), 187 sizeof(sCmdLine)/sizeof(sCmdLine[0]),
188 "%s%s", 188 "%s%s",
189 m_sDir, 189 m_sDir,
190 FileData.cFileName); 190 FileData.cFileName);
191 remove(sCmdLine); 191 remove(sCmdLine);
192 if (!FindNextFile(hList, &FileData) && GetLastError() == ERROR_NO_MORE_FILES) { 192 if (!FindNextFile(hList, &FileData) && GetLastError() == ERROR_NO_MORE_FILES) {
193 bRMfinished = true; 193 bRMfinished = true;
194 } 194 }
195 } 195 }
196 FindClose(hList); 196 FindClose(hList);
197 _rmdir(m_sDir); 197 _rmdir(m_sDir);
198 #else 198 #else
199 DIR *dir; 199 DIR *dir;
200 struct dirent *dirent; 200 struct dirent *dirent;
201 if (!(dir = opendir(m_sDir))) { 201 if (!(dir = opendir(m_sDir))) {
202 AIM_ERROR(_T("Couldn't remove files in temporary directory.")); 202 AIM_ERROR(_T("Couldn't remove files in temporary directory."));
203 return; 203 return;
204 } 204 }
205 while (dirent = readdir(dir)) { 205 while (dirent = readdir(dir)) {
206 snprintf(sCmdLine, 206 snprintf(sCmdLine,
207 sizeof(sCmdLine)/sizeof(sCmdLine[0]), 207 sizeof(sCmdLine)/sizeof(sCmdLine[0]),
208 "%s%s", 208 "%s%s",
209 m_sDir, 209 m_sDir,
210 dirent->d_name); 210 dirent->d_name);
211 unlink(sCmdLine); 211 unlink(sCmdLine);
212 } 212 }
213 closedir(dir); 213 closedir(dir);
214 rmdir(m_sDir); 214 rmdir(m_sDir);
215 #endif 215 #endif
216 } 216 }
217 217
218 void GraphicsOutputDeviceMovie::PlotParameterScreen() { 218 void GraphicsOutputDeviceMovie::PlotParameterScreen() {
219 AIM_ASSERT(m_pParam); 219 AIM_ASSERT(m_pParam);
220 char sStr[50]; 220 char sStr[50];
221 int lineno = 1; 221 int lineno = 1;
222 222
223 float fMarL = m_pParam->GetFloat(_S("graph.margin.left")); 223 float fMarL = m_pParam->GetFloat(_S("graph.margin.left"));
224 float fMarT = m_pParam->GetFloat(_S("graph.margin.top")); 224 float fMarT = m_pParam->GetFloat(_S("graph.margin.top"));
225 float fTextHeight = 1.0f / 50.0f * 1.2; // change this when fontsizing is there! 225 float fTextHeight = 1.0f / 50.0f * 1.2; // change this when fontsizing is there!
226 226
227 gText2f(fMarL, 1-(fMarT+fTextHeight*lineno++), 227 gText2f(fMarL, 1-(fMarT+fTextHeight*lineno++),
228 _S("AIM-C")); 228 _S("AIM-C"));
229 gText2f(fMarL, 229 gText2f(fMarL,
230 1-(fMarT+fTextHeight*lineno++), 230 1-(fMarT+fTextHeight*lineno++),
231 _S("(c) 2006-2010, Thomas Walters, Willem van Engen")); 231 _S("(c) 2006-2010, Thomas Walters, Willem van Engen"));
232 gText2f(fMarL, 232 gText2f(fMarL,
233 1-(fMarT+fTextHeight*lineno++), 233 1-(fMarT+fTextHeight*lineno++),
234 _S("http://aimc.acousticscale.org/")); 234 _S("http://aimc.acousticscale.org/"));
235 lineno++; 235 lineno++;
236 236
237 static const char *pPlotParams[] = { 237 static const char *pPlotParams[] = {
238 _S("input.buffersize"), 238 _S("input.buffersize"),
239 _S("input.samplerate"), 239 _S("input.samplerate"),
240 _S("bmm.freqstart"), 240 _S("bmm.freqstart"),
241 _S("bmm.freqend"), 241 _S("bmm.freqend"),
242 _S("bmm.numchannels"), 242 _S("bmm.numchannels"),
243 _S("preset.name"), 243 _S("preset.name"),
244 _S("preset.title"), 244 _S("preset.title"),
245 NULL 245 NULL
246 }; 246 };
247 for (int i = 0; pPlotParams[i]; i++) { 247 for (int i = 0; pPlotParams[i]; i++) {
248 snprintf(sStr, 248 snprintf(sStr,
249 sizeof(sStr)/sizeof(sStr[0]), _S("%s=%s"), 249 sizeof(sStr)/sizeof(sStr[0]), _S("%s=%s"),
250 pPlotParams[i], 250 pPlotParams[i],
251 m_pParam->GetString(pPlotParams[i])); 251 m_pParam->GetString(pPlotParams[i]));
252 gText2f(fMarL, 252 gText2f(fMarL,
253 1-(fMarT+fTextHeight*lineno++), 253 1-(fMarT+fTextHeight*lineno++),
254 sStr); 254 sStr);
255 } 255 }
256 } 256 }