1 /*
2 * Project: VizKit
3 * Version: 2.3
4
5 * Date: 20090823
6 * File: VisualDataStore.cpp
7 *
8 */
9
10 /***************************************************************************
11
12 Copyright (c) 2004-2009 Heiko Wichmann (http://www.imagomat.de/vizkit)
13
14
15 This software is provided 'as-is', without any expressed or implied warranty.
16 In no event will the authors be held liable for any damages
17 arising from the use of this software.
18
19 Permission is granted to anyone to use this software for any purpose,
20 including commercial applications, and to alter it and redistribute it
21 freely, subject to the following restrictions:
22
23 1. The origin of this software must not be misrepresented;
24 you must not claim that you wrote the original software.
25 If you use this software in a product, an acknowledgment
26 in the product documentation would be appreciated
27 but is not required.
28
29 2. Altered source versions must be plainly marked as such,
30 and must not be misrepresented as being the original software.
31
32 3. This notice may not be removed or altered from any source distribution.
33
34 ***************************************************************************/
35
36 #include "VisualDataStore.h"
37 #include "VisualHostCommunication.h"
38 #include "VisualErrorHandling.h"
39 #include "VisualAudioLab.h"
40 #include "VisualConfiguration.h"
41 #include "VisualPreferences.h"
42 #include "VisualThreading.h"
43 #include "VisualNotification.h"
44 #include "VisualString.h"
45 #include "VisualFile.h"
46 #include "VisualStyledString.h"
47 #include "VisualImage.h"
48 #include "VisualPlayerState.h"
49 #include "VisualQuickTime.h"
50
51 #if TARGET_OS_MAC
52 #include "VisualAppleScript.h"
53 #endif
54 #if TARGET_OS_MAC
55 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacMemory.h> // HUnlock
56 #endif
57
58
59 #if TARGET_OS_WIN
60 #include "iTunesCOMInterface.h"
61 #endif
62
63
64 using namespace VizKit;
65
66
67 const size_t VisualDataStore::audioMetaDataHistoryCount = 2;
68
69 bool VisualDataStore::lyricsCreationThreadIsRunning = false;
70
71 VisualDataStore* VisualDataStore::theVisualDataStore = NULL; // singleton
72
73
74 const VisualItemIdentifier VisualDataStore::albumCoverArtworkImageId;
75 VisualItemIdentifier VisualDataStore::fileWithLyricsStringId;
76 VisualItemIdentifier VisualDataStore::trackIdentifierOfLyricsMetadata;
77 const VisualItemIdentifier VisualDataStore::styledTrackInfoStringId;
78 const VisualItemIdentifier VisualDataStore::styledTrackLyricsStringId;
79 const VisualItemIdentifier VisualDataStore::updateInformationStringId;
80
81
VisualDataStore()82 VisualDataStore::VisualDataStore() {
83 VisualAudioMetaData emptyVisualAudioMetaData;
84 for (uint8 i = 0; i < audioMetaDataHistoryCount; i++) {
85 audioMetaDataHistory.push_back(emptyVisualAudioMetaData);
86 }
87 currAudioMetaDataHistoryIdx = audioMetaDataHistoryCount - 1;
88 appVersionMajorNum = 0;
89 appVersionMinorNum = 0;
90 }
91
92
~VisualDataStore()93 VisualDataStore::~VisualDataStore() {
94
95 processInfoMap.clear();
96
97 audioMetaDataHistory.clear();
98 }
99
100
getInstance()101 VisualDataStore* VisualDataStore::getInstance() {
102 if (theVisualDataStore == NULL) {
103 theVisualDataStore = new VisualDataStore;
104 }
105 return theVisualDataStore;
106 }
107
108
dispose()109 void VisualDataStore::dispose() {
110 if (theVisualDataStore != NULL) {
111 delete theVisualDataStore;
112 theVisualDataStore = NULL;
113 }
114 }
115
116
setValue(const ValueKey anIdentifier,const int anIntValue)117 void VisualDataStore::setValue(const ValueKey anIdentifier, const int anIntValue) {
118 bool found = false;
119
120 theVisualDataStore = VisualDataStore::getInstance();
121 for (ValueVectorIterator it = theVisualDataStore->valueVector.begin(); it != theVisualDataStore->valueVector.end(); it++) {
122 if ((*it)->key == anIdentifier && (*it)->dataType == kIntPrefType) {
123 (*it)->valueInt = anIntValue;
124 found = true;
125 }
126 }
127 if (found == false) {
128 Value* aValue = new Value;
129 aValue->dataType = kIntPrefType;
130 aValue->key = anIdentifier;
131 aValue->valueInt = anIntValue;
132 strcpy(aValue->valueChar, "\0");
133 aValue->valueBool = false;
134 theVisualDataStore->valueVector.push_back(aValue);
135 }
136 }
137
138
setValue(const ValueKey anIdentifier,const float aFloatValue)139 void VisualDataStore::setValue(const ValueKey anIdentifier, const float aFloatValue) {
140 bool found = false;
141
142 theVisualDataStore = VisualDataStore::getInstance();
143 for (ValueVectorIterator it = theVisualDataStore->valueVector.begin(); it != theVisualDataStore->valueVector.end(); it++) {
144 if ((*it)->key == anIdentifier && (*it)->dataType == kFloatPrefType) {
145 (*it)->valueFloat = aFloatValue;
146 found = true;
147 }
148 }
149 if (found == false) {
150 Value* aValue = new Value;
151 aValue->dataType = kFloatPrefType;
152 aValue->key = anIdentifier;
153 aValue->valueFloat = aFloatValue;
154 aValue->valueInt = 0;
155 strcpy(aValue->valueChar, "\0");
156 aValue->valueBool = false;
157 theVisualDataStore->valueVector.push_back(aValue);
158 }
159 }
160
161
setValue(const ValueKey anIdentifier,const char * const aCharValue)162 void VisualDataStore::setValue(const ValueKey anIdentifier, const char* const aCharValue) {
163 bool found = false;
164
165 char errStr[256] = "\0";
166 if (strlen(aCharValue) > 255) {
167 strncat(errStr, aCharValue, 255);
168 writeLog("char value too long");
169 return;
170 }
171
172 theVisualDataStore = VisualDataStore::getInstance();
173 for (ValueVectorIterator it = theVisualDataStore->valueVector.begin(); it != theVisualDataStore->valueVector.end(); it++) {
174 if ((*it)->key == anIdentifier && (*it)->dataType == kCharPrefType) {
175 strcpy((*it)->valueChar, aCharValue);
176 found = true;
177 }
178 }
179 if (found == false) {
180 Value* aValue = new Value;
181 aValue->dataType = kCharPrefType;
182 aValue->key = anIdentifier;
183 strcpy(aValue->valueChar, aCharValue);
184 aValue->valueInt = 0;
185 aValue->valueBool = false;
186 theVisualDataStore->valueVector.push_back(aValue);
187 }
188 }
189
190
setValue(const ValueKey anIdentifier,const bool aBoolValue)191 void VisualDataStore::setValue(const ValueKey anIdentifier, const bool aBoolValue) {
192 bool found = false;
193 theVisualDataStore = VisualDataStore::getInstance();
194 for (ValueVectorIterator it = theVisualDataStore->valueVector.begin(); it != theVisualDataStore->valueVector.end(); it++) {
195 if ((*it)->key == anIdentifier && (*it)->dataType == kBoolPrefType) {
196 (*it)->valueBool = aBoolValue;
197 found = true;
198 }
199 }
200 if (found == false) {
201 Value* aValue = new Value;
202 aValue->dataType = kBoolPrefType;
203 aValue->key = anIdentifier;
204 aValue->valueBool = aBoolValue;
205 aValue->valueInt = 0;
206 aValue->valueFloat = 0.0f;
207 strcpy(aValue->valueChar, "\0");
208 theVisualDataStore->valueVector.push_back(aValue);
209 }
210 }
211
212
getValueInt(const ValueKey anIdentifier,bool * wasSet)213 int VisualDataStore::getValueInt(const ValueKey anIdentifier, bool* wasSet) {
214
215 int prefVal = 0;
216
217 if (wasSet != NULL) {
218 *wasSet = false;
219 }
220
221 theVisualDataStore = VisualDataStore::getInstance();
222 for (ValueVectorIterator it = theVisualDataStore->valueVector.begin(); it != theVisualDataStore->valueVector.end(); it++) {
223 if ((*it)->key == anIdentifier && (*it)->dataType == kIntPrefType) {
224 if (wasSet != NULL) {
225 *wasSet = true;
226 }
227 return (*it)->valueInt;
228 }
229 }
230
231 return prefVal;
232 }
233
234
getValueFloat(const ValueKey anIdentifier,bool * wasSet)235 float VisualDataStore::getValueFloat(const ValueKey anIdentifier, bool* wasSet) {
236
237 float prefVal = 0;
238
239 if (wasSet != NULL) {
240 *wasSet = false;
241 }
242
243 theVisualDataStore = VisualDataStore::getInstance();
244 for (ValueVectorIterator it = theVisualDataStore->valueVector.begin(); it != theVisualDataStore->valueVector.end(); it++) {
245 if ((*it)->key == anIdentifier && (*it)->dataType == kFloatPrefType) {
246 if (wasSet != NULL) {
247 *wasSet = true;
248 }
249 return (*it)->valueFloat;
250 }
251 }
252
253 return prefVal;
254 }
255
256
getValueChar(const ValueKey anIdentifier,char * outPrefVal,bool * wasSet)257 void VisualDataStore::getValueChar(const ValueKey anIdentifier, char* outPrefVal, bool* wasSet) {
258
259 strcpy(outPrefVal, "\0");
260
261 if (wasSet != NULL) {
262 *wasSet = false;
263 }
264
265 theVisualDataStore = VisualDataStore::getInstance();
266 for (ValueVectorIterator it = theVisualDataStore->valueVector.begin(); it != theVisualDataStore->valueVector.end(); it++) {
267 if ((*it)->key == anIdentifier && (*it)->dataType == kCharPrefType) {
268 if (wasSet != NULL) {
269 *wasSet = true;
270 }
271 strncat(outPrefVal, (*it)->valueChar, strlen((*it)->valueChar));
272 return;
273 }
274 }
275
276 }
277
278
getValueBool(const ValueKey anIdentifier,bool * wasSet)279 bool VisualDataStore::getValueBool(const ValueKey anIdentifier, bool* wasSet) {
280
281 bool prefVal = false;
282
283 if (wasSet != NULL) {
284 *wasSet = false;
285 }
286
287 theVisualDataStore = VisualDataStore::getInstance();
288 for (ValueVectorIterator it = theVisualDataStore->valueVector.begin(); it != theVisualDataStore->valueVector.end(); it++) {
289 if ((*it)->key == anIdentifier && (*it)->dataType == kBoolPrefType) {
290 if (wasSet != NULL) {
291 *wasSet = true;
292 }
293 return (*it)->valueBool;
294 }
295 }
296
297 return prefVal;
298 }
299
300
setAppVersionNum(uint8 majorVersionNum,uint8 minorVersionNum)301 void VisualDataStore::setAppVersionNum(uint8 majorVersionNum, uint8 minorVersionNum) {
302 theVisualDataStore = VisualDataStore::getInstance();
303 theVisualDataStore->appVersionMajorNum = majorVersionNum;
304 theVisualDataStore->appVersionMinorNum = minorVersionNum;
305 }
306
307
getAppVersionMajorNum()308 uint8 VisualDataStore::getAppVersionMajorNum() {
309 theVisualDataStore = VisualDataStore::getInstance();
310 return theVisualDataStore->appVersionMajorNum;
311 }
312
313
getAppVersionMinorNum()314 uint8 VisualDataStore::getAppVersionMinorNum() {
315 theVisualDataStore = VisualDataStore::getInstance();
316 return theVisualDataStore->appVersionMinorNum;
317 }
318
319
resetCurrAudioMetaData(void)320 void VisualDataStore::resetCurrAudioMetaData(void) {
321 theVisualDataStore = VisualDataStore::getInstance();
322 theVisualDataStore->currAudioMetaData.init();
323 }
324
325
setAudioTrackName(const uint16 * const audioTrackName,uint32 audioTrackNameLength)326 void VisualDataStore::setAudioTrackName(const uint16* const audioTrackName, uint32 audioTrackNameLength) {
327 theVisualDataStore = VisualDataStore::getInstance();
328 VisualString trackName(audioTrackName, audioTrackNameLength);
329 theVisualDataStore->currAudioMetaData.setTrackName(trackName);
330 }
331
332
setAudioTrackArtistName(const uint16 * const audioTrackArtistName,uint32 audioTrackArtistNameLength)333 void VisualDataStore::setAudioTrackArtistName(const uint16* const audioTrackArtistName, uint32 audioTrackArtistNameLength) {
334 theVisualDataStore = VisualDataStore::getInstance();
335 VisualString trackArtistName(audioTrackArtistName, audioTrackArtistNameLength);
336 theVisualDataStore->currAudioMetaData.setTrackArtist(trackArtistName);
337 }
338
339
setAudioTrackAlbumName(const uint16 * const audioTrackAlbumName,uint32 audioTrackAlbumNameLength)340 void VisualDataStore::setAudioTrackAlbumName(const uint16* const audioTrackAlbumName, uint32 audioTrackAlbumNameLength) {
341 theVisualDataStore = VisualDataStore::getInstance();
342 VisualString trackAlbumName(audioTrackAlbumName, audioTrackAlbumNameLength);
343 theVisualDataStore->currAudioMetaData.setTrackAlbum(trackAlbumName);
344 }
345
346
setAudioTrackComposer(const uint16 * const audioTrackComposer,uint32 audioTrackComposerLength)347 void VisualDataStore::setAudioTrackComposer(const uint16* const audioTrackComposer, uint32 audioTrackComposerLength) {
348 theVisualDataStore = VisualDataStore::getInstance();
349 VisualString trackComposer(audioTrackComposer, audioTrackComposerLength);
350 theVisualDataStore->currAudioMetaData.setTrackComposer(trackComposer);
351 }
352
353
setAudioStreamTitle(const char * const audioStreamTitle,uint32 audioStreamTitleLength)354 void VisualDataStore::setAudioStreamTitle(const char* const audioStreamTitle, uint32 audioStreamTitleLength) {
355 theVisualDataStore = VisualDataStore::getInstance();
356 VisualString streamTitle(audioStreamTitle, audioStreamTitleLength);
357 theVisualDataStore->currAudioMetaData.setStreamTitle(streamTitle);
358 }
359
360
setAudioStreamTitle(const uint16 * const audioStreamTitle,uint32 audioStreamTitleLength)361 void VisualDataStore::setAudioStreamTitle(const uint16* const audioStreamTitle, uint32 audioStreamTitleLength) {
362 theVisualDataStore = VisualDataStore::getInstance();
363 VisualString streamTitle(audioStreamTitle, audioStreamTitleLength);
364 theVisualDataStore->currAudioMetaData.setStreamTitle(streamTitle);
365 }
366
367
setAudioStreamMessage(const char * const audioStreamMessage,uint32 audioStreamMessageLength)368 void VisualDataStore::setAudioStreamMessage(const char* const audioStreamMessage, uint32 audioStreamMessageLength) {
369 theVisualDataStore = VisualDataStore::getInstance();
370 VisualString streamMessage(audioStreamMessage, audioStreamMessageLength);
371 theVisualDataStore->currAudioMetaData.setStreamMessage(streamMessage);
372 }
373
374
setAudioStreamMessage(const uint16 * const audioStreamMessage,uint32 audioStreamMessageLength)375 void VisualDataStore::setAudioStreamMessage(const uint16* const audioStreamMessage, uint32 audioStreamMessageLength) {
376 theVisualDataStore = VisualDataStore::getInstance();
377 VisualString streamMessage(audioStreamMessage, audioStreamMessageLength);
378 theVisualDataStore->currAudioMetaData.setStreamMessage(streamMessage);
379 }
380
381
setAudioStreamURL(const char * const audioStreamURL,uint32 audioStreamURLLength)382 void VisualDataStore::setAudioStreamURL(const char* const audioStreamURL, uint32 audioStreamURLLength) {
383 theVisualDataStore = VisualDataStore::getInstance();
384 VisualString streamURL(audioStreamURL, audioStreamURLLength);
385 theVisualDataStore->currAudioMetaData.setStreamURL(streamURL);
386 }
387
388
setAudioStreamURL(const uint16 * const audioStreamURL,uint32 audioStreamURLLength)389 void VisualDataStore::setAudioStreamURL(const uint16* const audioStreamURL, uint32 audioStreamURLLength) {
390 theVisualDataStore = VisualDataStore::getInstance();
391 VisualString streamURL(audioStreamURL, audioStreamURLLength);
392 theVisualDataStore->currAudioMetaData.setStreamURL(streamURL);
393 }
394
395
setAudioTrackSizeInBytes(int sizeInBytes)396 void VisualDataStore::setAudioTrackSizeInBytes(int sizeInBytes) {
397 theVisualDataStore = VisualDataStore::getInstance();
398 theVisualDataStore->currAudioMetaData.setTrackSizeInBytes(sizeInBytes);
399 }
400
401
setAudioTrackYear(uint16 aYear)402 void VisualDataStore::setAudioTrackYear(uint16 aYear) {
403 theVisualDataStore = VisualDataStore::getInstance();
404 theVisualDataStore->currAudioMetaData.setYear(aYear);
405 }
406
407
setAudioDataIsStream(bool isStream)408 void VisualDataStore::setAudioDataIsStream(bool isStream) {
409 theVisualDataStore = VisualDataStore::getInstance();
410 theVisualDataStore->currAudioMetaData.setIsStream(isStream);
411 }
412
413
setLyricsOfCurrentTrack(const VisualString & lyricsString)414 void VisualDataStore::setLyricsOfCurrentTrack(const VisualString& lyricsString) {
415 theVisualDataStore = VisualDataStore::getInstance();
416
417 /*
418 VisualFile aFile;
419 aFile.initWithUserDesktopDirectory();
420 VisualString fileName;
421 fileName.initWithUTF8Buffer("lyricsTest.txt", 15);
422 aFile.appendFileName(fileName);
423 const uint16* const data = lyricsString.clone()->getUtf16Representation();
424 uint32 length = lyricsString.getNumberOfCharacters();
425 VisualFile::writeDataToFile((void**)&data, length * sizeof(uint16), aFile);
426 */
427
428 VisualString* normalizedLyrics = lyricsString.clone();
429 if (normalizedLyrics) {
430 normalizedLyrics->normalizeLineEndings();
431 theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].setTrackLyrics(*normalizedLyrics);
432 delete normalizedLyrics;
433 }
434 }
435
436
analyzeCurrentlySetMetadata()437 bool VisualDataStore::analyzeCurrentlySetMetadata() {
438 bool audioTrackDidChange = false;
439 theVisualDataStore = VisualDataStore::getInstance();
440 if (theVisualDataStore->currAudioMetaData != theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx]) {
441 theVisualDataStore->advanceAudioMetaDataHistory();
442 theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx] = theVisualDataStore->currAudioMetaData;
443 audioTrackDidChange = true;
444 }
445 return audioTrackDidChange;
446 }
447
448
advanceAudioMetaDataHistory()449 void VisualDataStore::advanceAudioMetaDataHistory() {
450 if ((this->currAudioMetaDataHistoryIdx + 1) >= this->audioMetaDataHistory.size()) {
451 this->currAudioMetaDataHistoryIdx = 0;
452 } else {
453 this->currAudioMetaDataHistoryIdx++;
454 }
455 }
456
457
getInfoOfCurrentAudioDataForDisplay()458 VisualString VisualDataStore::getInfoOfCurrentAudioDataForDisplay() {
459 VisualString displayInfo;
460 if (VisualDataStore::currentlyPlayingAudioIsStream()) {
461 const VisualString& streamTitle = theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getStreamTitle();
462 const VisualString& streamMessage = theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getStreamMessage();
463 if (!streamTitle.isEmpty()) {
464 displayInfo = streamTitle;
465 } else if (!streamMessage.isEmpty()) {
466 displayInfo = streamMessage;
467 }
468 } else {
469 const VisualString& trackArtist = theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getTrackArtist();
470 if (!trackArtist.isEmpty()) {
471 displayInfo = trackArtist;
472 }
473 const VisualString& trackName = theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getTrackName();
474 if (!trackName.isEmpty()) {
475 if (!displayInfo.isEmpty()) {
476 char trackInfoDisplayItemsDelimiterCharacters[32];
477 VisualPreferences::getValue(VisualPreferences::kTrackInfoDisplayItemsDelimiterCharacters, trackInfoDisplayItemsDelimiterCharacters);
478 displayInfo = (displayInfo + trackInfoDisplayItemsDelimiterCharacters);
479 }
480 displayInfo = (displayInfo + trackName);
481 }
482 }
483 return displayInfo;
484 }
485
486
getTrackSizeInBytes()487 uint32 VisualDataStore::getTrackSizeInBytes() {
488 theVisualDataStore = VisualDataStore::getInstance();
489 return theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getTrackSizeInBytes();
490 }
491
492
getTrackYear()493 uint16 VisualDataStore::getTrackYear() {
494 theVisualDataStore = VisualDataStore::getInstance();
495 return theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getYear();
496 }
497
498
getNameOfCurrentTrack()499 VisualString VisualDataStore::getNameOfCurrentTrack() {
500 theVisualDataStore = VisualDataStore::getInstance();
501 return theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getTrackName();
502 }
503
504
getArtistOfCurrentTrack()505 VisualString VisualDataStore::getArtistOfCurrentTrack() {
506 theVisualDataStore = VisualDataStore::getInstance();
507 return theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getTrackArtist();
508 }
509
510
getAlbumOfCurrentTrack()511 VisualString VisualDataStore::getAlbumOfCurrentTrack() {
512 theVisualDataStore = VisualDataStore::getInstance();
513 return theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getTrackAlbum();
514 }
515
516
getLyricsOfCurrentTrack()517 VisualString VisualDataStore::getLyricsOfCurrentTrack() {
518 return theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getTrackLyrics();
519 }
520
521
getIdentifierOfCurrentTrack()522 VisualItemIdentifier VisualDataStore::getIdentifierOfCurrentTrack() {
523 return theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getTrackIdentifier();
524 }
525
526
currentlyPlayingAudioIsStream(void)527 bool VisualDataStore::currentlyPlayingAudioIsStream(void) {
528 return theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].getIsStream();
529 }
530
531
setProcessInfo(const char * const labelStr,const char * const valueStr)532 void VisualDataStore::setProcessInfo(const char* const labelStr, const char* const valueStr) {
533 std::string labelString(labelStr);
534 std::string valueString(valueStr);
535 ProcessInfoMapIterator it;
536 theVisualDataStore = VisualDataStore::getInstance();
537 it = theVisualDataStore->processInfoMap.find(labelString);
538 if (it == theVisualDataStore->processInfoMap.end()) {
539 theVisualDataStore->processInfoMap[labelString] = valueString;
540 } else {
541 it->second = valueString;
542 }
543 }
544
545
getProcessInfoMap()546 const std::map<std::string, std::string>* const VisualDataStore::getProcessInfoMap() {
547 theVisualDataStore = VisualDataStore::getInstance();
548 return &theVisualDataStore->processInfoMap;
549 }
550
551
createCoverArtImage()552 VisualImage* VisualDataStore::createCoverArtImage() {
553
554 size_t numberOfBytes = 0;
555 uint16 numberOfArtworks = 0;
556 void* albumCoverArtworkImageData = NULL;
557
558 numberOfArtworks = VisualHostCommunication::getCurrentTrackCoverArt(&albumCoverArtworkImageData, (uint32&)numberOfBytes);
559
560 if (numberOfArtworks == 0) return NULL;
561
562 VisualImage* anImage = new VisualImage;
563 const char* coverArtDataPtr = (const char*)albumCoverArtworkImageData;
564 bool success = anImage->initWithEncodedData(coverArtDataPtr, numberOfBytes);
565
566 VisualHostCommunication::dispose();
567
568 if (!success) {
569 return NULL;
570 } else if (anImage->isEmpty()) {
571 delete anImage;
572 return NULL;
573 }
574
575 return anImage;
576 }
577
578
createLyricsOfCurrentTrack()579 bool VisualDataStore::createLyricsOfCurrentTrack() {
580 bool success = false;
581 if (VisualDataStore::lyricsCreationThreadIsRunning == true) return false;
582 success = VisualThreading::createThread((ThreadingFuncPtr)VisualDataStore::writeLyricsToFile);
583 return success;
584 }
585
586
587 #if TARGET_OS_MAC
writeLyricsToFile(void * parameter)588 OSStatus VisualDataStore::writeLyricsToFile(void* parameter) {
589
590 bool success = true;
591
592 VisualDataStore::lyricsCreationThreadIsRunning = true;
593
594 VisualItemIdentifier currTrackId = VisualDataStore::getIdentifierOfCurrentTrack();
595 VisualDataStore::trackIdentifierOfLyricsMetadata = currTrackId;
596
597 bool debug = false;
598
599 if (debug == true) {
600 writeLog("writeLyricsToFile (begin)");
601 }
602
603 VisualPlayerState* theVisualPlayerState = VisualPlayerState::getInstance();
604
605 VisualString tempFileName = VisualString("VizKitLyrics.tmp.txt");
606 VisualFile tempFile;
607 success = tempFile.initWithDirectoryOfTemporaryItems();
608 if (!success) {
609 return (OSStatus)1001;
610 }
611 success = tempFile.appendFileName(tempFileName);
612 if (!success) {
613 return (OSStatus)1002;
614 }
615
616 if ((theVisualPlayerState->getPlayerShowMode() & kIsShowing) != kIsShowing) {
617 return (OSStatus)1003;
618 }
619
620 VisualFile appleScriptFile;
621 success = appleScriptFile.initWithResourcesDirectory();
622 if (!success) {
623 return (OSStatus)1004;
624 }
625 VisualString appleScriptFileName = VisualString("getLyrics.applescript");
626 success = appleScriptFile.appendFileName(appleScriptFileName);
627 if (!success) {
628 return (OSStatus)1005;
629 }
630
631 if (debug == true) {
632 VisualString appleScriptFilePath;
633 appleScriptFile.getFilePath(appleScriptFilePath);
634 VisualString tempFilePath;
635 tempFile.getFilePath(tempFilePath);
636 char logStr[256];
637 sprintf(logStr, "before executeScriptFile(), %s %s", appleScriptFilePath.getUtf8Representation(), tempFilePath.getUtf8Representation());
638 writeLog(logStr);
639 }
640
641 VisualAppleScript::executeScriptFile(appleScriptFile);
642
643 if (debug == true) {
644 writeLog("after executeScriptFile()");
645 }
646
647 VisualNotification lyricsAreWrittenIntoTempFileNotification;
648 lyricsAreWrittenIntoTempFileNotification.setKey(kLyricsAreWrittenIntoTempFileMsg);
649 lyricsAreWrittenIntoTempFileNotification.setObject(tempFile);
650 lyricsAreWrittenIntoTempFileNotification.post();
651
652 if (debug == true) {
653 writeLog("---------------------- writeLyricsToFile (end)");
654 }
655
656 VisualDataStore::lyricsCreationThreadIsRunning = false;
657
658 return noErr;
659 }
660
661 #endif
662
663 #if TARGET_OS_WIN
writeLyricsToFile(LPVOID lpParam)664 DWORD WINAPI VisualDataStore::writeLyricsToFile(LPVOID lpParam) {
665
666 VisualDataStore::lyricsCreationThreadIsRunning = true;
667
668 DWORD retVal = 0;
669
670 IiTunes* iITunes = 0;
671 IITTrack* iITrack = 0;
672
673 CoInitialize(0);
674 //HRESULT result = CoInitializeEx(0, COINIT_APARTMENTTHREADED);
675
676 try
677 {
678 HRESULT hRes = ::CoCreateInstance(CLSID_iTunesApp, NULL, CLSCTX_LOCAL_SERVER, IID_IiTunes, (PVOID *)&iITunes);
679
680 if(hRes == S_OK && iITunes) {
681 iITunes->get_CurrentTrack(&iITrack);
682 if(iITrack) {
683
684 BSTR bstrTrack = 0;
685
686 iITrack->get_Name((BSTR *)&bstrTrack);
687
688 BSTR bstrLyricsTrack = ::SysAllocString((const OLECHAR*)(""));
689 //BSTR bstrLyricsTrack = 0;
690 IITFileOrCDTrack* iTrackFile;
691 iITrack->QueryInterface(IID_IITFileOrCDTrack, (void **)&iTrackFile);
692 if (iTrackFile) {
693 iTrackFile->get_Lyrics(&bstrLyricsTrack);
694 }
695 theVisualDataStore = VisualDataStore::getInstance();
696
697 uint16 trackLyricsStringLength = lstrlenW(bstrLyricsTrack);
698 VisualString lyrics((uint16*)bstrLyricsTrack, trackLyricsStringLength);
699 VisualDataStore::setLyricsOfCurrentTrack(lyrics);
700 //theVisualDataStore->audioMetaDataHistory[theVisualDataStore->currAudioMetaDataHistoryIdx].setTrackLyrics(lyrics);
701 //dynamic_cast<IITFileOrCDTrack*>(iITrack)->get_Lyrics((BSTR *)&bstrLyricsTrack);
702 //dynamic_cast<IITFileOrCDTrack*>(iITrack)->get_Lyrics((BSTR *)&theVisualDataStore->trackLyrics);
703
704 }
705 }
706
707 iITunes->Release();
708
709 }
710 catch(...)
711 {
712 try
713 {
714 if(iITunes)
715 iITunes->Release();
716
717 if(iITrack)
718 iITrack->Release();
719 }
720 catch(...)
721 {
722 }
723 }
724
725 CoUninitialize();
726
727
728 /*
729 iTunesLib.iTunesAppClass itl = new iTunesLib.iTunesAppClass();
730 string currTrack = itl.CurrentTrack.Name.ToString();
731 iTunesLib.IITTrack myTrack = (iTunesLib.IITTrack)itl.CurrentTrack;
732 iTunesLib.IITFileOrCDTrack test = (iTunesLib.IITFileOrCDTrack)myTrack;
733 string myLyrics = test.Lyrics;
734
735 MessageBox.Show("Track: "+currTrack+", Lyrics: "+myLyrics);
736 */
737
738 VisualNotification::post(kLyricsAreAvailableInMetadataMsg);
739
740 VisualDataStore::lyricsCreationThreadIsRunning = false;
741
742 return retVal;
743 }
744 #endif
745
746
747
748 #if TARGET_OS_MAC
readFileAndSendNotificationWithString(void * fileWithStringContent)749 OSStatus VisualDataStore::readFileAndSendNotificationWithString(void* fileWithStringContent) {
750 OSStatus retVal = noErr;
751 #endif
752 #if TARGET_OS_WIN
753 DWORD VisualDataStore::readFileAndSendNotificationWithString(LPVOID fileWithStringContent) {
754 DWORD retVal = 0;
755 #endif
756
757 bool debug = false;
758
759 if (debug == true) {
760 writeLog("readFileAndSendNotificationWithString (start)");
761 }
762
763 VisualFile* visualFile = reinterpret_cast<VisualFile*>(fileWithStringContent);
764
765 VisualString stringContentsOfFile;
766 stringContentsOfFile.initWithContentsOfFile(*visualFile);
767
768 if (debug == true) {
769 writeLog("after stringContentsOfFile.initWithContentsOfFile()");
770 }
771 if (stringContentsOfFile.getNumberOfCharacters() == 0) {
772 if (debug == true) {
773 writeLog("stringContentsOfFile.getNumberOfCharacters() == 0");
774 }
775 #if TARGET_OS_MAC
776 retVal = (OSStatus)1001;
777 #endif
778 #if TARGET_OS_WIN
779 retVal = (DWORD)1001;
780 #endif
781 return retVal;
782 }
783
784 VisualNotification aNotification(visualFile->getIdentifier());
785 aNotification.setKey(kStringWithIdentifierLoadedAndCreatedMsg);
786 aNotification.setObject(stringContentsOfFile);
787
788 delete visualFile;
789 visualFile = NULL;
790
791 aNotification.post();
792
793 if (debug == true) {
794 writeLog("readFileAndSendNotificationWithString (end)");
795 }
796
797 return retVal;
798 }
799
800
801 #if TARGET_OS_MAC
802 OSStatus VisualDataStore::readFileAndRemoveFileAndSendNotificationWithString(void* fileWithStringContent) {
803 OSStatus retVal = noErr;
804 #endif
805 #if TARGET_OS_WIN
806 DWORD VisualDataStore::readFileAndRemoveFileAndSendNotificationWithString(LPVOID fileWithStringContent) {
807 DWORD retVal = 0;
808 #endif
809
810 bool debug = false;
811
812 if (debug == true) {
813 writeLog("readFileAndRemoveFileAndSendNotificationWithString (start)");
814 }
815
816 VisualFile* visualFile = reinterpret_cast<VisualFile*>(fileWithStringContent);
817
818 if (!visualFile) {
819 #if TARGET_OS_MAC
820 retVal = (OSStatus)1001;
821 #endif
822 #if TARGET_OS_WIN
823 retVal = (DWORD)1001;
824 #endif
825 return retVal;
826 }
827
828 VisualString stringContentsOfFile;
829 stringContentsOfFile.initWithContentsOfFile(*visualFile);
830
831 if (debug == true) {
832 writeLog("after stringContentsOfFile.initWithContentsOfFile()");
833 }
834 if (stringContentsOfFile.getNumberOfCharacters() == 0) {
835 if (debug == true) {
836 writeLog("stringContentsOfFile.getNumberOfCharacters() == 0");
837 }
838 #if TARGET_OS_MAC
839 retVal = (OSStatus)1002;
840 #endif
841 #if TARGET_OS_WIN
842 retVal = (DWORD)1002;
843 #endif
844 return retVal;
845 }
846
847 VisualItemIdentifier fileIdentifier = visualFile->getIdentifier();
848 VisualNotification aNotification(fileIdentifier);
849 aNotification.setKey(kStringWithIdentifierLoadedAndCreatedMsg);
850 aNotification.setObject(stringContentsOfFile);
851
852 bool success = visualFile->remove();
853 if (debug == true) {
854 writeLog("tempFile.remove()");
855 }
856 if (!success) {
857 if (debug == true) {
858 writeLog("no success after remove()");
859 }
860 #if TARGET_OS_MAC
861 retVal = (OSStatus)1003;
862 #endif
863 #if TARGET_OS_WIN
864 retVal = (DWORD)1003;
865 #endif
866 }
867
868 delete visualFile;
869 visualFile = NULL;
870
871 aNotification.post();
872
873 if (debug == true) {
874 writeLog("readFileAndRemoveFileAndSendNotificationWithString (end)");
875 }
876
877 return retVal;
878 }
879