Support libsndfile’s virtual file interface#1
Conversation
…/libsndfile/api.html#open_virtual . * Pass a file-like object and set virtual_io=True in the constructor * If the file-like object represents a stream of data such that seeking would be prohibitive, set stream=True. The file-like object must implement its own __len__ in this case.
|
Awesome! This is very cool! Thank you so much for contributing this! I have a few questions though, which I annotated in your commit. I would be grateful if you could comment on those. |
|
I will try to do a bit more on this tonight; this is my first foray into using cffi. I agree about the |
|
I tried this on my own machine, and there was a weird issue: It wouldn't call the Do you have any idea what might be causing this behavior? Apart from that, it works great though! Would you be willing to update the README as well? |
|
By the way, Python3 requires quite a different example code than what you wrote: |
* Regular files continue to use `seek`/`tell` * Streams are expected to either set `_length` directly, or implement `__len__`
|
Abusing I also updated the README with your example (since yours works on 2.x as well, I just used it). I included an example of an HTTP request as well. |
|
OK, I like it! If you want to, we can merge it like this! However, I just had an idea: In the However, this is Python after all, so we don't actually need to use the As I said though, I think the current solution is good enough for a merge. Just tell me if you want to merge now or try to implement the callbacks as dynamically created functions first. Again, thank you very very much for your help! I truly appreciate it! |
|
I can look at converting to dynamic functions. I might have to rip out the streaming stuff; I just ran some tests, and it appears that |
…ss around a `user_data` pointer.
|
@bastibe: Is this what you were thinking of? |
|
Yes, very much so! I like it! See comments in the source code for more elaboration. |
|
If you want to just merge at any point, I can take it from there. I fear that I'm asking too much... |
|
Okay, I will take a look at splitting it out to a distinct method. Also, I think I'm going to remove the |
…wind the file object’s position.
* Move file object size logic into `vio_get_filelen` callback
|
Unfortunately, with these changes I'm getting a segfault when using the 2nd example from the README (HTTP request decoding): In [1]: from io import BytesIO
In [2]: from pysoundfile import SoundFile
In [3]: import requests
In [4]: fObj = BytesIO()
In [5]: response = requests.get('http://example.com/my.flac', stream=True)
In [6]: for data in response.iter_content(4096):
...: if data:
...: fObj.write(data)
...:
In [7]: fObj.seek(0)
Out[7]: 0L
flac = SoundFile(fObj, virtual_io=True)
In [8]: flac = SoundFile(fObj, virtual_io=True)
In [9]: flac_frames = flac.read(1024)
zsh: segmentation fault ipython |
|
Seems to be one of my test files. If I copy it locally and use the first example, I get the same segfault. However, it worked fine before these changes. |
|
I think the thing is that the CFFI does not increment the reference counts of objects, so if the only place you store something in is a CFFI object, it will get garbage collected. In your code, this is currently happeing in two places: I would propose to save The CFFI documentation has this example: |
passed to `SF_VIRTUAL_IO*`.
|
Looks like you were right; I'm no longer seeing the segfaults with this version. |
|
I think this is looking merge ready. Thanks for helping me fumble through |
|
Thank you very much for contributing this code! It is already up on PyPi and I will update the binary installers soon. |
Add the number of samples to the `info` class.
Add type hints to all public methods, functions and classes.
Documented here: http://www.mega-nerd.com/libsndfile/api.html#open_virtual .
I have need of being able to decode FLAC files from memory, so I added support for the virtual file interface in libsndfile.
set stream=True. The file-like object must implement its own
__len__in this case.This allows you to do the following: