summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gnuradio-core/src/lib/io/gr_file_source.cc96
-rw-r--r--gnuradio-core/src/lib/io/gr_file_source.h64
-rw-r--r--gnuradio-core/src/lib/io/gr_file_source.i2
-rw-r--r--grc/blocks/gr_file_source.xml1
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>