diff options
-rw-r--r-- | gr-blocks/grc/blocks_file_source.xml | 1 | ||||
-rw-r--r-- | gr-blocks/include/blocks/file_source.h | 28 | ||||
-rw-r--r-- | gr-blocks/lib/file_source_impl.cc | 98 | ||||
-rw-r--r-- | gr-blocks/lib/file_source_impl.h | 13 |
4 files changed, 114 insertions, 26 deletions
diff --git a/gr-blocks/grc/blocks_file_source.xml b/gr-blocks/grc/blocks_file_source.xml index 753465bb3..7ac573f2d 100644 --- a/gr-blocks/grc/blocks_file_source.xml +++ b/gr-blocks/grc/blocks_file_source.xml @@ -9,6 +9,7 @@ <key>blocks_file_source</key> <import>from gnuradio import blocks</import> <make>blocks.file_source($type.size*$vlen, $file, $repeat)</make> + <callback>open($file, $repeat)</callback> <param> <name>File</name> <key>file</key> diff --git a/gr-blocks/include/blocks/file_source.h b/gr-blocks/include/blocks/file_source.h index 6207cdf70..1a12aa905 100644 --- a/gr-blocks/include/blocks/file_source.h +++ b/gr-blocks/include/blocks/file_source.h @@ -40,6 +40,21 @@ namespace gr { // gr::blocks::file_source::sptr typedef boost::shared_ptr<file_source> sptr; + /*! + * \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 + */ static sptr make(size_t itemsize, const char *filename, bool repeat = false); /*! @@ -49,6 +64,19 @@ namespace gr { * \param whence one of SEEK_SET, SEEK_CUR, SEEK_END (man fseek) */ virtual bool seek(long seek_point, int whence) = 0; + + /*! + * \brief Opens a new file. + * + * \param filename name of the file to source from + * \param repeat repeat file from start + */ + virtual void open(const char *filename, bool repeat) = 0; + + /*! + * \brief Close the file handle. + */ + virtual void close() = 0; }; } /* namespace blocks */ diff --git a/gr-blocks/lib/file_source_impl.cc b/gr-blocks/lib/file_source_impl.cc index 0d20827b7..ed1f50c43 100644 --- a/gr-blocks/lib/file_source_impl.cc +++ b/gr-blocks/lib/file_source_impl.cc @@ -54,39 +54,87 @@ namespace gr { file_source::sptr file_source::make(size_t itemsize, const char *filename, bool repeat) { - return gnuradio::get_initial_sptr(new file_source_impl(itemsize, filename, repeat)); + return gnuradio::get_initial_sptr + (new file_source_impl(itemsize, filename, repeat)); } file_source_impl::file_source_impl(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) + 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 + open(filename, repeat); + } + + file_source_impl::~file_source_impl() + { + fclose ((FILE*)d_fp); + } + + bool + file_source_impl::seek(long seek_point, int whence) + { + return fseek((FILE*)d_fp, seek_point *d_itemsize, whence) == 0; + } + + + void + file_source_impl::open(const char *filename, bool repeat) + { + // obtain exclusive access for duration of this function + boost::mutex::scoped_lock lock(fp_mutex); 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"); + // 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_fp = fdopen (fd, "rb")) == NULL) { + 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; } - file_source_impl::~file_source_impl() + void + file_source_impl::close() { - fclose ((FILE *) d_fp); + // 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; } - - bool - file_source_impl::seek(long seek_point, int whence) + + void + file_source_impl::do_update() { - return fseek ((FILE *) d_fp, seek_point *d_itemsize, whence) == 0; + 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; + } } int @@ -94,37 +142,41 @@ namespace gr { gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - char *o = (char *) output_items[0]; + char *o = (char*)output_items[0]; int i; int size = noutput_items; - while (size) { - i = fread(o, d_itemsize, size, (FILE *) d_fp); + 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); size -= i; o += i * d_itemsize; - if (size == 0) // done + if(size == 0) // done break; - if (i > 0) // short read, try again + if(i > 0) // short read, try again continue; // We got a zero from fread. This is either EOF or error. In // any event, if we're in repeat mode, seek back to the beginning // of the file and try again, else break - - if (!d_repeat) + if(!d_repeat) break; - if (fseek ((FILE *) d_fp, 0, SEEK_SET) == -1) { + if(fseek ((FILE *) d_fp, 0, SEEK_SET) == -1) { fprintf(stderr, "[%s] fseek failed\n", __FILE__); exit(-1); } } - if (size > 0) { // EOF or error - if (size == noutput_items) // we didn't read anything; say we're done + if(size > 0) { // EOF or error + if(size == noutput_items) // we didn't read anything; say we're done return -1; return noutput_items - size; // else return partial result } diff --git a/gr-blocks/lib/file_source_impl.h b/gr-blocks/lib/file_source_impl.h index c35d563d1..600fe80ab 100644 --- a/gr-blocks/lib/file_source_impl.h +++ b/gr-blocks/lib/file_source_impl.h @@ -31,15 +31,22 @@ namespace gr { class BLOCKS_API file_source_impl : public file_source { 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; + boost::mutex fp_mutex; + void do_update(); + public: file_source_impl(size_t itemsize, const char *filename, bool repeat); ~file_source_impl(); bool seek(long seek_point, int whence); + void open(const char *filename, bool repeat); + void close(); int work(int noutput_items, gr_vector_const_void_star &input_items, |