Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2007-12-20 13:27:13 +0300
committerCampbell Barton <ideasman42@gmail.com>2007-12-20 13:27:13 +0300
commit5925fe36e0a176a73e65950f7ed5eef510c12f02 (patch)
treedc047e46e29c585820cd354704d2e7dc86188435 /source/blender/blenlib/intern/bpath.c
parent0a682cb50fe46a0e4327546cb74370c8e88fa231 (diff)
Render-farm and file utils for dealing with external data.
Useful to use before sending blend files to the renderfarm. * Make all Paths Relative - makes any absolute paths relative. * Report Missing Files - creates a textblock listing all missing files. * Find Missing Files - searches a directory recursively for filenames that dont exist at their current path. Added a path looper type and functions that currently loop on image, sound, font and external library paths.
Diffstat (limited to 'source/blender/blenlib/intern/bpath.c')
-rw-r--r--source/blender/blenlib/intern/bpath.c485
1 files changed, 485 insertions, 0 deletions
diff --git a/source/blender/blenlib/intern/bpath.c b/source/blender/blenlib/intern/bpath.c
new file mode 100644
index 00000000000..598b5720b65
--- /dev/null
+++ b/source/blender/blenlib/intern/bpath.c
@@ -0,0 +1,485 @@
+/**
+ *
+ * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ *
+ * 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 2
+ * of the License, or (at your option) any later version. The Blender
+ * Foundation also sells licenses for use in proprietary software under
+ * the Blender License. See http://www.blender.org/BL/ for information
+ * about this.
+ *
+ * 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.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Campbell barton
+ *
+ * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ */
+
+#include "BLI_bpath.h"
+#include "BKE_global.h"
+#include "DNA_ID.h" /* Library */
+#include "DNA_vfont_types.h"
+#include "DNA_image_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_scene_types.h" /* to get the current frame */
+#include <stdlib.h>
+#include <string.h>
+
+#include "BKE_main.h" /* so we can access G.main->*.first */
+#include "BKE_image.h" /* so we can check the image's type */
+
+#include "blendef.h"
+#include "BKE_utildefines.h"
+
+/* for writing to a textblock */
+#include "BKE_text.h"
+#include "BLI_blenlib.h"
+#include "DNA_text_types.h"
+
+/* path/file handeling stuff */
+#ifndef WIN32
+ #include <dirent.h>
+#else
+ #include "BLI_winstuff.h"
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <math.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define FILE_MAX 240
+
+
+/* TODO - BPATH_PLUGIN, BPATH_SEQ */
+enum BPathTypes {
+ BPATH_IMAGE = 0,
+ BPATH_SOUND,
+ BPATH_FONT,
+ BPATH_LIB,
+
+ BPATH_DONE
+};
+
+
+void BLI_bpathIterator_init( struct BPathIterator *bpi ) {
+ bpi->type = BPATH_IMAGE;
+ bpi->data = NULL;
+ BLI_bpathIterator_step(bpi);
+}
+
+char* BLI_bpathIterator_getPath( struct BPathIterator *bpi) {
+ return bpi->path;
+}
+void BLI_bpathIterator_copyPathExpanded( struct BPathIterator *bpi, char *path_expanded) {
+ char *filepath, *libpath;
+
+ filepath = BLI_bpathIterator_getPath(bpi);
+ libpath = BLI_bpathIterator_getLib(bpi);
+
+ BLI_strncpy(path_expanded, filepath, FILE_MAXDIR*2);
+
+ if (libpath) { /* check the files location relative to its library path */
+ BLI_convertstringcode(path_expanded, libpath, G.scene->r.cfra);
+ } else { /* local data, use the blend files path */
+ BLI_convertstringcode(path_expanded, G.sce, G.scene->r.cfra);
+ }
+}
+char* BLI_bpathIterator_getLib( struct BPathIterator *bpi) {
+ return bpi->lib;
+}
+char* BLI_bpathIterator_getName( struct BPathIterator *bpi) {
+ return bpi->name;
+}
+int BLI_bpathIterator_getType( struct BPathIterator *bpi) {
+ return bpi->type;
+}
+int BLI_bpathIterator_getPathMaxLen( struct BPathIterator *bpi) {
+ return bpi->len;
+}
+
+/* gets the first or the next image that has a path - not a viewer node or generated image */
+static struct Image *ima_getpath__internal(struct Image *ima, int step_next) {
+ if (ima==NULL)
+ return NULL;
+
+ if (step_next)
+ ima = ima->id.next;
+
+ while (ima) {
+ if (ima->packedfile==NULL && ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE))
+ break;
+ /* image is not a image with a path, skip it */
+ ima = ima->id.next;
+ }
+ return ima;
+}
+
+static struct VFont *vf_getpath__internal(struct VFont *vf, int step_next) {
+ if (vf==NULL)
+ return NULL;
+
+ if (step_next)
+ vf = vf->id.next;
+
+ while (vf) {
+ if (vf->packedfile==NULL && BLI_streq(vf->name, "<builtin>")==0) {
+ break;
+ }
+
+ /* font with no path, skip it */
+ vf = vf->id.next;
+ }
+ return vf;
+}
+
+static struct bSound *snd_getpath__internal(struct bSound *snd, int step_next) {
+ if (snd==NULL)
+ return NULL;
+
+ if (step_next)
+ snd = snd->id.next;
+
+ while (snd) {
+ if (snd->packedfile==NULL) {
+ break;
+ }
+
+ /* font with no path, skip it */
+ snd = snd->id.next;
+ }
+ return snd;
+}
+
+void BLI_bpathIterator_step( struct BPathIterator *bpi) {
+ while (bpi->type != BPATH_DONE) {
+
+ if ((bpi->type) == BPATH_IMAGE) {
+ /*if (bpi->data) bpi->data = ((ID *)bpi->data)->next;*/
+ if (bpi->data) bpi->data = ima_getpath__internal( (Image *)bpi->data, 1 ); /* must skip images that have no path */
+ else bpi->data = ima_getpath__internal(G.main->image.first, 0);
+
+ if (bpi->data) {
+ /* get the path info from this datatype */
+ Image *ima = (Image *)bpi->data;
+
+ bpi->lib = ima->id.lib ? ima->id.lib->filename : NULL;
+ bpi->path = ima->name;
+ bpi->name = ima->id.name+2;
+ bpi->len = sizeof(ima->name);
+
+ /* we are done, advancing to the next item, this type worked fine */
+ break;
+
+ } else {
+ bpi->type+=1; /* advance to the next type */
+ }
+
+
+ } else if ((bpi->type) == BPATH_SOUND) {
+ if (bpi->data) bpi->data = snd_getpath__internal( (bSound *)bpi->data, 1 ); /* must skip images that have no path */
+ else bpi->data = snd_getpath__internal(G.main->sound.first, 0);
+
+ if (bpi->data) {
+ /* get the path info from this datatype */
+ bSound *snd = (bSound *)bpi->data;
+
+ bpi->lib = snd->id.lib ? snd->id.lib->filename : NULL;
+ bpi->path = snd->sample->name;
+ bpi->name = snd->id.name+2;
+ bpi->len = sizeof(snd->sample->name);
+
+ /* we are done, advancing to the next item, this type worked fine */
+ break;
+ } else {
+ bpi->type+=1; /* advance to the next type */
+ }
+
+
+ } else if ((bpi->type) == BPATH_FONT) {
+
+ if (bpi->data) bpi->data = vf_getpath__internal( (VFont *)bpi->data, 1 );
+ else bpi->data = vf_getpath__internal( G.main->vfont.first, 0 );
+
+ if (bpi->data) {
+ /* get the path info from this datatype */
+ VFont *vf = (VFont *)bpi->data;
+
+ bpi->lib = vf->id.lib ? vf->id.lib->filename : NULL;
+ bpi->path = vf->name;
+ bpi->name = vf->id.name+2;
+ bpi->len = sizeof(vf->name);
+
+ /* we are done, advancing to the next item, this type worked fine */
+ break;
+ } else {
+ bpi->type+=1; /* advance to the next type */
+ }
+
+
+ } else if ((bpi->type) == BPATH_LIB) {
+
+ if (bpi->data) bpi->data = ((ID *)bpi->data)->next;
+ else bpi->data = G.main->library.first;
+
+ if (bpi->data) {
+ /* get the path info from this datatype */
+ Library *lib = (Library *)bpi->data;
+
+ bpi->lib = NULL;
+ bpi->path = lib->name;
+ bpi->name = NULL;
+ bpi->len = sizeof(lib->name);
+
+ /* we are done, advancing to the next item, this type worked fine */
+ break;
+ } else {
+ bpi->type+=1; /* advance to the next type */
+ }
+ }
+ }
+}
+
+int BLI_bpathIterator_isDone( struct BPathIterator *bpi) {
+ return bpi->type==BPATH_DONE;
+}
+
+/* include the path argument */
+static void bpathToText(Text *btxt, struct BPathIterator *bpi)
+{
+ char *name;
+ char path_expanded[FILE_MAXDIR*2];
+
+ switch(BLI_bpathIterator_getType(bpi)) {
+ case BPATH_IMAGE:
+ txt_insert_buf( btxt, "Image \"" );
+ break;
+ case BPATH_SOUND:
+ txt_insert_buf( btxt, "Sound \"" );
+ break;
+ case BPATH_FONT:
+ txt_insert_buf( btxt, "Font \"" );
+ break;
+ case BPATH_LIB:
+ txt_insert_buf( btxt, "Library \"" );
+ break;
+ default:
+ txt_insert_buf( btxt, "Unknown \"" );
+ break;
+ }
+
+ name = BLI_bpathIterator_getName(bpi);
+
+ if (name) {
+ txt_insert_buf( btxt, name );
+ }
+ txt_insert_buf( btxt, "\" " );
+
+ BLI_bpathIterator_copyPathExpanded(bpi, path_expanded);
+
+ txt_insert_buf( btxt, path_expanded );
+ txt_insert_buf( btxt, "\n" );
+ txt_move_eof( btxt, 0 );
+}
+
+/* high level function */
+Text *checkMissingFiles(void) {
+ Text *btxt = NULL;
+ struct BPathIterator bpi;
+
+ /* be sure there is low chance of the path being too short */
+ char filepath_expanded[FILE_MAXDIR*2];
+ char *filepath, *libpath;
+ int files_missing = 0;
+
+ BLI_bpathIterator_init(&bpi);
+ while (!BLI_bpathIterator_isDone(&bpi)) {
+ filepath = BLI_bpathIterator_getPath(&bpi);
+ libpath = BLI_bpathIterator_getLib(&bpi);
+
+ BLI_bpathIterator_copyPathExpanded( &bpi, filepath_expanded );
+
+ if (!BLI_exists(filepath_expanded)) {
+ if (!btxt)
+ btxt = add_empty_text( "missing_files.txt" );
+
+ bpathToText(btxt, &bpi);
+ files_missing = 1;
+ }
+ BLI_bpathIterator_step(&bpi);
+ }
+ return btxt;
+}
+
+/* dont log any errors at the moment, should probably do this */
+void makeFilesRelative(int *tot, int *changed, int *failed, int *linked) {
+ struct BPathIterator bpi;
+ char *filepath, *libpath;
+
+ /* be sure there is low chance of the path being too short */
+ char filepath_relative[(FILE_MAXDIR * 2) + FILE_MAXFILE];
+
+ *tot = *changed = *failed = *linked = 0;
+
+ BLI_bpathIterator_init(&bpi);
+ while (!BLI_bpathIterator_isDone(&bpi)) {
+ filepath = BLI_bpathIterator_getPath(&bpi);
+ libpath = BLI_bpathIterator_getLib(&bpi);
+
+ if(strncmp(filepath, "//", 2)==0) {
+ if (libpath) { /* cant make relative if we are kibrary - TODO, LOG THIS */
+ (*linked)++;
+ } else { /* local data, use the blend files path */
+ BLI_strncpy(filepath_relative, filepath, sizeof(filepath_relative));
+ BLI_makestringcode(G.sce, filepath_relative);
+ if (BLI_bpathIterator_getPathMaxLen(&bpi) < strlen(filepath_relative)) {
+ (*failed)++;
+ } else {
+ /* safe to to check the length */
+ if(strncmp(filepath_relative, "//", 2)==0) {
+ (*failed)++;
+ } else {
+ strcpy(filepath, filepath_relative);
+ (*changed)++;
+ }
+ }
+ }
+ }
+
+ BLI_bpathIterator_step(&bpi);
+ (*tot)++;
+ }
+}
+
+/* find this file recursively, use the biggest file so thumbnails dont get used by mistake
+ - dir: subdir to search
+ - filename: set this filename
+ - filesize: filesize for the file
+*/
+#define MAX_RECUR 16
+static int findFileRecursive(char *filename_new, const char *dirname, const char *filename, int *filesize, int *recur_depth)
+{
+ /* file searching stuff */
+ DIR *dir;
+ int file = 0;
+ struct dirent *de;
+ struct stat status;
+ char path[FILE_MAX];
+ int size;
+
+ printf("DIR %s\n", dirname);
+
+ dir = opendir(dirname);
+
+ if (dir==0)
+ return 0;
+
+ if (*filesize == -1)
+ *filesize = 0; /* dir opened fine */
+
+ while ((de = readdir(dir)) != NULL) {
+
+ if (strncmp(".", de->d_name, 2)==0 || strncmp("..", de->d_name, 3)==0)
+ continue;
+
+ BLI_join_dirfile(path, dirname, de->d_name);
+
+ if (stat(path, &status) != 0)
+ continue; /* cant stat, dont bother with this file, could print debug info here */
+
+ if (S_ISREG(status.st_mode)) { /* is file */
+ if (strncmp(filename, de->d_name, FILE_MAX)==0) { /* name matches */
+ /* open the file to read its size */
+ file = open(path, O_BINARY|O_RDONLY);
+ if (file >=0 ) {
+ size = BLI_filesize(file);
+ if (size > *filesize) { /* find the biggest file */
+ *filesize = size;
+ BLI_strncpy(filename_new, path, FILE_MAX);
+ }
+ close(file);
+ }
+ }
+ } else if (S_ISDIR(status.st_mode)) { /* is subdir */
+ if (*recur_depth <= MAX_RECUR) {
+ (*recur_depth)++;
+ findFileRecursive(filename_new, path, filename, filesize, recur_depth);
+ (*recur_depth)--;
+ }
+ }
+ }
+ closedir(dir);
+ return 1;
+}
+
+/* high level function - call from fileselector */
+void findMissingFiles(char *str) {
+ struct BPathIterator bpi;
+
+ /* be sure there is low chance of the path being too short */
+ char filepath_expanded[FILE_MAXDIR*2];
+ char *filepath, *libpath;
+ int filesize, recur_depth;
+
+ char dirname[FILE_MAX], filename[FILE_MAX], filename_new[FILE_MAX], dummyname[FILE_MAX];
+
+ BLI_split_dirfile(str, dirname, dummyname);
+
+ BLI_bpathIterator_init(&bpi);
+
+ while (!BLI_bpathIterator_isDone(&bpi)) {
+ filepath = BLI_bpathIterator_getPath(&bpi);
+ libpath = BLI_bpathIterator_getLib(&bpi);
+
+ if (libpath==NULL) {
+
+ BLI_bpathIterator_copyPathExpanded( &bpi, filepath_expanded );
+
+ if (!BLI_exists(filepath_expanded)) {
+ /* can the dir be opened? */
+ filesize = -1;
+ recur_depth = 0;
+ BLI_split_dirfile(filepath, dummyname, filename); /* the file to find */
+
+ findFileRecursive(filename_new, dirname, filename, &filesize, &recur_depth);
+ if (filesize == -1) { /* could not open dir */
+ printf("Could not open dir \"%s\"\n", dirname);
+ return;
+ }
+
+ if (filesize > 0) {
+
+ if (BLI_bpathIterator_getPathMaxLen( &bpi ) < strlen(filename_new)) {
+ printf("cannot set path \"%s\" too long!", filename_new);
+ } else {
+ /* copy the found path into the old one */
+ if (G.relbase_valid)
+ BLI_makestringcode(G.sce, filename_new);
+
+ strcpy( BLI_bpathIterator_getPath( &bpi ), filename_new );
+ }
+ }
+ }
+ }
+ BLI_bpathIterator_step(&bpi);
+ }
+}