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
2ChucK VERSIONS log2ChucK VERSIONS log
3------------------3------------------
4 4
51.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
51.5.0.3 (June 2023)141.5.0.3 (June 2023)
6---15---
7- (fixed) chuck audio I/O now correctly carries out extended probing16- (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
630 // push indent level630 // push indent level
631 EM_pushlog();631 EM_pushlog();
632 // load external libs632 // 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 ) )
634 {634 {
635 // pop indent level635 // pop indent level
636 EM_poplog();636 EM_poplog();
@@ -722,11 +722,20 @@ error: // 1.4.1.0 (ge) added · 85 unmodified lines
722//-----------------------------------------------------------------------------722//-----------------------------------------------------------------------------
723void ChucK::probeChugins()723void ChucK::probeChugins()
724{724{
725 Chuck_VM_Code * code = NULL;725 // ck files to pre load
726 Chuck_VM_Shred * shred = NULL;726 std::list<std::string> ck_libs_to_preload;
727 727
728 // print whether chugins enabled728 // print whether chugins enabled
729 EM_log( CK_LOG_SYSTEM, "chugin system: %s", getParamInt( CHUCK_PARAM_CHUGIN_ENABLE ) ? "ON" : "OFF" );729 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();
730 739
731 // chugin dur740 // chugin dur
732 std::string chuginDir = getParamString( CHUCK_PARAM_CHUGIN_DIRECTORY );741 std::string chuginDir = getParamString( CHUCK_PARAM_CHUGIN_DIRECTORY );
@@ -741,61 +750,35 @@ void ChucK::probeChugins() · 8 unmodified lines
741 std::list<std::string> named_dls = getParamStringList( CHUCK_PARAM_USER_CHUGINS );750 std::list<std::string> named_dls = getParamStringList( CHUCK_PARAM_USER_CHUGINS );
742 751
743 // log752 // log
744 EM_log( CK_LOG_SYSTEM, "probing chugins..." );753 EM_log( CK_LOG_SYSTEM, "probing chugins (.chug)..." );
745 // push indent level754 // push indent level
746 EM_pushlog();755 EM_pushlog();
747 // load external libs756 // 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 ) )
749 {758 {
750 // pop indent level759 // warning
751 EM_poplog();760 EM_log( CK_LOG_SYSTEM, "error probing chugins..." );
752 // clean up
753 // goto error;
754 }761 }
755 // pop log762 // pop log
756 EM_poplog();763 EM_poplog();
757 764
758 // log765 // log
759 EM_log( CK_LOG_SYSTEM, "probing pre-loading ChucK libs..." );766 EM_log( CK_LOG_SYSTEM, "probing auto-load chuck files (.ck)..." );
760 EM_pushlog();767 EM_pushlog();
761 768
762 // iterate over list of ck files that the compiler found769 // iterate over list of ck files that the compiler found
763 for( std::list<std::string>::iterator j =770 for( std::list<std::string>::iterator j = ck_libs_to_preload.begin();
764 compiler()->m_cklibs_to_preload.begin();771 j != ck_libs_to_preload.end(); j++ )
765 j != compiler()->m_cklibs_to_preload.end(); j++ )
766 {772 {
767 // the filename773 // the filename
768 std::string filename = *j;774 std::string filename = *j;
769
770 // log775 // log
771 EM_log( CK_LOG_SEVERE, "preloading '%s'...", filename.c_str() );776 EM_log( CK_LOG_SYSTEM, "source '%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();
795 }777 }
796 778
797 // clear the list of chuck files to preload779 // check
798 compiler()->m_cklibs_to_preload.clear();780 if( ck_libs_to_preload.size() == 0 )
781 EM_log( CK_LOG_SYSTEM, "(none found)" );
799 782
800 // pop log783 // pop log
801 EM_poplog();784 EM_poplog();
src/core/chuck_compile.cpp+333−108
@@ -745,6 +745,78 @@ error: · 744 unmodified lines
745 745
746 746
747 747
748
749//-----------------------------------------------------------------------------
750// name: expandfilePath()
751// desc: expand file path, e.g., ~ on unix systems | 1.5.0.4 (ge) moved here
752//-----------------------------------------------------------------------------
753std::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//-----------------------------------------------------------------------------
786t_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
748//-----------------------------------------------------------------------------820//-----------------------------------------------------------------------------
749// name: load_external_module_at_path()821// name: load_external_module_at_path()
750// desc: ...822// desc: ...
@@ -789,116 +861,82 @@ t_CKBOOL load_external_module_at_path( Chuck_Compiler * compiler, · 38 unmodified lines
789 861
790//-----------------------------------------------------------------------------862//-----------------------------------------------------------------------------
791// name: load_external_modules_in_directory()863// name: load_external_modules_in_directory()
792// desc: ...864// desc: load all external modules by extension within a directory
793//-----------------------------------------------------------------------------865//-----------------------------------------------------------------------------
794t_CKBOOL load_external_modules_in_directory( Chuck_Compiler * compiler,866t_CKBOOL load_external_modules_in_directory( Chuck_Compiler * compiler,
795 const char * directory,867 const char * directory,
796 const char * extension )868 const char * extension,
869 t_CKBOOL recursiveSearch = FALSE )
797{870{
798 static const t_CKBOOL RECURSIVE_SEARCH = false;871 // expand directory path
799 872 string path = expandFilePath( directory );
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
817 // open the directory873 // open the directory
818 DIR * dir = opendir( path.c_str() );874 DIR * dir = opendir( path.c_str() );
819 875
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
820 // if successful883 // if successful
821 if( dir )884 if( dir )
822 {885 {
823 // log
824 EM_log( CK_LOG_INFO, "examining directory '%s' for chugins", directory );
825
826 // do first read | 1.5.0.0 (ge + eito) #chunreal886 // do first read | 1.5.0.0 (ge + eito) #chunreal
827 struct dirent * de = readdir(dir);887 struct dirent * de = readdir(dir);
828 888 // while( (de = readdir(dir)) ) <- UE5 forces us to not do this
829 // while( (de = readdir(dir)) ) <- in ge's opinion clearer than what UE5 forces us to do
830 while( de != NULL )889 while( de != NULL )
831 {890 {
832 t_CKBOOL is_regular = false;891 t_CKBOOL is_regular = false;
833 t_CKBOOL is_directory = false;892 t_CKBOOL is_directory = false;
893 // get attributes
894 if( !getDirEntryAttribute( de, is_directory, is_regular ) ) continue;
834 895
835#if defined(__PLATFORM_WIN32__)896 // check | TODO: follow links?
836 is_directory = de->data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;897 if( is_regular )
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?
862 {898 {
863 if( extension_matches(de->d_name, extension) )899 // check for ck files to pre-load
900 if( extension_matches(de->d_name, ".ck") )
864 {901 {
902 // construct absolute path
865 std::string absolute_path = std::string(directory) + "/" + de->d_name;903 std::string absolute_path = std::string(directory) + "/" + de->d_name;
866 904 // append file path
867 load_external_module_at_path(compiler, de->d_name,905 compiler->m_cklibs_to_preload.push_back(absolute_path);
868 absolute_path.c_str());
869 }906 }
870 else if( extension_matches(de->d_name, ".ck") )907 // check extension passed in
908 else if( extension_matches(de->d_name, extension) )
871 {909 {
910 // construct absolute path
872 std::string absolute_path = std::string(directory) + "/" + de->d_name;911 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() );
874 }914 }
875 }915 }
876 else if( RECURSIVE_SEARCH && is_directory )916 else if( recursiveSearch && is_directory )
877 {917 {
878 // recurse918 // recurse | TODO: max depth?
879 // TODO: max depth?
880 if( strncmp(de->d_name, ".", sizeof(".")) != 0 &&919 if( strncmp(de->d_name, ".", sizeof(".")) != 0 &&
881 strncmp(de->d_name, "..", sizeof("..")) != 0 )920 strncmp(de->d_name, "..", sizeof("..")) != 0 )
882 {921 {
922 // construct absolute path
883 std::string absolute_path = std::string(directory) + "/" + de->d_name;923 std::string absolute_path = std::string(directory) + "/" + de->d_name;
884 load_external_modules_in_directory(compiler,924 // search in sub-directory
885 absolute_path.c_str(),925 load_external_modules_in_directory( compiler, absolute_path.c_str(), extension);
886 extension);
887 }926 }
888 }927 }
889#ifdef __PLATFORM_MACOSX__928#ifdef __PLATFORM_MACOSX__
890 // #if __APPLE__ probably cleaner but using the above for consistency for now (ge)929 else if( is_directory && extension_matches(de->d_name, extension) )
891 // ---930 {
892 // On macOS, a chugin can either be a regular file (a .dylib simply renamed to .chug)931 // 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)932 // 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,933 // 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.934 // 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 subfolder935 // 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) added936 // and look for a regular file. | 1.5.0.1 (dbraun) added
898 else if (is_directory && extension_matches(de->d_name, extension)) {
899 std::string absolute_path = std::string(directory) + "/" + de->d_name + "/Contents/MacOS";937 std::string absolute_path = std::string(directory) + "/" + de->d_name + "/Contents/MacOS";
900 const char* subdirectory = absolute_path.c_str();938 const char * subdirectory = absolute_path.c_str();
901 load_external_modules_in_directory(compiler, subdirectory, "");939 load_external_modules_in_directory( compiler, subdirectory, "" );
902 }940 }
903#endif // #ifdef __PLATFORM_MACOSX__941#endif // #ifdef __PLATFORM_MACOSX__
904 942
@@ -912,19 +950,14 @@ t_CKBOOL load_external_modules_in_directory( Chuck_Compiler * compiler, · 7 unmodified lines
912 else950 else
913 {951 {
914 // log (1.3.1.2: changed to 2 lines to stay within 80 chars)952 // log (1.3.1.2: changed to 2 lines to stay within 80 chars)
915 EM_log( CK_LOG_INFO, "unable to open directory:" );
916 EM_pushlog();953 EM_pushlog();
917 EM_log( CK_LOG_INFO, "'%s'", directory );954 EM_log( CK_LOG_INFO, "unable to open directory..." );
918 EM_log( CK_LOG_INFO, "ignoring for chugins..." );955 EM_log( CK_LOG_INFO, "ignoring for chugins..." );
919 EM_poplog();956 EM_poplog();
920 }957 }
921 958
922#ifndef __PLATFORM_WIN32__959 // pop log
923#ifndef __DISABLE_WORDEXP__960 EM_poplog();
924 // free | 1.5.0.0 (ge) added
925 wordfree( &exp_result );
926#endif
927#endif
928 961
929 return TRUE;962 return TRUE;
930}963}
@@ -934,11 +967,12 @@ t_CKBOOL load_external_modules_in_directory( Chuck_Compiler * compiler, · 3 unmodified lines
934 967
935//-----------------------------------------------------------------------------968//-----------------------------------------------------------------------------
936// name: load_external_modules()969// name: load_external_modules()
937// desc: ...970// desc: load external modules (e.g., .chug and .ck library files)
938//-----------------------------------------------------------------------------971//-----------------------------------------------------------------------------
939t_CKBOOL Chuck_Compiler:: load_external_modules( const char * extension,972t_CKBOOL Chuck_Compiler::load_external_modules( const char * extension,
940 std::list<std::string> & chugin_search_paths,973 std::list<std::string> & chugin_search_paths,
941 std::list<std::string> & named_dls )974 std::list<std::string> & named_dls,
975 t_CKBOOL recursiveSearch )
942{976{
943 // get env977 // get env
944 Chuck_Env * env = this->env();978 Chuck_Env * env = this->env();
@@ -949,23 +983,25 @@ t_CKBOOL Chuck_Compiler:: load_external_modules( const char * extension, · 4 unmodified lines
949 // load it983 // load it
950 type_engine_load_context( env, context );984 type_engine_load_context( env, context );
951 985
952 /* first load dynamic libraries explicitly named on the command line */986 // first load dynamic libraries explicitly named on the command line
953 for(std::list<std::string>::iterator i_dl = named_dls.begin();987 for( std::list<std::string>::iterator i_dl = named_dls.begin();
954 i_dl != named_dls.end(); i_dl++)988 i_dl != named_dls.end(); i_dl++ )
955 {989 {
990 // get chugin name
956 std::string & dl_path = *i_dl;991 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) )
958 dl_path += extension;994 dl_path += extension;
959 995 // load the module
960 load_external_module_at_path(this, dl_path.c_str(),996 load_external_module_at_path( this, dl_path.c_str(), dl_path.c_str() );
961 dl_path.c_str());
962 }997 }
963 998
964 /* now recurse through search paths and load any DLs or .ck files found */999 // 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();1000 for( std::list<std::string>::iterator i_sp = chugin_search_paths.begin();
966 i_sp != chugin_search_paths.end(); i_sp++)1001 i_sp != chugin_search_paths.end(); i_sp++ )
967 {1002 {
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 );
969 }1005 }
970 1006
971 // clear context1007 // clear context
@@ -975,18 +1011,207 @@ t_CKBOOL Chuck_Compiler:: load_external_modules( const char * extension, · 3 unmodified lines
975 env->global()->commit();1011 env->global()->commit();
976 1012
977 return TRUE;1013 return TRUE;
978 /*1014}
979error:
980 1015
981 // probably dangerous: rollback
982 env->global()->rollback();
983 1016
984 // clear context
985 type_engine_unload_context( env );
986 1017
987 // pop indent level1018
1019//-----------------------------------------------------------------------------
1020// name: probe_external_module_at_path()
1021// desc: probe external module
1022//-----------------------------------------------------------------------------
1023t_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//-----------------------------------------------------------------------------
1061t_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
988 EM_poplog();1158 EM_poplog();
989 1159
990 return FALSE;1160 return TRUE;
991 */1161}
1162
1163
1164
1165
1166//-----------------------------------------------------------------------------
1167// name: probe_external_modules()
1168// desc: probe external modules (e.g., .chug and .ck library files)
1169//-----------------------------------------------------------------------------
1170t_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;
992}1217}
src/core/chuck_compile.h+11−2
@@ -123,10 +123,19 @@ public: // replace-dac | added 1.4.1.0 (jack) · 122 unmodified lines
123 // of a new sample sucker.123 // of a new sample sucker.
124 void setReplaceDac( t_CKBOOL shouldReplaceDac, const std::string & replacement );124 void setReplaceDac( t_CKBOOL shouldReplaceDac, const std::string & replacement );
125 125
126public: // chugin load | refactored 1.4.1.0 (ge)126public:
127 // chugin load | 1.4.1.0 (ge) refactored
127 t_CKBOOL load_external_modules( const char * extension,128 t_CKBOOL load_external_modules( const char * extension,
128 std::list<std::string> & chugin_search_paths,129 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 );
130 139
131protected: // internal140protected: // internal
132 // do entire file141 // do entire file
src/core/chuck_dl.cpp+105−25
@@ -719,7 +719,7 @@ t_CKBOOL Chuck_DLL::good() const · 718 unmodified lines
719// name: query()719// name: query()
720// desc: ...720// desc: ...
721//-----------------------------------------------------------------------------721//-----------------------------------------------------------------------------
722const Chuck_DL_Query * Chuck_DLL::query( )722const Chuck_DL_Query * Chuck_DLL::query()
723{723{
724 if( !m_handle && !m_query_func )724 if( !m_handle && !m_query_func )
725 {725 {
@@ -738,38 +738,38 @@ const Chuck_DL_Query * Chuck_DLL::query( ) · 12 unmodified lines
738 m_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() );738 m_version_func = (f_ck_declversion)this->get_addr( (string("_")+CK_DECLVERSION_FUNC).c_str() );
739 if( !m_version_func )739 if( !m_version_func )
740 {740 {
741 m_last_error = string("no version function found in dll '")741 m_last_error = string("no version function found in dll '") + m_filename + string("'");
742 + m_filename + string("'");
743 return NULL;742 return NULL;
744 }743 }
745 744
746 // check version745 // check version
747 t_CKUINT dll_version = m_version_func();746 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
748 t_CKBOOL version_ok = FALSE;751 t_CKBOOL version_ok = FALSE;
749 // major version must be same752 // major version must be same; minor version must less than or equal
750 // minor version must less than or equal753 if( m_versionMajor == CK_DLL_VERSION_MAJOR && m_versionMinor <= CK_DLL_VERSION_MINOR)
751 if(CK_DLL_VERSION_GETMAJOR(dll_version) == CK_DLL_VERSION_MAJOR &&
752 CK_DLL_VERSION_GETMINOR(dll_version) <= CK_DLL_VERSION_MINOR)
753 version_ok = TRUE;754 version_ok = TRUE;
754 755
755 if(!version_ok)756 // if version not okay
756 // SPENCERTODO: do they need to be equal, or can dll_version be < ?757 if( !version_ok )
757 {758 {
759 // construct error string
758 ostringstream oss;760 ostringstream oss;
759 oss << "chugin version mismatch:" << endl761 oss << "chugin version mismatch:" << endl
760 << "filename: "762 << "filename: "
761 << m_filename << "'" << endl763 << m_filename << "'" << endl
762 << "versions: chugin: "764 << "versions: chugin: "
763 << CK_DLL_VERSION_GETMAJOR(dll_version)765 << CK_DLL_VERSION_GETMAJOR(dll_version)
764 << "."766 << "."
765 << CK_DLL_VERSION_GETMINOR(dll_version)767 << CK_DLL_VERSION_GETMINOR(dll_version)
766 << " vs. chuck host: "768 << " vs. chuck host: "
767 << CK_DLL_VERSION_MAJOR769 << CK_DLL_VERSION_MAJOR
768 << "."770 << "."
769 << CK_DLL_VERSION_MINOR;771 << CK_DLL_VERSION_MINOR;
770
771 m_last_error = oss.str();772 m_last_error = oss.str();
772
773 return NULL;773 return NULL;
774 }774 }
775 775
@@ -780,8 +780,7 @@ const Chuck_DL_Query * Chuck_DLL::query( ) · 4 unmodified lines
780 m_query_func = (f_ck_query)this->get_addr( (string("_")+m_func).c_str() );780 m_query_func = (f_ck_query)this->get_addr( (string("_")+m_func).c_str() );
781 if( !m_query_func )781 if( !m_query_func )
782 {782 {
783 m_last_error = string("no query function found in dll '")783 m_last_error = string("no query function found in dll '") + m_filename + string("'");
784 + m_filename + string("'");
785 return NULL;784 return NULL;
786 }785 }
787 786
@@ -861,6 +860,41 @@ const Chuck_DL_Query * Chuck_DLL::query( ) · 73 unmodified lines
861 860
862 861
863 862
863//-----------------------------------------------------------------------------
864// name: probe()
865// desc: probe the dll without fully loading its content
866//-----------------------------------------------------------------------------
867t_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
864//-----------------------------------------------------------------------------898//-----------------------------------------------------------------------------
865// name: unload()899// name: unload()
866// desc: ...900// desc: ...
@@ -921,7 +955,7 @@ const char * Chuck_DLL::last_error() const · 54 unmodified lines
921 955
922//-----------------------------------------------------------------------------956//-----------------------------------------------------------------------------
923// name: name()957// name: name()
924// desc: ...958// desc: return name given to dll
925//-----------------------------------------------------------------------------959//-----------------------------------------------------------------------------
926const char * Chuck_DLL::name() const960const char * Chuck_DLL::name() const
927{961{
@@ -929,7 +963,53 @@ const char * Chuck_DLL::name() const · 1 unmodified line
929}963}
930 964
931 965
932//const t_CKUINT Chuck_DL_Query::RESERVED_SIZE;966
967
968//-----------------------------------------------------------------------------
969// name: versionMajor()
970// desc: get version major
971//-----------------------------------------------------------------------------
972t_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//-----------------------------------------------------------------------------
987t_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//-----------------------------------------------------------------------------
1002t_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
933 1013
934//-----------------------------------------------------------------------------1014//-----------------------------------------------------------------------------
935// name: Chuck_DL_Query1015// name: Chuck_DL_Query
src/core/chuck_dl.h+18−4
@@ -604,20 +604,30 @@ public: · 603 unmodified lines
604 // get last error604 // get last error
605 const char * last_error() const;605 const char * last_error() const;
606 // unload the ckx606 // unload the ckx
607 t_CKBOOL unload( );607 t_CKBOOL unload();
608 // query the content of the dll608 // 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();
610 // is good612 // is good
611 t_CKBOOL good() const;613 t_CKBOOL good() const;
612 // name614 // name
613 const char * name() const;615 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();
614 624
615public:625public:
616 // constructor626 // constructor
617 Chuck_DLL( Chuck_Carrier * carrier, const char * xid = NULL )627 Chuck_DLL( Chuck_Carrier * carrier, const char * xid = NULL )
618 : m_handle(NULL), m_id(xid ? xid : ""),628 : m_handle(NULL), m_id(xid ? xid : ""),
619 m_query( carrier ),629 m_query( carrier ), m_done_query(FALSE), m_query_func(NULL),
620 m_done_query(FALSE), m_query_func(NULL), m_version_func(NULL)630 m_version_func(NULL), m_versionMajor(0), m_versionMinor(0)
621 { }631 { }
622 // destructor632 // destructor
623 ~Chuck_DLL() { this->unload(); }633 ~Chuck_DLL() { this->unload(); }
@@ -634,6 +644,10 @@ protected: · 10 unmodified lines
634 f_ck_declversion m_version_func;644 f_ck_declversion m_version_func;
635 f_ck_query m_query_func;645 f_ck_query m_query_func;
636 Chuck_DL_Query m_query;646 Chuck_DL_Query m_query;
647
648protected: // addition info 1.5.0.4 (ge) added
649 t_CKUINT m_versionMajor;
650 t_CKUINT m_versionMinor;
637};651};
638 652
639 653
src/core/chuck_errmsg.cpp+1−1
@@ -613,7 +613,7 @@ void EM_setlog( t_CKINT level ) · 612 unmodified lines
613 g_loglevel = level;613 g_loglevel = level;
614 614
615 // log this615 // 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] );
617}617}
618 618
619// push log619// push log
src/host/chuck_main.cpp+16−13
@@ -221,7 +221,8 @@ void usage() · 220 unmodified lines
221 CK_FPRINTF_STDERR( " srate:<N>|bufsize:<N>|bufnum:<N>|shell|empty|\n" );221 CK_FPRINTF_STDERR( " srate:<N>|bufsize:<N>|bufnum:<N>|shell|empty|\n" );
222 CK_FPRINTF_STDERR( " remote:<hostname>|port:<N>|verbose:<N>|level:<N>|\n" );222 CK_FPRINTF_STDERR( " remote:<hostname>|port:<N>|verbose:<N>|level:<N>|\n" );
223 CK_FPRINTF_STDERR( " callback|deprecate:{stop|warn|ignore}|\n" );223 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" );
225 CK_FPRINTF_STDERR( " [commands] = add|remove|replace|remove.all|status|time|kill\n" );226 CK_FPRINTF_STDERR( " [commands] = add|remove|replace|remove.all|status|time|kill\n" );
226 CK_FPRINTF_STDERR( " [+-=^] = shortcuts for add, remove, replace, status\n" );227 CK_FPRINTF_STDERR( " [+-=^] = shortcuts for add, remove, replace, status\n" );
227 version();228 version();
@@ -471,6 +472,7 @@ bool go( int argc, const char ** argv ) · 243 unmodified lines
471 t_CKINT adc_chans_before_rtaudio = adc_chans; // added 1.5.0.0472 t_CKINT adc_chans_before_rtaudio = adc_chans; // added 1.5.0.0
472 t_CKBOOL dump = FALSE;473 t_CKBOOL dump = FALSE;
473 t_CKBOOL probe = FALSE;474 t_CKBOOL probe = FALSE;
475 t_CKBOOL probe_chugs = FALSE;
474 t_CKBOOL set_priority = FALSE;476 t_CKBOOL set_priority = FALSE;
475 t_CKBOOL auto_depend = FALSE;477 t_CKBOOL auto_depend = FALSE;
476 t_CKBOOL block = FALSE;478 t_CKBOOL block = FALSE;
@@ -767,6 +769,8 @@ bool go( int argc, const char ** argv ) · 290 unmodified lines
767 }769 }
768 else if( !strcmp( argv[i], "--probe" ) )770 else if( !strcmp( argv[i], "--probe" ) )
769 probe = TRUE;771 probe = TRUE;
772 else if( !strcmp( argv[i], "--chugin-probe" ) )
773 probe_chugs = TRUE;
770 else if( !strcmp( argv[i], "--poop" ) )774 else if( !strcmp( argv[i], "--poop" ) )
771 uh();775 uh();
772 else if( !strcmp( argv[i], "--caution-to-the-wind" ) )776 else if( !strcmp( argv[i], "--caution-to-the-wind" ) )
@@ -832,9 +836,8 @@ bool go( int argc, const char ** argv ) · 59 unmodified lines
832 // probe HID devices836 // probe HID devices
833 HidInManager::probeHidIn();837 HidInManager::probeHidIn();
834 838
835 // don't exit, wait to probe chugins, which needs a ChucK instance | 1.5.0.4839 // done probe
836 // exit840 exit( 0 );
837 // exit( 0 );
838 }841 }
839 842
840 // set caution to wind843 // set caution to wind
@@ -854,7 +857,7 @@ bool go( int argc, const char ** argv ) · 13 unmodified lines
854 // set adaptive size857 // set adaptive size
855 if( adaptive_size < 0 ) adaptive_size = buffer_size;858 if( adaptive_size < 0 ) adaptive_size = buffer_size;
856 859
857 if( !files && vm_halt && !g_enable_shell )860 if( !files && vm_halt && !g_enable_shell && !probe_chugs )
858 {861 {
859 CK_FPRINTF_STDERR( "[chuck]: no input files... (try --help)\n" );862 CK_FPRINTF_STDERR( "[chuck]: no input files... (try --help)\n" );
860 exit( 1 );863 exit( 1 );
@@ -884,7 +887,7 @@ bool go( int argc, const char ** argv ) · 23 unmodified lines
884 }887 }
885 888
886 // find dac_name if appropriate (added 1.3.0.0)889 // find dac_name if appropriate (added 1.3.0.0)
887 if( dac_name.size() > 0 )890 if( !probe_chugs && dac_name.size() > 0 )
888 {891 {
889 // check with RtAudio892 // check with RtAudio
890 t_CKINT dev = ChuckAudio::device_named( audioDriver, dac_name, TRUE, FALSE );893 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
901 }904 }
902 905
903 // find adc_name if appropriate (added 1.3.0.0)906 // find adc_name if appropriate (added 1.3.0.0)
904 if( adc_name.size() > 0 )907 if( !probe_chugs && adc_name.size() > 0 )
905 {908 {
906 // check with RtAudio909 // check with RtAudio
907 t_CKINT dev = ChuckAudio::device_named( audioDriver, adc_name, FALSE, TRUE );910 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
917 }920 }
918 }921 }
919 922
920
921 //-------------------- VIRTUAL MACHINE SETUP (PART 1) -------------------------923 //-------------------- VIRTUAL MACHINE SETUP (PART 1) -------------------------
922 // instantiate a ChucK!924 // instantiate a ChucK!
923 the_chuck = new ChucK();925 the_chuck = new ChucK();
924 // set log level so things can start logging926 // set log level so things can start logging
925 the_chuck->setLogLevel( log_level );927 the_chuck->setLogLevel( log_level );
926 // log
927 EM_log( CK_LOG_SYSTEM, "booting up ChucK instance..." );
928 // push
929 EM_pushlog();
930 928
931 // set chugins parameters929 // set chugins parameters
932 the_chuck->setParam( CHUCK_PARAM_CHUGIN_ENABLE, chugin_load );930 the_chuck->setParam( CHUCK_PARAM_CHUGIN_ENABLE, chugin_load );
@@ -934,7 +932,7 @@ bool go( int argc, const char ** argv ) · 1 unmodified line
934 the_chuck->setParam( CHUCK_PARAM_USER_CHUGIN_DIRECTORIES, dl_search_path );932 the_chuck->setParam( CHUCK_PARAM_USER_CHUGIN_DIRECTORIES, dl_search_path );
935 933
936 // probe chugins | 1.5.0.4 (ge) added934 // probe chugins | 1.5.0.4 (ge) added
937 if( probe )935 if( probe_chugs )
938 {936 {
939 // ensure log level is at least SYSTEM937 // ensure log level is at least SYSTEM
940 if( the_chuck->getLogLevel() < CK_LOG_SYSTEM )938 if( the_chuck->getLogLevel() < CK_LOG_SYSTEM )
@@ -948,6 +946,11 @@ bool go( int argc, const char ** argv ) · 7 unmodified lines
948 exit( 0 );946 exit( 0 );
949 }947 }
950 948
949 // log
950 EM_log( CK_LOG_SYSTEM, "booting up ChucK instance..." );
951 // push
952 EM_pushlog();
953
951 //--------------------------- AUDIO I/O SETUP ---------------------------------954 //--------------------------- AUDIO I/O SETUP ---------------------------------
952 // log955 // log
953 EM_log( CK_LOG_SYSTEM, "initializing audio subsystem..." );956 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