diff options
-rw-r--r-- | gnuradio-core/src/lib/io/gr_file_source.cc | 96 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_file_source.h | 64 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_file_source.i | 2 | ||||
-rw-r--r-- | grc/blocks/gr_file_source.xml | 1 |
4 files changed, 131 insertions, 32 deletions
diff --git a/gnuradio-core/src/lib/io/gr_file_source.cc b/gnuradio-core/src/lib/io/gr_file_source.cc index 96333fa24..09f3986cd 100644 --- a/gnuradio-core/src/lib/io/gr_file_source.cc +++ b/gnuradio-core/src/lib/io/gr_file_source.cc @@ -49,24 +49,14 @@ #define OUR_O_LARGEFILE 0 #endif -gr_file_source::gr_file_source (size_t itemsize, const char *filename, bool repeat) - : gr_sync_block ("file_source", - gr_make_io_signature (0, 0, 0), - gr_make_io_signature (1, 1, itemsize)), - d_itemsize (itemsize), d_fp (0), d_repeat (repeat) +gr_file_source::gr_file_source(size_t itemsize, const char *filename, bool repeat) + : gr_sync_block("file_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize(itemsize), d_fp(0), d_new_fp (0), d_repeat(repeat), + d_updated(false) { - // we use "open" to use to the O_LARGEFILE flag - - int fd; - if ((fd = open (filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0){ - perror (filename); - throw std::runtime_error ("can't open file"); - } - - if ((d_fp = fdopen (fd, "rb")) == NULL){ - perror (filename); - throw std::runtime_error ("can't open file"); - } + open(filename, repeat); } // public constructor that returns a shared_ptr @@ -79,7 +69,11 @@ gr_make_file_source (size_t itemsize, const char *filename, bool repeat) gr_file_source::~gr_file_source () { - fclose ((FILE *) d_fp); + close(); + if(d_fp) { + fclose(d_fp); + d_fp = 0; + } } int @@ -91,6 +85,11 @@ gr_file_source::work (int noutput_items, int i; int size = noutput_items; + do_update(); // update d_fp is reqd + if(d_fp == NULL) + throw std::runtime_error("work with file not open"); + + boost::mutex::scoped_lock lock(fp_mutex); // hold for the rest of this function while (size) { i = fread(o, d_itemsize, size, (FILE *) d_fp); @@ -129,5 +128,64 @@ gr_file_source::work (int noutput_items, bool gr_file_source::seek (long seek_point, int whence) { - return fseek ((FILE *) d_fp, seek_point * d_itemsize, whence) == 0; + // obtain exclusive access for duration of this function + boost::mutex::scoped_lock lock(fp_mutex); + return fseek((FILE *) d_fp, seek_point * d_itemsize, whence) == 0; +} + +void +gr_file_source::open(const char *filename, bool repeat) +{ + // obtain exclusive access for duration of this function + boost::mutex::scoped_lock lock(fp_mutex); + + int fd; + + // we use "open" to use to the O_LARGEFILE flag + if((fd = ::open(filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0) { + perror(filename); + throw std::runtime_error("can't open file"); + } + + if(d_new_fp) { + fclose(d_new_fp); + d_new_fp = 0; + } + + if((d_new_fp = fdopen (fd, "rb")) == NULL) { + perror(filename); + ::close(fd); // don't leak file descriptor if fdopen fails + throw std::runtime_error("can't open file"); + } + + d_updated = true; + d_repeat = repeat; +} + +void +gr_file_source::close() +{ + // obtain exclusive access for duration of this function + boost::mutex::scoped_lock lock(fp_mutex); + + if(d_new_fp != NULL) { + fclose(d_new_fp); + d_new_fp = NULL; + } + d_updated = true; +} + +void +gr_file_source::do_update() +{ + if(d_updated) { + boost::mutex::scoped_lock lock(fp_mutex); // hold while in scope + + if(d_fp) + fclose(d_fp); + + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_updated = false; + } } diff --git a/gnuradio-core/src/lib/io/gr_file_source.h b/gnuradio-core/src/lib/io/gr_file_source.h index 1cc44a3b1..0478fba04 100644 --- a/gnuradio-core/src/lib/io/gr_file_source.h +++ b/gnuradio-core/src/lib/io/gr_file_source.h @@ -25,6 +25,7 @@ #include <gr_core_api.h> #include <gr_sync_block.h> +#include <boost/thread/mutex.hpp> class gr_file_source; typedef boost::shared_ptr<gr_file_source> gr_file_source_sptr; @@ -39,31 +40,68 @@ gr_make_file_source (size_t itemsize, const char *filename, bool repeat = false) class GR_CORE_API gr_file_source : public gr_sync_block { - friend GR_CORE_API gr_file_source_sptr gr_make_file_source (size_t itemsize, - const char *filename, - bool repeat); private: - size_t d_itemsize; - void *d_fp; - bool d_repeat; + size_t d_itemsize; + FILE *d_fp; + FILE *d_new_fp; + bool d_repeat; + bool d_updated; protected: - gr_file_source (size_t itemsize, const char *filename, bool repeat); + gr_file_source(size_t itemsize, const char *filename, bool repeat); + + void do_update(); + + boost::mutex fp_mutex; public: - ~gr_file_source (); + /*! + * \brief Create a file source. + * + * Opens \p filename as a source of items into a flowgraph. The data + * is expected to be in binary format, item after item. The \p + * itemsize of the block determines the conversion from bits to + * items. + * + * If \p repeat is turned on, the file will repeat the file after + * it's reached the end. + * + * \param itemsize the size of each item in the file, in bytes + * \param filename name of the file to source from + * \param repeat repeat file from start + */ + friend GR_CORE_API gr_file_source_sptr + gr_make_file_source(size_t itemsize, + const char *filename, + bool repeat); + + ~gr_file_source(); - int work (int noutput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); /*! - * \brief seek file to \p seek_point relative to \p whence + * \brief Seek file to \p seek_point relative to \p whence * * \param seek_point sample offset in file * \param whence one of SEEK_SET, SEEK_CUR, SEEK_END (man fseek) */ - bool seek (long seek_point, int whence); + bool seek(long seek_point, int whence); + + /*! + * \brief Opens a new file. + * + * \param filename name of the file to source from + * \param repeat repeat file from start + */ + void open(const char *filename, bool repeat); + + /*! + * \brief Close the file handle. + */ + void close(); + }; #endif /* INCLUDED_GR_FILE_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_source.i b/gnuradio-core/src/lib/io/gr_file_source.i index 9bf44691d..e71cef0d1 100644 --- a/gnuradio-core/src/lib/io/gr_file_source.i +++ b/gnuradio-core/src/lib/io/gr_file_source.i @@ -40,4 +40,6 @@ class gr_file_source : public gr_sync_block ~gr_file_source (); bool seek (long seek_point, int whence); + void open (const char *filename, bool repeat); + void close(); }; diff --git a/grc/blocks/gr_file_source.xml b/grc/blocks/gr_file_source.xml index fcc7a7040..5f0e16b27 100644 --- a/grc/blocks/gr_file_source.xml +++ b/grc/blocks/gr_file_source.xml @@ -9,6 +9,7 @@ <key>gr_file_source</key> <import>from gnuradio import gr</import> <make>gr.file_source($type.size*$vlen, $file, $repeat)</make> + <callback>open($file, $repeat)</callback> <param> <name>File</name> <key>file</key> |