1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <zircon/assert.h>
8 #include <fbl/auto_call.h>
9 #include <fbl/algorithm.h>
10 #include <lib/fdio/io.h>
11 #include <stdio.h>
12 
13 #include "wav-source.h"
14 
15 constexpr uint32_t WAVCommon::RIFF_FOUR_CC;
16 constexpr uint32_t WAVCommon::WAVE_FOUR_CC;
17 constexpr uint32_t WAVCommon::FMT_FOUR_CC;
18 constexpr uint32_t WAVCommon::DATA_FOUR_CC;
19 
20 constexpr uint16_t WAVCommon::FORMAT_UNKNOWN;
21 constexpr uint16_t WAVCommon::FORMAT_LPCM;
22 constexpr uint16_t WAVCommon::FORMAT_MSFT_ADPCM;
23 constexpr uint16_t WAVCommon::FORMAT_IEEE_FLOAT;
24 constexpr uint16_t WAVCommon::FORMAT_MSFT_ALAW;
25 constexpr uint16_t WAVCommon::FORMAT_MSFT_MULAW;
26 
Initialize(const char * filename,InitMode mode)27 zx_status_t WAVCommon::Initialize(const char* filename, InitMode mode) {
28     if (fd_ >= 0) {
29         printf("Failed to initialize WAVCommon for \"%s\", already initialized\n", filename);
30         return ZX_ERR_BAD_STATE;
31     }
32 
33     int flags = (mode == InitMode::SOURCE)
34               ? O_RDONLY
35               : O_RDWR | O_CREAT;
36     fd_ = ::open(filename, flags);
37     if (fd_ < 0) {
38         printf("Failed to open \"%s\" (res %d)\n", filename, fd_);
39         return static_cast<zx_status_t>(fd_);
40     }
41 
42     return ZX_OK;
43 }
44 
Close()45 void WAVCommon::Close() {
46     if (fd_ >= 0) {
47         ::close(fd_);
48         fd_ = -1;
49     }
50 }
51 
Read(void * buf,size_t len)52 zx_status_t WAVCommon::Read(void* buf, size_t len) {
53     if (fd_ < 0) return ZX_ERR_BAD_STATE;
54 
55     ssize_t res = ::read(fd_, buf, len);
56     if (res < 0) {
57         printf("Read error (errno %d)\n", errno);
58         return static_cast<zx_status_t>(errno);
59     }
60 
61     if (static_cast<size_t>(res) != len) {
62         printf("Short read error (%zd < %zu)\n", res, len);
63         return ZX_ERR_IO;
64     }
65 
66     return ZX_OK;
67 }
68 
Write(const void * buf,size_t len)69 zx_status_t WAVCommon::Write(const void* buf, size_t len) {
70     if (fd_ < 0) return ZX_ERR_BAD_STATE;
71 
72     ssize_t res = ::write(fd_, buf, len);
73     if (res < 0) {
74         printf("Write error (errno %d)\n", errno);
75         return static_cast<zx_status_t>(errno);
76     }
77 
78     if (static_cast<size_t>(res) != len) {
79         printf("Short write error (%zd < %zu)\n", res, len);
80         return ZX_ERR_IO;
81     }
82 
83     return ZX_OK;
84 }
85 
Seek(off_t abs_pos)86 zx_status_t WAVCommon::Seek(off_t abs_pos) {
87     if (fd_ < 0) return ZX_ERR_BAD_STATE;
88     if (abs_pos < 0) return ZX_ERR_INVALID_ARGS;
89 
90     off_t res = ::lseek(fd_, abs_pos, SEEK_SET);
91     if (res < 0) {
92         printf("Seek error (errno %d)\n", errno);
93         return static_cast<zx_status_t>(errno);
94     }
95 
96     if (res != abs_pos) {
97         printf("Failed to see to target (target %zd, got %zd)\n",
98                 static_cast<ssize_t>(abs_pos),
99                 static_cast<ssize_t>(res));
100         return ZX_ERR_IO;
101     }
102 
103     return ZX_OK;
104 }
105