Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

player: add zip implementation and improve rar implementation #101

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

myQwil
Copy link
Contributor

@myQwil myQwil commented Nov 2, 2024

Improvements to rar reader:

  • better and more specific error handling
  • add arc_entry_t to reduce the amount of virtual functions
  • use std::unique_ptr so our reader always cleans up on scope exit

The zip implementation requires libarchive. Zlib is an optional requirement for decompressing
individually gzipped files within a zip. The zip reader should still work somewhat without zlib, just not in as many scenarios.

EDIT: One more change was made. Some zips contain one multi-track file like .kss along with several .m3u's, so the reader now accounts for that scenario.

- better and more specific error handling
- signatures placed in derived archive classes
- add arc_entry_t to make fewer virtual funcs necessary
- use std::unique_ptr so it always deletes on scope exit
@Wohlstand
Copy link
Collaborator

I'll try to take a look on this probably tomorrow, this week is pretty busy for me.

@sezero
Copy link
Contributor

sezero commented Nov 2, 2024

player/Archive_Reader.cpp: In member function 'const char* Zip_Reader::open_zip(const char*)':
player/Archive_Reader.cpp:108:44: error: 'archive_read_support_filter_all' was not declared in this scope
  if ( archive_read_support_filter_all( zip ) != ARCHIVE_OK
                                            ^
player/Archive_Reader.cpp: In member function 'virtual const char* Zip_Reader::open(const char*)':
player/Archive_Reader.cpp:145:52: error: 'archive_read_free' was not declared in this scope
  if ( res != ARCHIVE_EOF || archive_read_free( zip ) != ARCHIVE_OK )
                                                    ^
player/Archive_Reader.cpp: In member function 'virtual const char* Zip_Reader::next(void*, arc_entry_t*)':
player/Archive_Reader.cpp:157:2: error: 'la_int64_t' was not declared in this scope
  la_int64_t size = archive_entry_size( head );
  ^
player/Archive_Reader.cpp:158:2: error: 'la_ssize_t' was not declared in this scope
  la_ssize_t pos = 0;
  ^
player/Archive_Reader.cpp:160:2: error: 'pos' was not declared in this scope
  pos += archive_read_data( zip, bp, 3 );
  ^
player/Archive_Reader.cpp:166:32: error: invalid use of non-static member function
   if ( (err = buf.resize( size )) )
                                ^
player/Archive_Reader.cpp:168:28: error: 'memcpy' was not declared in this scope
   memcpy( &buf[0], bp, pos );
                            ^
player/Archive_Reader.cpp:171:8: error: invalid use of member function (did you forget the '()' ?)
   size = BLARGG_4CHAR(b[3], b[2], b[1], b[0]);
        ^
player/Archive_Reader.cpp:174:37: error: 'memset' was not declared in this scope
   memset( &stream, 0, sizeof stream );
                                     ^
player/Archive_Reader.cpp:178:20: error: cannot convert 'Archive_Reader::size' from type 'long int (Archive_Reader::)() const' to type 'uInt {aka unsigned int}'
   stream.avail_out = size;
                    ^
player/Archive_Reader.cpp:199:14: error: cannot convert 'Archive_Reader::size' from type 'long int (Archive_Reader::)() const' to type 'size_t {aka unsigned int}'
  entry->size = size;
              ^
player/Archive_Reader.cpp: In destructor 'virtual Zip_Reader::~Zip_Reader()':
player/Archive_Reader.cpp:205:25: error: 'archive_read_free' was not declared in this scope
  archive_read_free( zip );
                         ^

This was with gcc4.9

If I enabled unrar, two was not declared in this scope errors for memcpy and memset did not appear, so you at least need this:

--- a/player/Archive_Reader.cpp
+++ b/player/Archive_Reader.cpp
@@ -3,8 +3,8 @@
 blargg_err_t const arc_eof = "Archive: End of file";
 
-#ifdef RARDLL
-
 #include <string.h>
 
+#ifdef RARDLL
+
 static const int erar_offset = 10;
 static blargg_err_t const erar_handle = "Failed to instantiate RAR handle";

As for rest of the errors, I guess you need some new version of libarchive?? If so, you should specify it in cmake'ry (my libarchive is 2.8.3)

@Wohlstand
Copy link
Collaborator

If so, you should specify it in cmake'ry (my libarchive is 2.8.3)

Or better, polish the code to ensure it will build with older version too to maintain compatibility with older distros environments (even some of supported LTS distro versions will have a similiar older version).

@myQwil
Copy link
Contributor Author

myQwil commented Nov 3, 2024

That should hopefully take care of the unrecognized type and memset/memcpy issues.

But it sounds like there are still some functions being used which either didn't exist before or had their name changed. Also, i'm using libarchive 3.7.7-1.

@myQwil myQwil force-pushed the listable-zip branch 2 times, most recently from 8927766 to 1848cff Compare November 3, 2024 01:05
@sezero
Copy link
Contributor

sezero commented Nov 3, 2024

archive_read_free can be replaced with archive_read_finish if ARCHIVE_VERSION_NUMBER < 3000000

Don't know what to do with archive_read_support_filter_all

@myQwil
Copy link
Contributor Author

myQwil commented Nov 3, 2024

From what I can tell, a filtering feature hadn't been added yet by that version.

I think we can just leave that function call out. "filter all" seems to be the default behavior anyway, and it still works on my end when I take it out.

@sezero
Copy link
Contributor

sezero commented Nov 3, 2024

Don't know what to do with archive_read_support_filter_all

Ah, obviously, archive_read_support_filter_all can be replaced with archive_read_support_compression_all, again if ARCHIVE_VERSION_NUMBER < 3000000

So, the following patch makes it build for me:

diff --git a/player/Archive_Reader.cpp b/player/Archive_Reader.cpp
index 6423d18..a272523 100644
--- a/player/Archive_Reader.cpp
+++ b/player/Archive_Reader.cpp
@@ -102,6 +102,16 @@ static blargg_err_t const zerrs[] = {
 };
 #endif // HAVE_ZLIB_H
 
+#if (ARCHIVE_VERSION_NUMBER < 3000000)
+static inline int archive_read_free(struct archive *a) {
+	return archive_read_finish(a);
+}
+
+static inline int archive_read_support_filter_all(struct archive *a) {
+	return archive_read_support_compression_all(a);
+}
+#endif
+
 blargg_err_t Zip_Reader::open_zip( const char* path ) {
 	if ( !(zip = archive_read_new()) )
 		return zip_err_struct;

@sezero
Copy link
Contributor

sezero commented Nov 3, 2024

I think we can just leave that function call out. "filter all" seems to be the default behavior anyway, and it still works on my end when I take it out.

That'd be OK too, I guess.. (not tried though)

@myQwil
Copy link
Contributor Author

myQwil commented Nov 3, 2024

Actually, I think you're right. Looks like "filter" was just a name change from "compression"

Requires libarchive. Zlib is an optional requirement for decompressing
individually gzipped files within a zip. The zip reader should still
work somewhat without zlib, just not in as many scenarios.
@sezero
Copy link
Contributor

sezero commented Nov 3, 2024

Latest rev builds cleanly for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants