/* --------------------------------------------------------------------------*/ /* */ /* object for getting file listings using wildcard patterns */ /* Written by Hans-Christoph Steiner */ /* */ /* Copyright (c) 2006 Hans-Christoph Steiner */ /* */ /* This program is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 3 */ /* of the License, or (at your option) any later version. */ /* */ /* See file LICENSE for further informations on licensing terms. */ /* */ /* This program is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program; if not, write to the Free Software Foundation, */ /* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* */ /* --------------------------------------------------------------------------*/ #include #ifdef _WIN32 #define _WIN32_WINNT 0x0400 #include #include #else #include #include #endif #include static char *version = "$Revision: 1.12 $"; t_int folder_list_instance_count; #define DEBUG(x) //#define DEBUG(x) x /*------------------------------------------------------------------------------ * CLASS DEF */ static t_class *folder_list_class; typedef struct _folder_list { t_object x_obj; t_symbol *x_pattern; } t_folder_list; /*------------------------------------------------------------------------------ * IMPLEMENTATION */ // TODO: regexp ~ to USERPROFILE for Windows // TODO: make FindFirstFile display when its just a dir static void folder_list_output(t_folder_list* x) { DEBUG(post("folder_list_output");); #ifdef _WIN32 WIN32_FIND_DATA findData; HANDLE hFind; DWORD errorNumber; LPVOID lpErrorMessage; char fullPathNameBuffer[MAX_PATH] = ""; char unbashBuffer[MAX_PATH] = ""; char outputBuffer[MAX_PATH] = ""; char *pathBuffer; // arg, looks perfect, but only in Windows Vista // GetFinalPathNameByHandle(hFind,fullPathNameBuffer,MAX_PATH,FILE_NAME_NORMALIZED); GetFullPathName(x->x_pattern->s_name, MAX_PATH, fullPathNameBuffer, NULL); sys_unbashfilename(fullPathNameBuffer,unbashBuffer); hFind = FindFirstFile(x->x_pattern->s_name, &findData); if (hFind == INVALID_HANDLE_VALUE) { errorNumber = GetLastError(); switch (errorNumber) { case ERROR_FILE_NOT_FOUND: case ERROR_PATH_NOT_FOUND: pd_error(x,"[folder_list] nothing found for \"%s\"",x->x_pattern->s_name); break; default: FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, errorNumber, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpErrorMessage, 0, NULL ); pd_error(x,"[folder_list] %s", (char *)lpErrorMessage); } return; } char* unbashBuffer_position = strrchr(unbashBuffer, '/'); if(unbashBuffer_position) { pathBuffer = getbytes(MAX_PATH+1); strncpy(pathBuffer, unbashBuffer, unbashBuffer_position - unbashBuffer); } do { // skip "." and ".." if( strcmp(findData.cFileName, ".") && strcmp(findData.cFileName, "..") ) { strncpy(outputBuffer, pathBuffer, MAX_PATH); strcat(outputBuffer,"/"); strcat(outputBuffer,findData.cFileName); outlet_symbol( x->x_obj.ob_outlet, gensym(outputBuffer) ); } } while (FindNextFile(hFind, &findData) != 0); FindClose(hFind); #else unsigned int i; glob_t glob_buffer; DEBUG(post("globbing %s",x->x_pattern->s_name);); switch( glob( x->x_pattern->s_name, GLOB_TILDE, NULL, &glob_buffer ) ) { case GLOB_NOSPACE: pd_error(x,"[folder_list] out of memory for \"%s\"",x->x_pattern->s_name); break; # ifdef GLOB_ABORTED case GLOB_ABORTED: pd_error(x,"[folder_list] aborted \"%s\"",x->x_pattern->s_name); break; # endif # ifdef GLOB_NOMATCH case GLOB_NOMATCH: pd_error(x,"[folder_list] nothing found for \"%s\"",x->x_pattern->s_name); break; # endif } for(i = 0; i < glob_buffer.gl_pathc; i++) outlet_symbol( x->x_obj.ob_outlet, gensym(glob_buffer.gl_pathv[i]) ); globfree( &(glob_buffer) ); #endif } static void folder_list_set(t_folder_list* x, t_symbol *s) { DEBUG(post("folder_list_set");); #ifdef _WIN32 char *patternBuffer; char envVarBuffer[MAX_PATH]; if( (s->s_name[0] == '~') && (s->s_name[1] == '/')) { patternBuffer = getbytes(MAX_PATH); strcpy(patternBuffer,"%USERPROFILE%"); strncat(patternBuffer, s->s_name + 1, MAX_PATH - 1); post("set: %s", patternBuffer); } else { patternBuffer = s->s_name; } ExpandEnvironmentStrings(patternBuffer, envVarBuffer, MAX_PATH - 2); x->x_pattern = gensym(envVarBuffer); #else // UNIX // TODO translate env vars to a full path x->x_pattern = s; #endif /* _WIN32 */ } static void folder_list_symbol(t_folder_list *x, t_symbol *s) { folder_list_set(x,s); folder_list_output(x); } static void *folder_list_new(t_symbol *s) { DEBUG(post("folder_list_new");); t_folder_list *x = (t_folder_list *)pd_new(folder_list_class); t_symbol *currentdir; char buffer[MAXPDSTRING]; if(!folder_list_instance_count) { post("[folder_list] %s",version); post("\twritten by Hans-Christoph Steiner "); post("\tcompiled on "__DATE__" at "__TIME__ " "); } folder_list_instance_count++; symbolinlet_new(&x->x_obj, &x->x_pattern); outlet_new(&x->x_obj, &s_symbol); /* set to the value from the object argument, if that exists */ if (s != &s_) { x->x_pattern = s; } else { currentdir = canvas_getcurrentdir(); strncpy(buffer,currentdir->s_name,MAXPDSTRING); strncat(buffer,"/*",MAXPDSTRING); x->x_pattern = gensym(buffer); post("setting pattern to default: %s",x->x_pattern->s_name); } return (x); } void folder_list_setup(void) { DEBUG(post("folder_list_setup");); folder_list_class = class_new(gensym("folder_list"), (t_newmethod)folder_list_new, 0, sizeof(t_folder_list), 0, A_DEFSYMBOL, 0); /* add inlet datatype methods */ class_addbang(folder_list_class,(t_method) folder_list_output); class_addsymbol(folder_list_class,(t_method) folder_list_symbol); /* add inlet message methods */ class_addmethod(folder_list_class,(t_method) folder_list_set,gensym("set"), A_DEFSYMBOL, 0); }