aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/s3m_extractor.c
blob: c4789cef3682dd15c61fad0dd4fb14635196293f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
     This file is part of libextractor.
     Copyright (C) 2002, 2003, 2004, 2009, 2012 Vidyut Samanta and Christian Grothoff

     libextractor is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published
     by the Free Software Foundation; either version 3, or (at your
     option) any later version.

     libextractor is distributed in the hope that it will be useful, but
     WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with libextractor; see the file COPYING.  If not, write to the
     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     Boston, MA 02110-1301, USA.
 */
/**
 * @file plugins/s3m_extractor.c
 * @brief plugin to support Scream Tracker (S3M) files
 * @author Toni Ruottu
 * @author Christian Grothoff
 */
#include "platform.h"
#include "extractor.h"
#include "le_architecture.h"


LE_NETWORK_STRUCT_BEGIN
struct S3MHeader
{
  char song_name[28];
  uint8_t byte_1A;
  uint8_t file_type; /* 0x10 == ST3 module */
  uint8_t unknown1[2];
  uint16_t number_of_orders LE_PACKED; /* should be even */
  uint16_t number_of_instruments LE_PACKED;
  uint16_t number_of_patterns LE_PACKED;
  uint16_t flags LE_PACKED;
  uint16_t created_with_version LE_PACKED;
  uint16_t file_format_info LE_PACKED;
  char SCRM[4];
  uint8_t global_volume;
  uint8_t initial_speed;
  uint8_t initial_tempo;
  uint8_t master_volume;
  uint8_t ultra_click_removal;
  uint8_t default_channel_positions;
  uint8_t unknown2[8];
  uint16_t special LE_PACKED;
  uint8_t channel_settings[32];
};
LE_NETWORK_STRUCT_END


/**
 * Give meta data to LE 'proc' callback using the given LE type and value.
 *
 * @param t LE meta data type
 * @param s meta data to add
 */
#define ADD(s, t) do { if (0 != ec->proc (ec->cls, "s3m", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen (s) + 1)) return; } while (0)


/**
 * Extractor based upon Scream Tracker 3.20 spec at http://16-bits.org/s3m/
 *
 * Looks like the format was defined by the software implementation,
 * and that implementation was for little-endian platform, which means
 * that the format is little-endian.
 *
 * @param ec extraction context
 */
void
EXTRACTOR_s3m_extract_method (struct EXTRACTOR_ExtractContext *ec)
{
  void *data;
  struct S3MHeader header;
  char song_name_NT[29];

  if ((ssize_t) sizeof (header) >
      ec->read (ec->cls,
		&data,
		sizeof (header)))
    return;
  memcpy (&header, data, sizeof (header));
  if ( (0x1A != header.byte_1A) ||
       (0 != memcmp (header.SCRM, "SCRM", 4)) )
    return;
  header.number_of_orders = LE_le16toh (header.number_of_orders);
  header.number_of_instruments = LE_le16toh (header.number_of_instruments);
  header.number_of_patterns = LE_le16toh (header.number_of_patterns);
  header.flags = LE_le16toh (header.flags);
  header.created_with_version = LE_le16toh (header.created_with_version);
  header.file_format_info = LE_le16toh (header.file_format_info);
  header.special = LE_le16toh (header.special);
  memcpy (song_name_NT, header.song_name, 28);
  song_name_NT[28] = '\0';
  ADD ("audio/x-s3m", EXTRACTOR_METATYPE_MIMETYPE);
  ADD (song_name_NT, EXTRACTOR_METATYPE_TITLE);
  /* TODO: turn other header data into useful metadata (i.e. RESOURCE_TYPE).
   * Also, disabled instruments can be (and are) used to carry user-defined text.
   */
}

/* end of s3m_extractor.c */