Mercurial > hg > aimc
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 } |