History

initial feature done

Ge Wang committed 3 years ago

Commit add40a01 parent dcebc368 files · +516 −193Browse files

Unified · Split

8 files
  1. VERSIONS +9 −0
  2. src/core/chuck.cpp +23 −40
  3. src/core/chuck_compile.cpp +333 −108
  4. src/core/chuck_compile.h +11 −2
  5. src/core/chuck_dl.cpp +105 −25
  6. src/core/chuck_dl.h +18 −4
  7. src/core/chuck_errmsg.cpp +1 −1
  8. src/host/chuck_main.cpp +16 −13
VERSIONS+9−0
@@ -2,6 +2,15 @@ · 1 unmodified line
22 ChucK VERSIONS log
33 ------------------
44
5+1.5.0.4
6+---
7+- (added) --chugin-probe command-line flag to probe (and verify version)
8+ for chugins and auto-load chuck sources in the search paths; print
9+ results and any version mismatches
10+- (updated) setting chuck log level is no longer logged below
11+ log level INFO
12+
13+
514 1.5.0.3 (June 2023)
615 ---
716 - (fixed) chuck audio I/O now correctly carries out extended probing
src/core/chuck.cpp+23−40
@@ -630,7 +630,7 @@ t_CKBOOL ChucK::initChugins() · 629 unmodified lines
630630 // push indent level
631631 EM_pushlog();
632632 // load external libs
633− if( !compiler()->load_external_modules( ".chug", dl_search_path, named_dls ) )
633+ if( !compiler()->load_external_modules( ".chug", dl_search_path, named_dls, true ) )
634634 {
635635 // pop indent level
636636 EM_poplog();
@@ -722,11 +722,20 @@ error: // 1.4.1.0 (ge) added · 85 unmodified lines
722722 //-----------------------------------------------------------------------------
723723 void ChucK::probeChugins()
724724 {
725− Chuck_VM_Code * code = NULL;
726− Chuck_VM_Shred * shred = NULL;
725+ // ck files to pre load
726+ std::list<std::string> ck_libs_to_preload;
727727
728728 // print whether chugins enabled
729729 EM_log( CK_LOG_SYSTEM, "chugin system: %s", getParamInt( CHUCK_PARAM_CHUGIN_ENABLE ) ? "ON" : "OFF" );
730+ // print host version
731+ EM_log( CK_LOG_SYSTEM, "chuck host version: %d.%d", CK_DLL_VERSION_MAJOR, CK_DLL_VERSION_MINOR );
732+ // push
733+ EM_pushlog();
734+ // print host version
735+ EM_log( CK_LOG_SYSTEM, "chugin major version must == host major version" );
736+ EM_log( CK_LOG_SYSTEM, "chugin minor version must <= host major version" );
737+ // pop
738+ EM_poplog();
730739
731740 // chugin dur
732741 std::string chuginDir = getParamString( CHUCK_PARAM_CHUGIN_DIRECTORY );
@@ -741,61 +750,35 @@ void ChucK::probeChugins() · 8 unmodified lines
741750 std::list<std::string> named_dls = getParamStringList( CHUCK_PARAM_USER_CHUGINS );
742751
743752 // log
744− EM_log( CK_LOG_SYSTEM, "probing chugins..." );
753+ EM_log( CK_LOG_SYSTEM, "probing chugins (.chug)..." );
745754 // push indent level
746755 EM_pushlog();
747756 // load external libs
748− if(!compiler()->load_external_modules( ".chug", dl_search_path, named_dls ))
757+ if( !Chuck_Compiler::probe_external_modules( ".chug", dl_search_path, named_dls, TRUE, ck_libs_to_preload ) )
749758 {
750− // pop indent level
751− EM_poplog();
752− // clean up
753− // goto error;
759+ // warning
760+ EM_log( CK_LOG_SYSTEM, "error probing chugins..." );
754761 }
755762 // pop log
756763 EM_poplog();
757764
758765 // log
759− EM_log( CK_LOG_SYSTEM, "probing pre-loading ChucK libs..." );
766+ EM_log( CK_LOG_SYSTEM, "probing auto-load chuck files (.ck)..." );
760767 EM_pushlog();
761768
762769 // iterate over list of ck files that the compiler found
763− for( std::list<std::string>::iterator j =
764− compiler()->m_cklibs_to_preload.begin();
765− j != compiler()->m_cklibs_to_preload.end(); j++ )
770+ for( std::list<std::string>::iterator j = ck_libs_to_preload.begin();
771+ j != ck_libs_to_preload.end(); j++ )
766772 {
767773 // the filename
768774 std::string filename = *j;
769−
770775 // log
771− EM_log( CK_LOG_SEVERE, "preloading '%s'...", filename.c_str() );
772− // push indent
773− EM_pushlog();
774−
775− // SPENCERTODO: what to do for full path
776− std::string full_path = filename;
777−
778− // parse, type-check, and emit
779− if(compiler()->go( filename, NULL, NULL, full_path ))
780− {
781− // TODO: how to compilation handle?
782− //return 1;
783−
784− // get the code
785− code = compiler()->output();
786− // name it - TODO?
787− // code->name += string(argv[i]);
788−
789− // spork it
790− shred = vm()->spork( code, NULL, TRUE );
791− }
792−
793− // pop indent
794− EM_poplog();
776+ EM_log( CK_LOG_SYSTEM, "source '%s'...", filename.c_str() );
795777 }
796778
797− // clear the list of chuck files to preload
798− compiler()->m_cklibs_to_preload.clear();
779+ // check
780+ if( ck_libs_to_preload.size() == 0 )
781+ EM_log( CK_LOG_SYSTEM, "(none found)" );
799782
800783 // pop log
801784 EM_poplog();
src/core/chuck_compile.cpp+333−108
@@ -745,6 +745,78 @@ error: · 744 unmodified lines
745745
746746
747747
748+
749+//-----------------------------------------------------------------------------
750+// name: expandfilePath()
751+// desc: expand file path, e.g., ~ on unix systems | 1.5.0.4 (ge) moved here
752+//-----------------------------------------------------------------------------
753+std::string expandFilePath( const string & directory )
754+{
755+ // expansion
756+ string exp;
757+
758+#ifndef __PLATFORM_WIN32__
759+#ifndef __DISABLE_WORDEXP__
760+ // 1.5.0.0 (ge) added (for ~)
761+ wordexp_t exp_result;
762+ // "perform shell-style word expansions"
763+ wordexp( directory.c_str(), &exp_result, 0 );
764+ // concatenate in case there are spaces in the path
765+ for( t_CKINT i = 0; i < exp_result.we_wordc; i++ )
766+ exp += string(i > 0 ? " " : "") + exp_result.we_wordv[i];
767+ // free
768+ wordfree( &exp_result );
769+#endif
770+#endif
771+
772+ // if exp still empty, no change
773+ if( exp == "" ) exp = directory;
774+
775+ // done
776+ return exp;
777+}
778+
779+
780+
781+
782+//-----------------------------------------------------------------------------
783+// name: getDirEntryAttribute()
784+// desc: get directory entry attribute | 1.5.0.4 (ge) moved into function
785+//-----------------------------------------------------------------------------
786+t_CKBOOL getDirEntryAttribute( dirent * de, t_CKBOOL & isDirectory, t_CKBOOL & isRegular )
787+{
788+#if defined(__PLATFORM_WIN32__)
789+ isDirectory = de->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
790+ isRegular = ((de->data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
791+ (de->data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
792+ (de->data.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE));
793+#elif defined(__WINDOWS_PTHREAD__) // Cygwin -- doesn't have dirent d_type
794+ std::string absolute_path = std::string(directory) + "/" + de->d_name;
795+ struct stat st;
796+ if( stat(absolute_path.c_str(), &st) == 0 )
797+ {
798+ isDirectory = st.st_mode & S_IFDIR;
799+ isRegular = st.st_mode & S_IFREG;
800+ }
801+ else
802+ {
803+ // uhh ...
804+ EM_log( CK_LOG_INFO,
805+ "unable to open file '%s', ignoring for chugins",
806+ absolute_path.c_str() );
807+ return false;
808+ }
809+#else
810+ isDirectory = de->d_type == DT_DIR;
811+ isRegular = de->d_type == DT_REG;
812+#endif
813+
814+ return true;
815+}
816+
817+
818+
819+
748820 //-----------------------------------------------------------------------------
749821 // name: load_external_module_at_path()
750822 // desc: ...
@@ -789,116 +861,82 @@ t_CKBOOL load_external_module_at_path( Chuck_Compiler * compiler, · 38 unmodified lines
789861
790862 //-----------------------------------------------------------------------------
791863 // name: load_external_modules_in_directory()
792−// desc: ...
864+// desc: load all external modules by extension within a directory
793865 //-----------------------------------------------------------------------------
794866 t_CKBOOL load_external_modules_in_directory( Chuck_Compiler * compiler,
795867 const char * directory,
796− const char * extension )
868+ const char * extension,
869+ t_CKBOOL recursiveSearch = FALSE )
797870 {
798− static const t_CKBOOL RECURSIVE_SEARCH = false;
799−
800− // directory path
801− string path = directory, exp = "";
802−
803−#ifndef __PLATFORM_WIN32__
804−#ifndef __DISABLE_WORDEXP__
805− // 1.5.0.0 (ge) added (for ~)
806− wordexp_t exp_result;
807− // "perform shell-style word expansions"
808− wordexp( directory, &exp_result, 0 );
809− // concatenate in case there are spaces in the path
810− for( t_CKINT i = 0; i < exp_result.we_wordc; i++ )
811− exp += string(i > 0 ? " " : "") + exp_result.we_wordv[i];
812− // replace
813− path = exp;
814−#endif
815−#endif
816−
871+ // expand directory path
872+ string path = expandFilePath( directory );
817873 // open the directory
818874 DIR * dir = opendir( path.c_str() );
819875
876+ // log
877+ EM_log( CK_LOG_INFO, "examining directory for chugins..." );
878+ // push
879+ EM_pushlog();
880+ // print directory to examine
881+ EM_log( CK_LOG_INFO, "'%s'", directory );
882+
820883 // if successful
821884 if( dir )
822885 {
823− // log
824− EM_log( CK_LOG_INFO, "examining directory '%s' for chugins", directory );
825−
826886 // do first read | 1.5.0.0 (ge + eito) #chunreal
827887 struct dirent * de = readdir(dir);
828−
829− // while( (de = readdir(dir)) ) <- in ge's opinion clearer than what UE5 forces us to do
888+ // while( (de = readdir(dir)) ) <- UE5 forces us to not do this
830889 while( de != NULL )
831890 {
832891 t_CKBOOL is_regular = false;
833892 t_CKBOOL is_directory = false;
893+ // get attributes
894+ if( !getDirEntryAttribute( de, is_directory, is_regular ) ) continue;
834895
835−#if defined(__PLATFORM_WIN32__)
836− is_directory = de->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
837− is_regular = ((de->data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ||
838− (de->data.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ||
839− (de->data.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE));
840−#elif defined(__WINDOWS_PTHREAD__) // Cygwin -- doesn't have dirent d_type
841− std::string absolute_path = std::string(directory) + "/" + de->d_name;
842− struct stat st;
843− if( stat(absolute_path.c_str(), &st) == 0 )
844− {
845− is_directory = st.st_mode & S_IFDIR;
846− is_regular = st.st_mode & S_IFREG;
847− }
848− else
849− {
850− // uhh ...
851− EM_log( CK_LOG_INFO,
852− "unable to open file '%s', ignoring for chugins",
853− absolute_path.c_str() );
854− continue;
855− }
856−#else
857− is_directory = de->d_type == DT_DIR;
858− is_regular = de->d_type == DT_REG;
859−#endif
860−
861− if( is_regular ) // TODO: follow links?
896+ // check | TODO: follow links?
897+ if( is_regular )
862898 {
863− if( extension_matches(de->d_name, extension) )
899+ // check for ck files to pre-load
900+ if( extension_matches(de->d_name, ".ck") )
864901 {
902+ // construct absolute path
865903 std::string absolute_path = std::string(directory) + "/" + de->d_name;
866−
867− load_external_module_at_path(compiler, de->d_name,
868− absolute_path.c_str());
904+ // append file path
905+ compiler->m_cklibs_to_preload.push_back(absolute_path);
869906 }
870− else if( extension_matches(de->d_name, ".ck") )
907+ // check extension passed in
908+ else if( extension_matches(de->d_name, extension) )
871909 {
910+ // construct absolute path
872911 std::string absolute_path = std::string(directory) + "/" + de->d_name;
873− compiler->m_cklibs_to_preload.push_back(absolute_path);
912+ // load module
913+ load_external_module_at_path( compiler, de->d_name, absolute_path.c_str() );
874914 }
875915 }
876− else if( RECURSIVE_SEARCH && is_directory )
916+ else if( recursiveSearch && is_directory )
877917 {
878− // recurse
879− // TODO: max depth?
918+ // recurse | TODO: max depth?
880919 if( strncmp(de->d_name, ".", sizeof(".")) != 0 &&
881920 strncmp(de->d_name, "..", sizeof("..")) != 0 )
882921 {
922+ // construct absolute path
883923 std::string absolute_path = std::string(directory) + "/" + de->d_name;
884− load_external_modules_in_directory(compiler,
885− absolute_path.c_str(),
886− extension);
924+ // search in sub-directory
925+ load_external_modules_in_directory( compiler, absolute_path.c_str(), extension);
887926 }
888927 }
889928 #ifdef __PLATFORM_MACOSX__
890− // #if __APPLE__ probably cleaner but using the above for consistency for now (ge)
891− // ---
892− // On macOS, a chugin can either be a regular file (a .dylib simply renamed to .chug)
893− // or it can be a MODULE like using CMake with add_library(FooChugin MODULE foo.cpp)
894− // If it's a module bundle, then because .chug is a nonstandard extension,
895− // on the filesystem it shows up as a directory ending in .chug.
896− // If we see one of these directories, we can dive directly to the Contents/MacOS subfolder
897− // and look for a regular file. | 1.5.0.1 (dbraun) added
898− else if (is_directory && extension_matches(de->d_name, extension)) {
929+ else if( is_directory && extension_matches(de->d_name, extension) )
930+ {
931+ // On macOS, a chugin can either be a regular file (a .dylib simply renamed to .chug)
932+ // or it can be a MODULE like using CMake with add_library(FooChugin MODULE foo.cpp)
933+ // If it's a module bundle, then because .chug is a nonstandard extension,
934+ // on the filesystem it shows up as a directory ending in .chug.
935+ // If we see one of these directories, we can dive directly to the Contents/MacOS subfolder
936+ // and look for a regular file. | 1.5.0.1 (dbraun) added
899937 std::string absolute_path = std::string(directory) + "/" + de->d_name + "/Contents/MacOS";
900− const char* subdirectory = absolute_path.c_str();
901− load_external_modules_in_directory(compiler, subdirectory, "");
938+ const char * subdirectory = absolute_path.c_str();
939+ load_external_modules_in_directory( compiler, subdirectory, "" );
902940 }
903941 #endif // #ifdef __PLATFORM_MACOSX__
904942
@@ -912,19 +950,14 @@ t_CKBOOL load_external_modules_in_directory( Chuck_Compiler * compiler, · 7 unmodified lines
912950 else
913951 {
914952 // log (1.3.1.2: changed to 2 lines to stay within 80 chars)
915− EM_log( CK_LOG_INFO, "unable to open directory:" );
916953 EM_pushlog();
917− EM_log( CK_LOG_INFO, "'%s'", directory );
954+ EM_log( CK_LOG_INFO, "unable to open directory..." );
918955 EM_log( CK_LOG_INFO, "ignoring for chugins..." );
919956 EM_poplog();
920957 }
921958
922−#ifndef __PLATFORM_WIN32__
923−#ifndef __DISABLE_WORDEXP__
924− // free | 1.5.0.0 (ge) added
925− wordfree( &exp_result );
926−#endif
927−#endif
959+ // pop log
960+ EM_poplog();
928961
929962 return TRUE;
930963 }
@@ -934,11 +967,12 @@ t_CKBOOL load_external_modules_in_directory( Chuck_Compiler * compiler, · 3 unmodified lines
934967
935968 //-----------------------------------------------------------------------------
936969 // name: load_external_modules()
937−// desc: ...
970+// desc: load external modules (e.g., .chug and .ck library files)
938971 //-----------------------------------------------------------------------------
939−t_CKBOOL Chuck_Compiler:: load_external_modules( const char * extension,
940− std::list<std::string> & chugin_search_paths,
941− std::list<std::string> & named_dls )
972+t_CKBOOL Chuck_Compiler::load_external_modules( const char * extension,
973+ std::list<std::string> & chugin_search_paths,
974+ std::list<std::string> & named_dls,
975+ t_CKBOOL recursiveSearch )
942976 {
943977 // get env
944978 Chuck_Env * env = this->env();
@@ -949,23 +983,25 @@ t_CKBOOL Chuck_Compiler:: load_external_modules( const char * extension, · 4 unmodified lines
949983 // load it
950984 type_engine_load_context( env, context );
951985
952− /* first load dynamic libraries explicitly named on the command line */
953− for(std::list<std::string>::iterator i_dl = named_dls.begin();
954− i_dl != named_dls.end(); i_dl++)
986+ // first load dynamic libraries explicitly named on the command line
987+ for( std::list<std::string>::iterator i_dl = named_dls.begin();
988+ i_dl != named_dls.end(); i_dl++ )
955989 {
990+ // get chugin name
956991 std::string & dl_path = *i_dl;
957− if(!extension_matches(dl_path.c_str(), extension))
992+ // check extension, append if no match
993+ if( !extension_matches(dl_path.c_str(), extension) )
958994 dl_path += extension;
959−
960− load_external_module_at_path(this, dl_path.c_str(),
961− dl_path.c_str());
995+ // load the module
996+ load_external_module_at_path( this, dl_path.c_str(), dl_path.c_str() );
962997 }
963998
964− /* now recurse through search paths and load any DLs or .ck files found */
965− for(std::list<std::string>::iterator i_sp = chugin_search_paths.begin();
966− i_sp != chugin_search_paths.end(); i_sp++)
999+ // now recurse through search paths and load any DLs or .ck files found
1000+ for( std::list<std::string>::iterator i_sp = chugin_search_paths.begin();
1001+ i_sp != chugin_search_paths.end(); i_sp++ )
9671002 {
968− load_external_modules_in_directory(this, (*i_sp).c_str(), extension);
1003+ // search directory and load contents
1004+ load_external_modules_in_directory( this, (*i_sp).c_str(), extension, recursiveSearch );
9691005 }
9701006
9711007 // clear context
@@ -975,18 +1011,207 @@ t_CKBOOL Chuck_Compiler:: load_external_modules( const char * extension, · 3 unmodified lines
9751011 env->global()->commit();
9761012
9771013 return TRUE;
978− /*
979−error:
1014+}
9801015
981− // probably dangerous: rollback
982− env->global()->rollback();
9831016
984− // clear context
985− type_engine_unload_context( env );
9861017
987− // pop indent level
1018+
1019+//-----------------------------------------------------------------------------
1020+// name: probe_external_module_at_path()
1021+// desc: probe external module
1022+//-----------------------------------------------------------------------------
1023+t_CKBOOL probe_external_module_at_path( const char * name, const char * dl_path )
1024+{
1025+ // create dynamic module
1026+ Chuck_DLL * dll = new Chuck_DLL( NULL, name );
1027+
1028+ // load the dll, lazy mode
1029+ if( dll->load(dl_path, CK_QUERY_FUNC, TRUE) )
1030+ {
1031+ // probe it
1032+ dll->probe();
1033+ // print
1034+ EM_log( CK_LOG_SYSTEM, "chugin %s [version %d.%d]", name, dll->versionMajor(), dll->versionMinor() );
1035+ // if not compatible
1036+ if( !dll->compatible() )
1037+ {
1038+ // push
1039+ EM_pushlog();
1040+ EM_log( CK_LOG_SYSTEM, "VERSION MISMATCH with host %d.%d", CK_DLL_VERSION_MAJOR, CK_DLL_VERSION_MINOR );
1041+ EM_poplog();
1042+ }
1043+ }
1044+ else
1045+ {
1046+ // print
1047+ EM_log( CK_LOG_SYSTEM, "chugin: '%s' FAILED to load...", name );
1048+ }
1049+
1050+ // done
1051+ return TRUE;
1052+}
1053+
1054+
1055+
1056+
1057+//-----------------------------------------------------------------------------
1058+// name: probe_external_modules_in_directory()
1059+// desc: probe all external modules by extension within a directory
1060+//-----------------------------------------------------------------------------
1061+t_CKBOOL probe_external_modules_in_directory( const char * directory,
1062+ const char * extension,
1063+ t_CKBOOL recursiveSearch,
1064+ std::list<std::string> & ck_libs )
1065+{
1066+ // expand directory path
1067+ string path = expandFilePath( directory );
1068+ // open the directory
1069+ DIR * dir = opendir( path.c_str() );
1070+
1071+ // log
1072+ // EM_log( CK_LOG_SYSTEM, "examining directory for chugins..." );
1073+ // print directory to examine
1074+ EM_log( CK_LOG_SYSTEM, "%s", directory );
1075+ // push
1076+ EM_pushlog();
1077+
1078+ // if successful
1079+ if( dir )
1080+ {
1081+ // do first read | 1.5.0.0 (ge + eito) #chunreal
1082+ struct dirent * de = readdir(dir);
1083+ // while( (de = readdir(dir)) ) <- UE5 forces us to not do this
1084+ while( de != NULL )
1085+ {
1086+ t_CKBOOL is_regular = false;
1087+ t_CKBOOL is_directory = false;
1088+ // get attributes
1089+ if( !getDirEntryAttribute( de, is_directory, is_regular ) ) continue;
1090+
1091+ // check | TODO: follow links?
1092+ if( is_regular )
1093+ {
1094+ // check for ck files to pre-load
1095+ if( extension_matches(de->d_name, ".ck") )
1096+ {
1097+ // print
1098+ // EM_log( CK_LOG_SYSTEM, "module %s", de->d_name );
1099+
1100+ // construct absolute path
1101+ std::string absolute_path = std::string(directory) + "/" + de->d_name;
1102+ // append file path
1103+ ck_libs.push_back(absolute_path);
1104+ }
1105+ // check extension passed in
1106+ else if( extension_matches(de->d_name, extension) )
1107+ {
1108+ // construct absolute path
1109+ std::string absolute_path = std::string(directory) + "/" + de->d_name;
1110+ // load module
1111+ probe_external_module_at_path( de->d_name, absolute_path.c_str() );
1112+ }
1113+ }
1114+ else if( recursiveSearch && is_directory )
1115+ {
1116+ // recurse | TODO: max depth?
1117+ if( strncmp(de->d_name, ".", sizeof(".")) != 0 &&
1118+ strncmp(de->d_name, "..", sizeof("..")) != 0 )
1119+ {
1120+ // construct absolute path
1121+ std::string absolute_path = std::string(directory) + "/" + de->d_name;
1122+ // search in sub-directory
1123+ probe_external_modules_in_directory( absolute_path.c_str(), extension, TRUE, ck_libs );
1124+ }
1125+ }
1126+#ifdef __PLATFORM_MACOSX__
1127+ else if( is_directory && extension_matches(de->d_name, extension) )
1128+ {
1129+ // On macOS, a chugin can either be a regular file (a .dylib simply renamed to .chug)
1130+ // or it can be a MODULE like using CMake with add_library(FooChugin MODULE foo.cpp)
1131+ // If it's a module bundle, then because .chug is a nonstandard extension,
1132+ // on the filesystem it shows up as a directory ending in .chug.
1133+ // If we see one of these directories, we can dive directly to the Contents/MacOS subfolder
1134+ // and look for a regular file. | 1.5.0.1 (dbraun) added
1135+ std::string absolute_path = std::string(directory) + "/" + de->d_name + "/Contents/MacOS";
1136+ const char * subdirectory = absolute_path.c_str();
1137+ probe_external_modules_in_directory( subdirectory, "", FALSE, ck_libs );
1138+ }
1139+#endif // #ifdef __PLATFORM_MACOSX__
1140+
1141+ // read next | 1.5.0.0 (ge) moved here due to #chunreal
1142+ de = readdir( dir );
1143+ }
1144+
1145+ // close
1146+ closedir( dir );
1147+ }
1148+ else
1149+ {
1150+ // log (1.3.1.2: changed to 2 lines to stay within 80 chars)
1151+ EM_pushlog();
1152+ EM_log( CK_LOG_SYSTEM, "unable to open directory..." );
1153+ EM_log( CK_LOG_SYSTEM, "ignoring for chugins..." );
1154+ EM_poplog();
1155+ }
1156+
1157+ // pop log
9881158 EM_poplog();
9891159
990− return FALSE;
991− */
1160+ return TRUE;
1161+}
1162+
1163+
1164+
1165+
1166+//-----------------------------------------------------------------------------
1167+// name: probe_external_modules()
1168+// desc: probe external modules (e.g., .chug and .ck library files)
1169+//-----------------------------------------------------------------------------
1170+t_CKBOOL Chuck_Compiler::probe_external_modules( const char * extension,
1171+ std::list<std::string> & chugin_search_paths,
1172+ std::list<std::string> & named_dls,
1173+ t_CKBOOL recursiveSearch,
1174+ std::list<std::string> & ck_libs )
1175+{
1176+ // print
1177+ EM_log( CK_LOG_SYSTEM, "probing specified chugins..." );
1178+ // push
1179+ EM_pushlog();
1180+
1181+ // first load dynamic libraries explicitly named on the command line
1182+ for( std::list<std::string>::iterator i_dl = named_dls.begin();
1183+ i_dl != named_dls.end(); i_dl++ )
1184+ {
1185+ // get chugin name
1186+ std::string & dl_path = *i_dl;
1187+ // check extension, append if no match
1188+ if( !extension_matches(dl_path.c_str(), extension) )
1189+ dl_path += extension;
1190+ // load the module
1191+ probe_external_module_at_path( dl_path.c_str(), dl_path.c_str() );
1192+ }
1193+
1194+ // check
1195+ if( named_dls.size() == 0 )
1196+ EM_log( CK_LOG_SYSTEM, "(none specified)" );
1197+
1198+ // pop
1199+ EM_poplog();
1200+ // print
1201+ EM_log( CK_LOG_SYSTEM, "probing chugins in search paths..." );
1202+ // push
1203+ EM_pushlog();
1204+
1205+ // now recurse through search paths and load any DLs or .ck files found
1206+ for( std::list<std::string>::iterator i_sp = chugin_search_paths.begin();
1207+ i_sp != chugin_search_paths.end(); i_sp++ )
1208+ {
1209+ // search directory and load contents
1210+ probe_external_modules_in_directory( (*i_sp).c_str(), extension, recursiveSearch, ck_libs );
1211+ }
1212+
1213+ // pop
1214+ EM_poplog();
1215+
1216+ return TRUE;
9921217 }
src/core/chuck_compile.h+11−2
@@ -123,10 +123,19 @@ public: // replace-dac | added 1.4.1.0 (jack) · 122 unmodified lines
123123 // of a new sample sucker.
124124 void setReplaceDac( t_CKBOOL shouldReplaceDac, const std::string & replacement );
125125
126−public: // chugin load | refactored 1.4.1.0 (ge)
126+public:
127+ // chugin load | 1.4.1.0 (ge) refactored
127128 t_CKBOOL load_external_modules( const char * extension,
128129 std::list<std::string> & chugin_search_paths,
129− std::list<std::string> & named_dls );
130+ std::list<std::string> & named_dls,
131+ t_CKBOOL recursiveSearch );
132+
133+ // chugin probe | 1.5.0.4 (ge) added
134+ static t_CKBOOL probe_external_modules( const char * extension,
135+ std::list<std::string> & chugin_search_paths,
136+ std::list<std::string> & named_dls,
137+ t_CKBOOL recursiveSearch,
138+ std::list<std::string> & ck_libs );
130139
131140 protected: // internal
132141 // do entire file
src/core/chuck_dl.cpp+105−25
@@ -719,7 +719,7 @@ t_CKBOOL Chuck_DLL::good() const · 718 unmodified lines
719719 // name: query()
720720 // desc: ...
721721 //-----------------------------------------------------------------------------
722−const Chuck_DL_Query * Chuck_DLL::query( )
722+const Chuck_DL_Query * Chuck_DLL::query()
723723 {
724724 if( !m_handle && !m_query_func )
725725 {
@@ -738,38 +738,38 @@ const Chuck_DL_Query * Chuck_DLL::query( ) · 12 unmodified lines
738738 m_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() );
739739 if( !m_version_func )
740740 {
741− m_last_error = string("no version function found in dll '")
742− + m_filename + string("'");
741+ m_last_error = string("no version function found in dll '") + m_filename + string("'");
743742 return NULL;
744743 }
745744
746745 // check version
747746 t_CKUINT dll_version = m_version_func();
747+ // get major and minor version numbers
748+ m_versionMajor = CK_DLL_VERSION_GETMAJOR(dll_version);
749+ m_versionMinor = CK_DLL_VERSION_GETMINOR(dll_version);
750+ // is version ok
748751 t_CKBOOL version_ok = FALSE;
749− // major version must be same
750− // minor version must less than or equal
751− if(CK_DLL_VERSION_GETMAJOR(dll_version) == CK_DLL_VERSION_MAJOR &&
752− CK_DLL_VERSION_GETMINOR(dll_version) <= CK_DLL_VERSION_MINOR)
752+ // major version must be same; minor version must less than or equal
753+ if( m_versionMajor == CK_DLL_VERSION_MAJOR && m_versionMinor <= CK_DLL_VERSION_MINOR)
753754 version_ok = TRUE;
754755
755− if(!version_ok)
756− // SPENCERTODO: do they need to be equal, or can dll_version be < ?
756+ // if version not okay
757+ if( !version_ok )
757758 {
759+ // construct error string
758760 ostringstream oss;
759761 oss << "chugin version mismatch:" << endl
760− << "filename: "
761− << m_filename << "'" << endl
762− << "versions: chugin: "
763− << CK_DLL_VERSION_GETMAJOR(dll_version)
764− << "."
765− << CK_DLL_VERSION_GETMINOR(dll_version)
766− << " vs. chuck host: "
767− << CK_DLL_VERSION_MAJOR
768− << "."
769− << CK_DLL_VERSION_MINOR;
770−
762+ << "filename: "
763+ << m_filename << "'" << endl
764+ << "versions: chugin: "
765+ << CK_DLL_VERSION_GETMAJOR(dll_version)
766+ << "."
767+ << CK_DLL_VERSION_GETMINOR(dll_version)
768+ << " vs. chuck host: "
769+ << CK_DLL_VERSION_MAJOR
770+ << "."
771+ << CK_DLL_VERSION_MINOR;
771772 m_last_error = oss.str();
772−
773773 return NULL;
774774 }
775775
@@ -780,8 +780,7 @@ const Chuck_DL_Query * Chuck_DLL::query( ) · 4 unmodified lines
780780 m_query_func = (f_ck_query)this->get_addr( (string("_")+m_func).c_str() );
781781 if( !m_query_func )
782782 {
783− m_last_error = string("no query function found in dll '")
784− + m_filename + string("'");
783+ m_last_error = string("no query function found in dll '") + m_filename + string("'");
785784 return NULL;
786785 }
787786
@@ -861,6 +860,41 @@ const Chuck_DL_Query * Chuck_DLL::query( ) · 73 unmodified lines
861860
862861
863862
863+//-----------------------------------------------------------------------------
864+// name: probe()
865+// desc: probe the dll without fully loading its content
866+//-----------------------------------------------------------------------------
867+t_CKBOOL Chuck_DLL::probe()
868+{
869+ if( !m_handle && !m_query_func )
870+ {
871+ m_last_error = "dynamic link library not loaded for query...";
872+ return FALSE;
873+ }
874+
875+ // get the address of the DL version function from the DLL
876+ if( !m_version_func )
877+ m_version_func = (f_ck_declversion)this->get_addr( CK_DECLVERSION_FUNC );
878+ if( !m_version_func )
879+ m_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() );
880+ if( !m_version_func )
881+ {
882+ m_last_error = string("no version function found in dll '") + m_filename + string("'");
883+ return FALSE;
884+ }
885+
886+ // check version
887+ t_CKUINT dll_version = m_version_func();
888+ // get major and minor version numbers
889+ m_versionMajor = CK_DLL_VERSION_GETMAJOR(dll_version);
890+ m_versionMinor = CK_DLL_VERSION_GETMINOR(dll_version);
891+
892+ return TRUE;
893+}
894+
895+
896+
897+
864898 //-----------------------------------------------------------------------------
865899 // name: unload()
866900 // desc: ...
@@ -921,7 +955,7 @@ const char * Chuck_DLL::last_error() const · 54 unmodified lines
921955
922956 //-----------------------------------------------------------------------------
923957 // name: name()
924−// desc: ...
958+// desc: return name given to dll
925959 //-----------------------------------------------------------------------------
926960 const char * Chuck_DLL::name() const
927961 {
@@ -929,7 +963,53 @@ const char * Chuck_DLL::name() const · 1 unmodified line
929963 }
930964
931965
932−//const t_CKUINT Chuck_DL_Query::RESERVED_SIZE;
966+
967+
968+//-----------------------------------------------------------------------------
969+// name: versionMajor()
970+// desc: get version major
971+//-----------------------------------------------------------------------------
972+t_CKUINT Chuck_DLL::versionMajor()
973+{
974+ // probe dll
975+ if( !this->probe() ) return 0;
976+ // return
977+ return m_versionMajor;
978+}
979+
980+
981+
982+
983+//-----------------------------------------------------------------------------
984+// name: versionMinor()
985+// desc: get version minor
986+//-----------------------------------------------------------------------------
987+t_CKUINT Chuck_DLL::versionMinor()
988+{
989+ // probe dll
990+ if( !this->probe() ) return 0;
991+ // return
992+ return m_versionMinor;
993+}
994+
995+
996+
997+
998+//-----------------------------------------------------------------------------
999+// name: compatible()
1000+// desc: if version compatible between chugin and host
1001+//-----------------------------------------------------------------------------
1002+t_CKBOOL Chuck_DLL::compatible()
1003+{
1004+ // probe dll
1005+ if( !this->probe() ) return FALSE;
1006+ // major version must be same between chugin and host
1007+ // chugin minor version must less than or equal host minor version
1008+ return ( m_versionMajor == CK_DLL_VERSION_MAJOR && m_versionMinor <= CK_DLL_VERSION_MINOR );
1009+}
1010+
1011+
1012+
9331013
9341014 //-----------------------------------------------------------------------------
9351015 // name: Chuck_DL_Query
src/core/chuck_dl.h+18−4
@@ -604,20 +604,30 @@ public: · 603 unmodified lines
604604 // get last error
605605 const char * last_error() const;
606606 // unload the ckx
607− t_CKBOOL unload( );
607+ t_CKBOOL unload();
608608 // query the content of the dll
609− const Chuck_DL_Query * query( );
609+ const Chuck_DL_Query * query();
610+ // probe information about dll without fully loading it
611+ t_CKBOOL probe();
610612 // is good
611613 t_CKBOOL good() const;
612614 // name
613615 const char * name() const;
616+ // get version major
617+ t_CKUINT versionMajor();
618+ // get version minor
619+ t_CKUINT versionMinor();
620+ // is version compatible between dll and host
621+ // major version must be same between chugin and host
622+ // chugin minor version must less than or equal host minor version
623+ t_CKBOOL compatible();
614624
615625 public:
616626 // constructor
617627 Chuck_DLL( Chuck_Carrier * carrier, const char * xid = NULL )
618628 : m_handle(NULL), m_id(xid ? xid : ""),
619− m_query( carrier ),
620− m_done_query(FALSE), m_query_func(NULL), m_version_func(NULL)
629+ m_query( carrier ), m_done_query(FALSE), m_query_func(NULL),
630+ m_version_func(NULL), m_versionMajor(0), m_versionMinor(0)
621631 { }
622632 // destructor
623633 ~Chuck_DLL() { this->unload(); }
@@ -634,6 +644,10 @@ protected: · 10 unmodified lines
634644 f_ck_declversion m_version_func;
635645 f_ck_query m_query_func;
636646 Chuck_DL_Query m_query;
647+
648+protected: // addition info 1.5.0.4 (ge) added
649+ t_CKUINT m_versionMajor;
650+ t_CKUINT m_versionMinor;
637651 };
638652
639653
src/core/chuck_errmsg.cpp+1−1
@@ -613,7 +613,7 @@ void EM_setlog( t_CKINT level ) · 612 unmodified lines
613613 g_loglevel = level;
614614
615615 // log this
616− EM_log( CK_LOG_SYSTEM, "setting log level to: %li (%s)...", level, g_str[level] );
616+ EM_log( CK_LOG_INFO, "setting log level to: %li (%s)...", level, g_str[level] );
617617 }
618618
619619 // push log
src/host/chuck_main.cpp+16−13
@@ -221,7 +221,8 @@ void usage() · 220 unmodified lines
221221 CK_FPRINTF_STDERR( " srate:<N>|bufsize:<N>|bufnum:<N>|shell|empty|\n" );
222222 CK_FPRINTF_STDERR( " remote:<hostname>|port:<N>|verbose:<N>|level:<N>|\n" );
223223 CK_FPRINTF_STDERR( " callback|deprecate:{stop|warn|ignore}|\n" );
224− CK_FPRINTF_STDERR( " chugin-load:{on|off}|chugin-path:<path>|chugin:<name>\n" );
224+ CK_FPRINTF_STDERR( " chugin-load:{on|off}|chugin-path:<path>|chugin:<name>|\n" );
225+ CK_FPRINTF_STDERR( " chugin-probe\n" );
225226 CK_FPRINTF_STDERR( " [commands] = add|remove|replace|remove.all|status|time|kill\n" );
226227 CK_FPRINTF_STDERR( " [+-=^] = shortcuts for add, remove, replace, status\n" );
227228 version();
@@ -471,6 +472,7 @@ bool go( int argc, const char ** argv ) · 243 unmodified lines
471472 t_CKINT adc_chans_before_rtaudio = adc_chans; // added 1.5.0.0
472473 t_CKBOOL dump = FALSE;
473474 t_CKBOOL probe = FALSE;
475+ t_CKBOOL probe_chugs = FALSE;
474476 t_CKBOOL set_priority = FALSE;
475477 t_CKBOOL auto_depend = FALSE;
476478 t_CKBOOL block = FALSE;
@@ -767,6 +769,8 @@ bool go( int argc, const char ** argv ) · 290 unmodified lines
767769 }
768770 else if( !strcmp( argv[i], "--probe" ) )
769771 probe = TRUE;
772+ else if( !strcmp( argv[i], "--chugin-probe" ) )
773+ probe_chugs = TRUE;
770774 else if( !strcmp( argv[i], "--poop" ) )
771775 uh();
772776 else if( !strcmp( argv[i], "--caution-to-the-wind" ) )
@@ -832,9 +836,8 @@ bool go( int argc, const char ** argv ) · 59 unmodified lines
832836 // probe HID devices
833837 HidInManager::probeHidIn();
834838
835− // don't exit, wait to probe chugins, which needs a ChucK instance | 1.5.0.4
836− // exit
837− // exit( 0 );
839+ // done probe
840+ exit( 0 );
838841 }
839842
840843 // set caution to wind
@@ -854,7 +857,7 @@ bool go( int argc, const char ** argv ) · 13 unmodified lines
854857 // set adaptive size
855858 if( adaptive_size < 0 ) adaptive_size = buffer_size;
856859
857− if( !files && vm_halt && !g_enable_shell )
860+ if( !files && vm_halt && !g_enable_shell && !probe_chugs )
858861 {
859862 CK_FPRINTF_STDERR( "[chuck]: no input files... (try --help)\n" );
860863 exit( 1 );
@@ -884,7 +887,7 @@ bool go( int argc, const char ** argv ) · 23 unmodified lines
884887 }
885888
886889 // find dac_name if appropriate (added 1.3.0.0)
887− if( dac_name.size() > 0 )
890+ if( !probe_chugs && dac_name.size() > 0 )
888891 {
889892 // check with RtAudio
890893 t_CKINT dev = ChuckAudio::device_named( audioDriver, dac_name, TRUE, FALSE );
@@ -901,7 +904,7 @@ bool go( int argc, const char ** argv ) · 10 unmodified lines
901904 }
902905
903906 // find adc_name if appropriate (added 1.3.0.0)
904− if( adc_name.size() > 0 )
907+ if( !probe_chugs && adc_name.size() > 0 )
905908 {
906909 // check with RtAudio
907910 t_CKINT dev = ChuckAudio::device_named( audioDriver, adc_name, FALSE, TRUE );
@@ -917,16 +920,11 @@ bool go( int argc, const char ** argv ) · 9 unmodified lines
917920 }
918921 }
919922
920−
921923 //-------------------- VIRTUAL MACHINE SETUP (PART 1) -------------------------
922924 // instantiate a ChucK!
923925 the_chuck = new ChucK();
924926 // set log level so things can start logging
925927 the_chuck->setLogLevel( log_level );
926− // log
927− EM_log( CK_LOG_SYSTEM, "booting up ChucK instance..." );
928− // push
929− EM_pushlog();
930928
931929 // set chugins parameters
932930 the_chuck->setParam( CHUCK_PARAM_CHUGIN_ENABLE, chugin_load );
@@ -934,7 +932,7 @@ bool go( int argc, const char ** argv ) · 1 unmodified line
934932 the_chuck->setParam( CHUCK_PARAM_USER_CHUGIN_DIRECTORIES, dl_search_path );
935933
936934 // probe chugins | 1.5.0.4 (ge) added
937− if( probe )
935+ if( probe_chugs )
938936 {
939937 // ensure log level is at least SYSTEM
940938 if( the_chuck->getLogLevel() < CK_LOG_SYSTEM )
@@ -948,6 +946,11 @@ bool go( int argc, const char ** argv ) · 7 unmodified lines
948946 exit( 0 );
949947 }
950948
949+ // log
950+ EM_log( CK_LOG_SYSTEM, "booting up ChucK instance..." );
951+ // push
952+ EM_pushlog();
953+
951954 //--------------------------- AUDIO I/O SETUP ---------------------------------
952955 // log
953956 EM_log( CK_LOG_SYSTEM, "initializing audio subsystem..." );

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t