// ---------------------------------------------------------------------------- // void DefinitionReader::readFixtureDefinitions( LPCSTR directory ) { CFileFind finder; CString directory_search( directory ); directory_search.Append( "\\*" ); BOOL working = finder.FindFile( directory_search ); if ( !working ) throw StudioException( "Unable to find fixture definition directory '%s'", directory ); while ( working ) { working = finder.FindNextFile(); if ( finder.IsDots() ) continue; CString file_name = finder.GetFilePath(); if ( finder.IsDirectory() ) readFixtureDefinitions( file_name ); CString test_name( file_name ); if ( test_name.MakeLower().Find( ".xml" ) == -1 ) continue; // Check for definition file TiXmlDocument doc; if ( !doc.LoadFile( file_name ) ) throw StudioException( "Error reading fixture definition '%s'", file_name ); try { TiXmlElement* root = doc.FirstChildElement( "fixture_definitions" ); LPCSTR author = read_text_element( root, "author" ); LPCSTR version = read_text_element( root, "version" ); FixtureDefinitionPtrArray fixture_definitions = read_xml_list<FixtureDefinition>( root, "fixture" ); //DefinitionWriter writer; //writer.writeFixtureDefinition( file_name, author, version, fixture_definitions ); for ( FixtureDefinition* definition : fixture_definitions ) { definition->setSourceFile( file_name ); definition->m_author = author; definition->m_version = version; FixtureDefinition::addFixtureDefinition( definition ); delete definition; } } catch ( StudioException e ) { throw StudioException( "%s: %s", file_name, e.what() ); } } finder.Close(); }
// ---------------------------------------------------------------------------- // bool HttpRestServices::edit_venue_new( CString& response, LPCSTR data, DWORD size, LPCSTR content_type ) { SimpleJsonParser parser; CString reset_what; try { parser.parse( data ); reset_what = parser.get<CString>( "reset_what" ); } catch ( std::exception& e ) { throw StudioException( "JSON parser error (%s) data (%s)", e.what(), data ); } if ( reset_what == "new" ) { studio.newVenue(); } else if ( reset_what == "chases" ) { studio.getVenue()->deleteAllChases(); } else if ( reset_what == "groups" ) { studio.getVenue()->deleteAllFixtureGroups(); } else if ( reset_what == "scenes" ) { studio.getVenue()->deleteAllScenes(); } else return false; return true; }
// ---------------------------------------------------------------------------- // static bool music_matcher_load( Venue* venue, LPCSTR data, boolean clearFirst ) { SimpleJsonParser parser; std::vector<MusicSceneSelector> selections; try { parser.parse( data ); JsonNodePtrArray selection_parsers = parser.getObjects(); for ( JsonNode* selection : selection_parsers ) { UID selection_id = selection->get<UID>( "id" ); CString selection_name = selection->get<CString>( "track" ); CString selection_link = selection->get<CString>( "link" ); MusicSelectorType selection_type = (MusicSelectorType)selection->get<int>( "type" ); selections.push_back( MusicSceneSelector( selection_name, selection_link, selection_type, selection_id ) ); } } catch ( std::exception& e ) { throw StudioException( "JSON parser error (%s) data (%s)", e.what(), data ); } // Reload the selection map if ( clearFirst ) venue->clearMusicMappings(); venue->addMusicMappings( selections ); return true; }
// ---------------------------------------------------------------------------- // bool HttpRestServices::edit_scene_copy_fixtures( CString& response, LPCSTR data, DWORD size, LPCSTR content_type ) { if ( !studio.getVenue() || !studio.getVenue()->isRunning() ) return false; SimpleJsonParser parser; bool clear; bool keep_groups; ULONG scene_id; UIDArray actors; try { parser.parse( data ); clear = parser.get<bool>( "clear" ); scene_id = parser.get<unsigned long>( "scene_id" ); keep_groups = parser.get<bool>( "keep_groups" ); actors = parser.get<UIDArray>( "fixture_ids" ); } catch ( std::exception& e ) { DMXStudio::log( StudioException( "JSON parser error (%s) data (%s)", e.what(), data ) ); return false; } studio.getVenue()->moveDefaultFixturesToScene(scene_id, actors, keep_groups, clear ); return true; }
// ---------------------------------------------------------------------------- // bool HttpRestServices::player_login( Venue* venue, DMXHttpSession* session, CString& response, LPCSTR data, DWORD size, LPCSTR content_type ) { SimpleJsonParser parser; CString username; CString password; try { parser.parse( data ); username = parser.get<CString>( "username" ); password = parser.get<CString>( "password" ); } catch ( std::exception& e ) { throw StudioException( "JSON parser error (%s) data (%s)", e.what(), data ); } JsonBuilder json( response ); json.startObject(); if ( studio.getMusicPlayer()->signon( username, password ) ) { json.add( "logged_in", true ); } else { CString login_error = studio.getMusicPlayer()->getLastPlayerError(); if ( login_error.IsEmpty() ) login_error = "Login failed"; json.add( "logged_in", false ); json.add( "login_error", login_error ); } json.endObject(); return true; }
// ---------------------------------------------------------------------------- // Venue* VenueReader::readFromString( LPCSTR xml_data ) { TiXmlDocument doc; if ( !doc.Parse( xml_data ) ) throw StudioException( "Error parsing venue '%s' (%s)", xml_data, doc.ErrorDesc() ); return read( doc.FirstChildElement(), (Venue *)NULL ); }
// ---------------------------------------------------------------------------- // Venue* VenueReader::readFromFile( LPCSTR input_file ) { TiXmlDocument doc; if ( !doc.LoadFile( input_file ) ) throw StudioException( "Error reading venue '%s' (%s)", input_file, doc.ErrorDesc() ); return read( doc.FirstChildElement(), (Venue *)NULL ); }
// ---------------------------------------------------------------------------- // CString DMXStudio::getUserDocumentDirectory() { char input_file[MAX_PATH]; HRESULT result = SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, input_file); if ( result != S_OK ) throw StudioException( "Error %d finding document directory", result ); return CString( input_file ); }
// ---------------------------------------------------------------------------- // AnalyzeInfo* SpotifyEngine::loadTrackAnalysis( LPCSTR spotify_id ) { TrackAnalysisCache::iterator it = m_track_analysis_cache.find( spotify_id ); if ( it != m_track_analysis_cache.end() ) return (it)->second; // See if it existing on disk - if available, load into the cache and return CString filename = makeTrackAnalysisFileName( m_trackAnalysisContainer, spotify_id ); if ( GetFileAttributes( filename ) == INVALID_FILE_ATTRIBUTES ) return NULL; FILE* hFile = _fsopen( filename, "rt", _SH_DENYWR ); if ( hFile == NULL ) { log( "Unable to read track analysis from %s", filename ); return NULL; } // Get file size fseek( hFile, 0L, SEEK_END ); size_t size = ftell( hFile ); rewind( hFile ); CString data; fread( data.GetBufferSetLength(size), 1, size, hFile ); fclose( hFile ); SimpleJsonParser parser; try { parser.parse( data ); CString spotify_id = parser.get<CString>( "link" ); SimpleJsonParser amplitute_parser = parser.get<SimpleJsonParser>( "amplitude" ); size_t data_count = amplitute_parser.get<size_t>( "data_count" ); UINT duration_ms = amplitute_parser.get<size_t>( "duration_ms" ); std::vector<uint16_t> amplitude_data = amplitute_parser.getArray<uint16_t>( "data" ); AnalyzeInfo* info = (AnalyzeInfo*)calloc( sizeof(AnalyzeInfo) + (sizeof(uint16_t) * data_count), 1 ); for ( size_t i=0; i < data_count; i++ ) info->data[i] = amplitude_data[i]; strncpy_s( info->link, spotify_id, sizeof(info->link) ); info->data_count = data_count; info->duration_ms = duration_ms; m_track_analysis_cache[info->link] = info; return info; } catch ( std::exception& e ) { log( StudioException( "JSON parser error (%s) data (%s)", e.what(), data ) ); return NULL; } }
// ---------------------------------------------------------------------------- // void DefinitionReader::readFixtureDefinitions( ) { TCHAR definitions_root[MAX_PATH]; GetCurrentDirectory( MAX_PATH, definitions_root ); strcat_s( definitions_root, "\\FixtureDefinitions" ); DWORD attributes = GetFileAttributes( definitions_root ); if ( attributes == INVALID_FILE_ATTRIBUTES || !(attributes & FILE_ATTRIBUTE_DIRECTORY) ) throw StudioException( "Unable to find fixture definition directory '%s'", definitions_root ); readFixtureDefinitions( definitions_root ); size_t definitions = FixtureDefinition::FixtureDefinitions.size(); if ( definitions == 0 ) throw StudioException( "No fixture definitions found in '%s'", definitions_root ); DMXStudio::log_status( "Found %d fixture personality definitions", definitions ); }
// ---------------------------------------------------------------------------- // bool HttpRestServices::edit_venue_load( CString& response, LPCSTR data, DWORD size, LPCSTR content_type ) { SimpleJsonParser parser; CString venue_filename; try { parser.parse( data ); venue_filename = parser.get<CString>( "venue_filename" ); venue_filename.Replace( "\\\\", "\\" ); } catch ( std::exception& e ) { throw StudioException( "JSON parser error (%s) data (%s)", e.what(), data ); } return studio.loadVenueFromFile( (LPCSTR)venue_filename ); }
// ---------------------------------------------------------------------------- // bool HttpRestServices::edit_venue_update( CString& response, LPCSTR data, DWORD size, LPCSTR content_type ) { Venue* venue = studio.getVenue(); if ( !venue ) return false; SimpleJsonParser parser; try { parser.parse( data ); CString name = parser.get<CString>( "name" ); CString description = parser.get<CString>( "description" ); CString dmx_port = parser.get<CString>( "dmx_port" ); CString audio_capture_device = parser.get<CString>( "audio_capture_device" ); int dmx_packet_delay_ms = parser.get<int>( "dmx_packet_delay_ms" ); int dmx_minimum_delay_ms = parser.get<int>( "dmx_minimum_delay_ms" ); int audio_sample_size = parser.get<int>( "audio_sample_size" ); float audio_boost = parser.get<float>( "audio_boost" ); float audio_boost_floor = parser.get<float>( "audio_boost_floor" ); int auto_blackout = parser.get<int>( "auto_blackout" ); // There may be a better solution for this, but we need to kill all attached sound devices before the reset m_sound_sampler.detach(); venue->close(); venue->setName( name ); venue->setDescription( description ); venue->setDmxPort( dmx_port ); venue->setDmxPacketDelayMS( dmx_packet_delay_ms ); venue->setDmxMinimumDelayMS( dmx_minimum_delay_ms ); venue->setAudioCaptureDevice( audio_capture_device ); venue->setAudioBoost( audio_boost ); venue->setAudioBoostFloor( audio_boost_floor ); venue->setAudioSampleSize( audio_sample_size ); venue->setAutoBlackout( auto_blackout ); venue->open(); } catch ( std::exception& e ) { throw StudioException( "JSON parser error (%s) data (%s)", e.what(), data ); } return true; }
// ---------------------------------------------------------------------------- // void DMXStudio::writeVenueToFile( LPCSTR output_file ) { // Create the path if it does not exist CString path( output_file ); int pos = path.ReverseFind( '\\' ); if ( pos != -1) { path = path.Left( pos+1 ); if ( !PathFileExists( path ) ) if ( !CreateDirectory( path, NULL ) ) // TODO - need to created entire path throw StudioException( "Cannot create directory '%s' (ERROR %lu)", path, GetLastError() ); } CSingleLock lock( &m_venue_mutex, TRUE ); VenueWriter writer; writer.writeToFile( m_venue, output_file ); }
// ---------------------------------------------------------------------------- // bool DMXStudio::handleEvent( const Event& event ) { if ( isDebug() ) { CString output( "EVENT " ); output.Append( (LPCSTR)EventBus::eventAsString( event ) ); log_status( output ); } if ( event.m_source == ES_VENUE ) { if ( event.m_action == EA_START ) log_status( "Venue started [%s]", event.m_text ); else if ( event.m_action == EA_STOP ) log_status( "Venue stopped [%s]", event.m_text ); else if ( event.m_action == EA_ERROR ) log( StudioException( event.m_text ) ); } return false; }
// ---------------------------------------------------------------------------- // bool HttpRestServices::edit_scene( CString& response, LPCSTR data, EditMode mode ) { if ( !studio.getVenue() || !studio.getVenue()->isRunning() ) return false; SimpleJsonParser parser; UID scene_id; CString name, description; SceneNumber number; BPMRating bpm_rating; bool keep_groups; Scene* scene = NULL; UIDArray actors; PARSER_LIST animationParsers; std::vector<AbstractAnimation*> animations; Acts acts; try { parser.parse( data ); scene_id = parser.get<ULONG>( "id" ); name = parser.get<CString>( "name" ); description = parser.get<CString>( "description" ); number = parser.get<ULONG>( "number" ); bpm_rating = (BPMRating)parser.get<UINT>( "bpm_rating" ); keep_groups = parser.get<bool>( "keep_groups" ); actors = parser.get<UIDArray>( "actors" ); animationParsers = parser.get<PARSER_LIST>("animations"); acts = parser.get<Acts>( "acts" ); for ( PARSER_LIST::iterator it=animationParsers.begin(); it != animationParsers.end(); ++it ) { CString class_name = (*it).get<CString>( "class_name" ); UIDArray animation_actors = (*it).get<UIDArray>( "actors" ); SimpleJsonParser signalParser = (*it).get<SimpleJsonParser>( "signal" ); SimpleJsonParser animationParser = (*it).get<SimpleJsonParser>( class_name ); AnimationSignal signal = parseAnimationSignal( signalParser ); ANIMATION_PARSER_FUNC anim_parser_func = animation_parsers[ class_name ]; if ( anim_parser_func == NULL ) throw std::exception( "Unknown animation class name from client" ); animations.push_back( anim_parser_func( animationParser, signal, animation_actors ) ); } } catch ( std::exception& e ) { throw StudioException( "JSON parser error (%s) data (%s)", e.what(), data ); } if ( scene_id != 0 ) { scene = studio.getVenue()->getScene( scene_id ); if ( !scene ) return false; } // Make sure number is unique if ( mode != UPDATE || (scene && number != scene->getNumber()) ) { if ( studio.getVenue()->getSceneByNumber( number ) != NULL ) return false; } switch ( mode ) { case NEW: { scene_id = studio.getVenue()->allocUID(); Scene new_scene; new_scene.setUID( scene_id ); studio.getVenue()->addScene( new_scene ); scene = studio.getVenue()->getScene( scene_id ); studio.getVenue()->moveDefaultFixturesToScene( scene_id, actors, keep_groups, true ); break; } case COPY: { scene_id = studio.getVenue()->allocUID(); Scene new_scene( *scene ); new_scene.setUID( scene_id ); studio.getVenue()->addScene( new_scene ); scene = studio.getVenue()->getScene( scene_id ); } // Fall through case UPDATE: // Verify actors - remove any that have been deselected UIDArray active_actors = scene->getActorUIDs(); for ( UIDArray::iterator it=active_actors.begin(); it != active_actors.end(); ++it ) { if ( std::find( actors.begin(), actors.end(), *it ) == actors.end() ) scene->removeActor( *it ); } break; } scene->setName( name ); scene->setSceneNumber( number ); scene->setBPMRating( bpm_rating ); scene->setDescription( description ); scene->setActs( acts ); scene->clearAnimations(); for ( std::vector<AbstractAnimation*>::iterator it=animations.begin(); it != animations.end(); ++it ) scene->addAnimation( *it ); if ( mode != UPDATE ) // Switch to new scene studio.getVenue()->selectScene( scene->getUID() ); else if ( studio.getVenue()->getCurrentSceneUID() == scene->getUID() ) studio.getVenue()->loadScene( ); return true; }